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.
- package/dist/cli/index.js +290 -288
- package/dist/cli-node/index.js +290 -288
- package/dist/index.js +1675 -1657
- package/dist/skills/debugging/SKILL.md +2 -0
- package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
- package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/dist/skills/debugging/references/runtimes/go.md +15 -1
- package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/dist/skills/debugging/references/runtimes/node.md +25 -0
- package/dist/skills/debugging/references/runtimes/python.md +13 -0
- package/dist/skills/debugging/references/runtimes/rust.md +41 -0
- package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
- package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/dist/skills/debugging/references/tools/dap.md +103 -0
- package/dist/skills/debugging/references/tools/frida.md +193 -0
- package/dist/tools/delegate-task/types.d.ts +3 -0
- package/dist/tui.js +131 -147
- package/package.json +18 -15
- package/packages/lsp-core/src/index.ts +1 -0
- package/packages/lsp-core/src/lsp/client-wrapper.ts +25 -5
- package/packages/lsp-core/src/lsp/client.ts +26 -0
- package/packages/lsp-core/src/lsp/connection.ts +16 -0
- package/packages/lsp-core/src/lsp/constants.ts +1 -0
- package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
- package/packages/lsp-core/src/lsp/format-document.ts +90 -0
- package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
- package/packages/lsp-core/src/lsp/manager.ts +34 -1
- package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
- package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
- package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
- package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
- package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
- package/packages/lsp-core/src/lsp/transport.ts +9 -0
- package/packages/lsp-core/src/lsp/types.ts +8 -0
- package/packages/lsp-core/src/tool-surface.test.ts +13 -1
- package/packages/lsp-core/src/tools/definitions.ts +14 -0
- package/packages/lsp-core/src/tools/format.test.ts +56 -0
- package/packages/lsp-core/src/tools/format.ts +56 -0
- package/packages/lsp-core/src/tools/index.ts +1 -0
- package/packages/lsp-core/src/tools/types.ts +10 -0
- package/packages/lsp-daemon/dist/cli.js +432 -144
- package/packages/lsp-daemon/dist/client.d.ts +10 -0
- package/packages/lsp-daemon/dist/client.js +401 -107
- package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
- package/packages/lsp-daemon/dist/daemon-client.js +3 -0
- package/packages/lsp-daemon/dist/index.js +395 -107
- package/packages/lsp-daemon/package.json +1 -1
- package/packages/lsp-tools-mcp/dist/cli.js +384 -99
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +53 -0
- package/packages/lsp-tools-mcp/dist/mcp.js +384 -99
- package/packages/lsp-tools-mcp/dist/tools.js +385 -99
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -2
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +69 -35
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +21 -2
- package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +404 -121
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +3 -3
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +3 -3
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +4 -4
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +30 -15
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +30 -15
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +22 -10
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/model-catalog.json +3 -3
- package/packages/omo-codex/plugin/package-lock.json +13 -13
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +38 -23
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
- package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
- package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
|
@@ -5,7 +5,7 @@ import { argv, stderr } from "node:process";
|
|
|
5
5
|
|
|
6
6
|
// src/proxy.ts
|
|
7
7
|
import { existsSync as existsSync13, realpathSync as realpathSync6 } from "node:fs";
|
|
8
|
-
import { basename as basename4, delimiter as delimiter4, dirname as
|
|
8
|
+
import { basename as basename4, delimiter as delimiter4, dirname as dirname11, isAbsolute as isAbsolute6 } from "node:path";
|
|
9
9
|
|
|
10
10
|
// ../mcp-stdio-core/src/record.ts
|
|
11
11
|
function isPlainRecord(value) {
|
|
@@ -320,7 +320,7 @@ function createIdleTimer(idleTimeoutMs, log, onTimeout) {
|
|
|
320
320
|
}
|
|
321
321
|
// ../lsp-core/src/lsp/client-wrapper.ts
|
|
322
322
|
import { existsSync as existsSync10, realpathSync as realpathSync5, statSync as statSync3 } from "node:fs";
|
|
323
|
-
import { basename as basename3, dirname as
|
|
323
|
+
import { basename as basename3, dirname as dirname8, join as join5, resolve as resolve8 } from "node:path";
|
|
324
324
|
|
|
325
325
|
// ../lsp-core/src/request-context.ts
|
|
326
326
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -592,6 +592,7 @@ var DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
592
592
|
var REQUEST_TIMEOUT_MS = 15000;
|
|
593
593
|
var INIT_TIMEOUT_MS = 60000;
|
|
594
594
|
var IDLE_TIMEOUT_MS = 5 * 60000;
|
|
595
|
+
var MAX_RESIDENT_CLIENTS = 6;
|
|
595
596
|
var REAPER_INTERVAL_MS = 60000;
|
|
596
597
|
var STOP_HARD_KILL_TIMEOUT_MS = 5000;
|
|
597
598
|
var STOP_SIGKILL_GRACE_MS = 1000;
|
|
@@ -1117,6 +1118,7 @@ class LspClientTransport {
|
|
|
1117
1118
|
this.diagnosticsStore = new Map;
|
|
1118
1119
|
this.workspaceApplyEditHandler = null;
|
|
1119
1120
|
this.diagnosticPullSupported = false;
|
|
1121
|
+
this.documentFormattingSupported = false;
|
|
1120
1122
|
this.requestTimeoutMs = timeouts.requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
1121
1123
|
this.initializeTimeoutMs = timeouts.initializeTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
1122
1124
|
}
|
|
@@ -1138,6 +1140,12 @@ class LspClientTransport {
|
|
|
1138
1140
|
isDiagnosticPullSupported() {
|
|
1139
1141
|
return this.diagnosticPullSupported;
|
|
1140
1142
|
}
|
|
1143
|
+
setDocumentFormattingSupported(supported) {
|
|
1144
|
+
this.documentFormattingSupported = supported;
|
|
1145
|
+
}
|
|
1146
|
+
isDocumentFormattingSupported() {
|
|
1147
|
+
return this.documentFormattingSupported;
|
|
1148
|
+
}
|
|
1141
1149
|
handlePublishDiagnostics(params) {
|
|
1142
1150
|
this.diagnosticsStore.set(params.uri, [...params.diagnostics]);
|
|
1143
1151
|
}
|
|
@@ -1351,6 +1359,14 @@ function supportsDiagnosticPull(capabilities) {
|
|
|
1351
1359
|
return false;
|
|
1352
1360
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
1353
1361
|
}
|
|
1362
|
+
function supportsDocumentFormatting(capabilities) {
|
|
1363
|
+
if (capabilities === undefined)
|
|
1364
|
+
return false;
|
|
1365
|
+
const provider = capabilities.documentFormattingProvider;
|
|
1366
|
+
if (provider === undefined || provider === null || provider === false)
|
|
1367
|
+
return false;
|
|
1368
|
+
return provider === true || typeof provider === "object";
|
|
1369
|
+
}
|
|
1354
1370
|
|
|
1355
1371
|
class LspClientConnection extends LspClientTransport {
|
|
1356
1372
|
async initialize() {
|
|
@@ -1367,6 +1383,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1367
1383
|
references: {},
|
|
1368
1384
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
1369
1385
|
publishDiagnostics: {},
|
|
1386
|
+
formatting: { dynamicRegistration: false },
|
|
1370
1387
|
rename: {
|
|
1371
1388
|
prepareSupport: true,
|
|
1372
1389
|
prepareSupportDefaultBehavior: 1
|
|
@@ -1408,6 +1425,7 @@ class LspClientConnection extends LspClientTransport {
|
|
|
1408
1425
|
initializationOptions: this.server.initialization
|
|
1409
1426
|
}, { timeoutMs: this.initializeTimeoutMs });
|
|
1410
1427
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
1428
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
1411
1429
|
await this.sendNotification("initialized", {});
|
|
1412
1430
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
1413
1431
|
settings: { json: { validate: { enable: true } } }
|
|
@@ -2992,6 +3010,18 @@ class LspClient extends LspClientConnection {
|
|
|
2992
3010
|
textDocument: { uri: pathToFileURL3(absPath).href }
|
|
2993
3011
|
}, options);
|
|
2994
3012
|
}
|
|
3013
|
+
async formatDocument(filePath, options, signal) {
|
|
3014
|
+
if (!this.isDocumentFormattingSupported())
|
|
3015
|
+
return null;
|
|
3016
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
3017
|
+
await this.openFile(absPath);
|
|
3018
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
3019
|
+
const edits = await this.sendRequest("textDocument/formatting", {
|
|
3020
|
+
textDocument: { uri: pathToFileURL3(absPath).href },
|
|
3021
|
+
options
|
|
3022
|
+
}, requestOptions);
|
|
3023
|
+
return edits ?? [];
|
|
3024
|
+
}
|
|
2995
3025
|
async workspaceSymbols(query, signal) {
|
|
2996
3026
|
const options = signal === undefined ? {} : { signal };
|
|
2997
3027
|
return this.sendRequest("workspace/symbol", { query }, options);
|
|
@@ -3244,6 +3274,7 @@ class LspManager {
|
|
|
3244
3274
|
this.disposed = false;
|
|
3245
3275
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
3246
3276
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
3277
|
+
this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
|
|
3247
3278
|
this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
|
|
3248
3279
|
this.clientFactory = options.clientFactory ?? ((root, server2) => new LspClient(root, server2));
|
|
3249
3280
|
this.now = options.now ?? (() => Date.now());
|
|
@@ -3277,6 +3308,26 @@ class LspManager {
|
|
|
3277
3308
|
}
|
|
3278
3309
|
}
|
|
3279
3310
|
}
|
|
3311
|
+
evictForAdmission() {
|
|
3312
|
+
while (this.clients.size >= this.maxResidentClients) {
|
|
3313
|
+
const victim = this.leastRecentlyUsedIdleClient();
|
|
3314
|
+
if (!victim)
|
|
3315
|
+
return;
|
|
3316
|
+
this.clients.delete(victim.key);
|
|
3317
|
+
stopClientBestEffort(victim.managed.client);
|
|
3318
|
+
}
|
|
3319
|
+
}
|
|
3320
|
+
leastRecentlyUsedIdleClient() {
|
|
3321
|
+
let candidate = null;
|
|
3322
|
+
for (const [key, managed] of this.clients) {
|
|
3323
|
+
if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing)
|
|
3324
|
+
continue;
|
|
3325
|
+
if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
|
|
3326
|
+
candidate = { key, managed };
|
|
3327
|
+
}
|
|
3328
|
+
}
|
|
3329
|
+
return candidate;
|
|
3330
|
+
}
|
|
3280
3331
|
async tryDeleteIfOrphaned(key, managed) {
|
|
3281
3332
|
if (managed.refCount === 0 && managed.pendingWaiters === 0 && !managed.isInitializing && this.clients.get(key) === managed) {
|
|
3282
3333
|
this.clients.delete(key);
|
|
@@ -3323,6 +3374,7 @@ class LspManager {
|
|
|
3323
3374
|
managed.lastUsedAt = this.now();
|
|
3324
3375
|
return managed.client;
|
|
3325
3376
|
}
|
|
3377
|
+
this.evictForAdmission();
|
|
3326
3378
|
const client = this.clientFactory(root, server2);
|
|
3327
3379
|
const initStartedAt = this.now();
|
|
3328
3380
|
const initPromise = (async () => {
|
|
@@ -3385,6 +3437,7 @@ class LspManager {
|
|
|
3385
3437
|
const key = this.getKey(root, server2.id);
|
|
3386
3438
|
if (this.clients.has(key))
|
|
3387
3439
|
return;
|
|
3440
|
+
this.evictForAdmission();
|
|
3388
3441
|
const client = this.clientFactory(root, server2);
|
|
3389
3442
|
const initStartedAt = this.now();
|
|
3390
3443
|
const initPromise = (async () => {
|
|
@@ -3510,57 +3563,6 @@ function nearestExistingAncestor(directory) {
|
|
|
3510
3563
|
return current;
|
|
3511
3564
|
}
|
|
3512
3565
|
|
|
3513
|
-
// ../lsp-core/src/lsp/server-install-state.ts
|
|
3514
|
-
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3515
|
-
import { dirname as dirname6 } from "node:path";
|
|
3516
|
-
function getInstallDecisionsPath() {
|
|
3517
|
-
return lspRequestContext().installDecisionsPath;
|
|
3518
|
-
}
|
|
3519
|
-
function loadInstallDecisions() {
|
|
3520
|
-
const path = getInstallDecisionsPath();
|
|
3521
|
-
if (!existsSync7(path))
|
|
3522
|
-
return {};
|
|
3523
|
-
try {
|
|
3524
|
-
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
3525
|
-
return isInstallDecisions(parsed) ? parsed : {};
|
|
3526
|
-
} catch {
|
|
3527
|
-
return {};
|
|
3528
|
-
}
|
|
3529
|
-
}
|
|
3530
|
-
function loadInstallDecision(serverId) {
|
|
3531
|
-
return loadInstallDecisions()[serverId];
|
|
3532
|
-
}
|
|
3533
|
-
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3534
|
-
const decisions = loadInstallDecisions();
|
|
3535
|
-
decisions[serverId] = { decision, decidedAt };
|
|
3536
|
-
writeInstallDecisions(decisions);
|
|
3537
|
-
}
|
|
3538
|
-
function isInstallDecision(value) {
|
|
3539
|
-
return value === "declined" || value === "allowed";
|
|
3540
|
-
}
|
|
3541
|
-
function writeInstallDecisions(decisions) {
|
|
3542
|
-
const path = getInstallDecisionsPath();
|
|
3543
|
-
mkdirSync(dirname6(path), { recursive: true });
|
|
3544
|
-
const tmpPath = `${path}.tmp`;
|
|
3545
|
-
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3546
|
-
`, "utf8");
|
|
3547
|
-
renameSync2(tmpPath, path);
|
|
3548
|
-
}
|
|
3549
|
-
function isInstallDecisions(value) {
|
|
3550
|
-
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3551
|
-
}
|
|
3552
|
-
function isInstallDecisionRecord(value) {
|
|
3553
|
-
if (!isRecord5(value))
|
|
3554
|
-
return false;
|
|
3555
|
-
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3556
|
-
}
|
|
3557
|
-
function isRecord5(value) {
|
|
3558
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3559
|
-
}
|
|
3560
|
-
|
|
3561
|
-
// ../lsp-core/src/lsp/config-loader.ts
|
|
3562
|
-
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
3563
|
-
|
|
3564
3566
|
// ../lsp-core/src/lsp/server-definitions.ts
|
|
3565
3567
|
var LSP_INSTALL_HINTS = {
|
|
3566
3568
|
typescript: "npm install -g typescript-language-server typescript",
|
|
@@ -3606,6 +3608,26 @@ var LSP_INSTALL_HINTS = {
|
|
|
3606
3608
|
julials: `julia -e 'using Pkg; Pkg.add("LanguageServer")'`,
|
|
3607
3609
|
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"
|
|
3608
3610
|
};
|
|
3611
|
+
var LSP_LOCAL_INSTALL_HINTS = {
|
|
3612
|
+
typescript: "bun add -d typescript-language-server typescript",
|
|
3613
|
+
vue: "bun add -d @vue/language-server",
|
|
3614
|
+
eslint: "bun add -d vscode-langservers-extracted",
|
|
3615
|
+
oxlint: "bun add -d oxlint",
|
|
3616
|
+
biome: "bun add -d @biomejs/biome",
|
|
3617
|
+
svelte: "bun add -d svelte-language-server",
|
|
3618
|
+
astro: "bun add -d @astrojs/language-server",
|
|
3619
|
+
bash: "bun add -d bash-language-server",
|
|
3620
|
+
"bash-ls": "bun add -d bash-language-server",
|
|
3621
|
+
"yaml-ls": "bun add -d yaml-language-server",
|
|
3622
|
+
php: "bun add -d intelephense",
|
|
3623
|
+
prisma: "bun add -d prisma",
|
|
3624
|
+
dockerfile: "bun add -d dockerfile-language-server-nodejs",
|
|
3625
|
+
pyright: "uv add --dev pyright",
|
|
3626
|
+
basedpyright: "uv add --dev basedpyright",
|
|
3627
|
+
ruff: "uv add --dev ruff",
|
|
3628
|
+
ty: "uv add --dev ty",
|
|
3629
|
+
"ruby-lsp": "bundle add ruby-lsp --group development"
|
|
3630
|
+
};
|
|
3609
3631
|
var BUILTIN_SERVERS = {
|
|
3610
3632
|
typescript: {
|
|
3611
3633
|
command: ["typescript-language-server", "--stdio"],
|
|
@@ -3708,7 +3730,56 @@ var BUILTIN_SERVERS = {
|
|
|
3708
3730
|
}
|
|
3709
3731
|
};
|
|
3710
3732
|
|
|
3733
|
+
// ../lsp-core/src/lsp/server-install-state.ts
|
|
3734
|
+
import { existsSync as existsSync7, mkdirSync, readFileSync as readFileSync3, renameSync as renameSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
3735
|
+
import { dirname as dirname6 } from "node:path";
|
|
3736
|
+
function getInstallDecisionsPath() {
|
|
3737
|
+
return lspRequestContext().installDecisionsPath;
|
|
3738
|
+
}
|
|
3739
|
+
function loadInstallDecisions() {
|
|
3740
|
+
const path = getInstallDecisionsPath();
|
|
3741
|
+
if (!existsSync7(path))
|
|
3742
|
+
return {};
|
|
3743
|
+
try {
|
|
3744
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
3745
|
+
return isInstallDecisions(parsed) ? parsed : {};
|
|
3746
|
+
} catch {
|
|
3747
|
+
return {};
|
|
3748
|
+
}
|
|
3749
|
+
}
|
|
3750
|
+
function loadInstallDecision(serverId) {
|
|
3751
|
+
return loadInstallDecisions()[serverId];
|
|
3752
|
+
}
|
|
3753
|
+
function recordInstallDecision(serverId, decision, decidedAt = new Date().toISOString()) {
|
|
3754
|
+
const decisions = loadInstallDecisions();
|
|
3755
|
+
decisions[serverId] = { decision, decidedAt };
|
|
3756
|
+
writeInstallDecisions(decisions);
|
|
3757
|
+
}
|
|
3758
|
+
function isInstallDecision(value) {
|
|
3759
|
+
return value === "declined" || value === "allowed";
|
|
3760
|
+
}
|
|
3761
|
+
function writeInstallDecisions(decisions) {
|
|
3762
|
+
const path = getInstallDecisionsPath();
|
|
3763
|
+
mkdirSync(dirname6(path), { recursive: true });
|
|
3764
|
+
const tmpPath = `${path}.tmp`;
|
|
3765
|
+
writeFileSync2(tmpPath, `${JSON.stringify(decisions, null, 2)}
|
|
3766
|
+
`, "utf8");
|
|
3767
|
+
renameSync2(tmpPath, path);
|
|
3768
|
+
}
|
|
3769
|
+
function isInstallDecisions(value) {
|
|
3770
|
+
return isRecord5(value) && Object.values(value).every(isInstallDecisionRecord);
|
|
3771
|
+
}
|
|
3772
|
+
function isInstallDecisionRecord(value) {
|
|
3773
|
+
if (!isRecord5(value))
|
|
3774
|
+
return false;
|
|
3775
|
+
return isInstallDecision(value["decision"]) && typeof value["decidedAt"] === "string";
|
|
3776
|
+
}
|
|
3777
|
+
function isRecord5(value) {
|
|
3778
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3779
|
+
}
|
|
3780
|
+
|
|
3711
3781
|
// ../lsp-core/src/lsp/config-loader.ts
|
|
3782
|
+
import { existsSync as existsSync8, readFileSync as readFileSync4 } from "node:fs";
|
|
3712
3783
|
function getProjectConfigPaths() {
|
|
3713
3784
|
return lspRequestContext().projectConfigPaths;
|
|
3714
3785
|
}
|
|
@@ -3905,53 +3976,154 @@ function getDisabledServerIds() {
|
|
|
3905
3976
|
|
|
3906
3977
|
// ../lsp-core/src/lsp/server-installation.ts
|
|
3907
3978
|
import { existsSync as existsSync9 } from "node:fs";
|
|
3908
|
-
import { delimiter as delimiter3, join as join4 } from "node:path";
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3979
|
+
import { delimiter as delimiter3, dirname as dirname7, isAbsolute as isAbsolute3, join as join4, resolve as resolve7 } from "node:path";
|
|
3980
|
+
var LOCAL_BIN_RULES = [
|
|
3981
|
+
{
|
|
3982
|
+
markers: ["package.json", "bun.lock", "bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"],
|
|
3983
|
+
binDirs: [join4("node_modules", ".bin")]
|
|
3984
|
+
},
|
|
3985
|
+
{
|
|
3986
|
+
markers: [
|
|
3987
|
+
"pyproject.toml",
|
|
3988
|
+
"ty.toml",
|
|
3989
|
+
"requirements.txt",
|
|
3990
|
+
"setup.py",
|
|
3991
|
+
"setup.cfg",
|
|
3992
|
+
"Pipfile",
|
|
3993
|
+
"pyrightconfig.json",
|
|
3994
|
+
"ruff.toml",
|
|
3995
|
+
".ruff.toml"
|
|
3996
|
+
],
|
|
3997
|
+
binDirs: [
|
|
3998
|
+
join4(".venv", "bin"),
|
|
3999
|
+
join4(".venv", "Scripts"),
|
|
4000
|
+
join4("venv", "bin"),
|
|
4001
|
+
join4("venv", "Scripts"),
|
|
4002
|
+
join4(".env", "bin"),
|
|
4003
|
+
join4(".env", "Scripts")
|
|
4004
|
+
]
|
|
4005
|
+
},
|
|
4006
|
+
{
|
|
4007
|
+
markers: ["Gemfile", "Gemfile.lock"],
|
|
4008
|
+
binDirs: [join4("vendor", "bundle", "bin"), "bin"]
|
|
4009
|
+
},
|
|
4010
|
+
{
|
|
4011
|
+
markers: ["go.mod", "go.sum", "go.work"],
|
|
4012
|
+
binDirs: ["bin"]
|
|
4013
|
+
}
|
|
4014
|
+
];
|
|
4015
|
+
var resolutionCache = new Map;
|
|
4016
|
+
var probeCount = 0;
|
|
4017
|
+
function probe(path) {
|
|
4018
|
+
probeCount += 1;
|
|
4019
|
+
return existsSync9(path);
|
|
4020
|
+
}
|
|
4021
|
+
function executableSuffixes(platform, pathExt) {
|
|
4022
|
+
if (platform !== "win32")
|
|
4023
|
+
return [""];
|
|
4024
|
+
const configured = pathExt ?? process.env["PATHEXT"] ?? "";
|
|
4025
|
+
const systemExts = configured.split(";").filter((entry) => entry.length > 0).map((entry) => entry.toLowerCase());
|
|
4026
|
+
return [...new Set(["", ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
4027
|
+
}
|
|
4028
|
+
function probeWithSuffixes(directory, command, suffixes) {
|
|
4029
|
+
for (const suffix of suffixes) {
|
|
4030
|
+
const candidate = join4(directory, command + suffix);
|
|
4031
|
+
if (probe(candidate))
|
|
4032
|
+
return candidate;
|
|
3918
4033
|
}
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
4034
|
+
return null;
|
|
4035
|
+
}
|
|
4036
|
+
function resolveLocal(command, workingDirectory, suffixes, stopAt) {
|
|
4037
|
+
const boundary = stopAt === undefined ? undefined : resolve7(stopAt);
|
|
4038
|
+
let current = resolve7(workingDirectory);
|
|
4039
|
+
while (true) {
|
|
4040
|
+
for (const rule of LOCAL_BIN_RULES) {
|
|
4041
|
+
if (!rule.markers.some((marker) => probe(join4(current, marker))))
|
|
4042
|
+
continue;
|
|
4043
|
+
for (const binDir of rule.binDirs) {
|
|
4044
|
+
const found = probeWithSuffixes(join4(current, binDir), command, suffixes);
|
|
4045
|
+
if (found !== null)
|
|
4046
|
+
return found;
|
|
4047
|
+
}
|
|
3928
4048
|
}
|
|
4049
|
+
if (probe(join4(current, ".git")))
|
|
4050
|
+
return null;
|
|
4051
|
+
if (boundary !== undefined && current === boundary)
|
|
4052
|
+
return null;
|
|
4053
|
+
const parent = dirname7(current);
|
|
4054
|
+
if (parent === current)
|
|
4055
|
+
return null;
|
|
4056
|
+
current = parent;
|
|
3929
4057
|
}
|
|
3930
|
-
|
|
3931
|
-
|
|
4058
|
+
}
|
|
4059
|
+
function resolveFromPath(command, suffixes, platform, pathEnvOverride) {
|
|
4060
|
+
let pathEnv = pathEnvOverride ?? process.env["PATH"] ?? "";
|
|
4061
|
+
if (platform === "win32" && !pathEnv) {
|
|
3932
4062
|
pathEnv = process.env["Path"] ?? "";
|
|
3933
4063
|
}
|
|
3934
|
-
const
|
|
3935
|
-
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3939
|
-
|
|
3940
|
-
}
|
|
4064
|
+
for (const entry of pathEnv.split(delimiter3)) {
|
|
4065
|
+
if (entry.length === 0)
|
|
4066
|
+
continue;
|
|
4067
|
+
const found = probeWithSuffixes(entry, command, suffixes);
|
|
4068
|
+
if (found !== null)
|
|
4069
|
+
return found;
|
|
3941
4070
|
}
|
|
3942
|
-
|
|
3943
|
-
|
|
3944
|
-
|
|
4071
|
+
return null;
|
|
4072
|
+
}
|
|
4073
|
+
function resolveServerBinary(command, workingDirectory, options = {}) {
|
|
4074
|
+
if (command.length === 0)
|
|
4075
|
+
return null;
|
|
4076
|
+
const [cmd] = command;
|
|
4077
|
+
if (cmd === undefined || cmd.length === 0)
|
|
4078
|
+
return null;
|
|
4079
|
+
const platform = options.platform ?? process.platform;
|
|
4080
|
+
const suffixes = executableSuffixes(platform, options.pathExt);
|
|
4081
|
+
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
4082
|
+
const explicit = isAbsolute3(cmd) ? cmd : resolve7(workingDirectory ?? process.cwd(), cmd);
|
|
4083
|
+
return probe(explicit) ? explicit : null;
|
|
4084
|
+
}
|
|
4085
|
+
const cacheKey = JSON.stringify([
|
|
4086
|
+
workingDirectory ?? "",
|
|
4087
|
+
cmd,
|
|
4088
|
+
platform,
|
|
4089
|
+
options.stopAt ?? "",
|
|
4090
|
+
options.pathExt ?? "",
|
|
4091
|
+
options.pathEnv ?? process.env["PATH"] ?? ""
|
|
4092
|
+
]);
|
|
4093
|
+
const cached = resolutionCache.get(cacheKey);
|
|
4094
|
+
if (cached !== undefined)
|
|
4095
|
+
return cached;
|
|
4096
|
+
let resolved = null;
|
|
4097
|
+
if (workingDirectory !== undefined && workingDirectory.length > 0) {
|
|
4098
|
+
resolved = resolveLocal(cmd, workingDirectory, suffixes, options.stopAt);
|
|
4099
|
+
}
|
|
4100
|
+
resolved ??= resolveFromPath(cmd, suffixes, platform, options.pathEnv);
|
|
4101
|
+
if (resolved === null && cmd === "node")
|
|
4102
|
+
resolved = cmd;
|
|
4103
|
+
resolutionCache.set(cacheKey, resolved);
|
|
4104
|
+
return resolved;
|
|
4105
|
+
}
|
|
4106
|
+
function isServerInstalled(command, workingDirectory, options = {}) {
|
|
4107
|
+
if (command.length === 0)
|
|
4108
|
+
return false;
|
|
4109
|
+
return resolveServerBinary(command, workingDirectory, options) !== null;
|
|
3945
4110
|
}
|
|
3946
4111
|
|
|
3947
4112
|
// ../lsp-core/src/lsp/server-resolution.ts
|
|
4113
|
+
function withResolvedCommand(command, binaryPath) {
|
|
4114
|
+
return [binaryPath, ...command.slice(1)];
|
|
4115
|
+
}
|
|
3948
4116
|
function findServerForExtension(ext) {
|
|
3949
4117
|
const servers = getMergedServers();
|
|
4118
|
+
const workingDirectory = contextCwd();
|
|
3950
4119
|
for (const server2 of servers) {
|
|
3951
|
-
if (server2.extensions.includes(ext)
|
|
4120
|
+
if (!server2.extensions.includes(ext))
|
|
4121
|
+
continue;
|
|
4122
|
+
const binaryPath = resolveServerBinary(server2.command, workingDirectory);
|
|
4123
|
+
if (binaryPath !== null) {
|
|
3952
4124
|
const resolvedServer = {
|
|
3953
4125
|
id: server2.id,
|
|
3954
|
-
command: server2.command,
|
|
4126
|
+
command: withResolvedCommand(server2.command, binaryPath),
|
|
3955
4127
|
extensions: server2.extensions,
|
|
3956
4128
|
priority: server2.priority
|
|
3957
4129
|
};
|
|
@@ -3998,6 +4170,7 @@ function findServerForExtension(ext) {
|
|
|
3998
4170
|
function getAllServers() {
|
|
3999
4171
|
const servers = getMergedServers();
|
|
4000
4172
|
const disabled = getDisabledServerIds();
|
|
4173
|
+
const workingDirectory = contextCwd();
|
|
4001
4174
|
const result = [];
|
|
4002
4175
|
const seen = new Set;
|
|
4003
4176
|
for (const server2 of servers) {
|
|
@@ -4005,7 +4178,7 @@ function getAllServers() {
|
|
|
4005
4178
|
continue;
|
|
4006
4179
|
result.push({
|
|
4007
4180
|
id: server2.id,
|
|
4008
|
-
installed: isServerInstalled(server2.command),
|
|
4181
|
+
installed: isServerInstalled(server2.command, workingDirectory),
|
|
4009
4182
|
extensions: server2.extensions,
|
|
4010
4183
|
disabled: false,
|
|
4011
4184
|
source: server2.source,
|
|
@@ -4019,7 +4192,7 @@ function getAllServers() {
|
|
|
4019
4192
|
const builtin = BUILTIN_SERVERS[id];
|
|
4020
4193
|
result.push({
|
|
4021
4194
|
id,
|
|
4022
|
-
installed: builtin ? isServerInstalled(builtin.command) : false,
|
|
4195
|
+
installed: builtin ? isServerInstalled(builtin.command, workingDirectory) : false,
|
|
4023
4196
|
extensions: builtin?.extensions ?? [],
|
|
4024
4197
|
disabled: true,
|
|
4025
4198
|
source: "disabled",
|
|
@@ -4042,7 +4215,7 @@ function findWorkspaceRoot(filePath) {
|
|
|
4042
4215
|
const abs = resolveReadablePathInsideContext(filePath);
|
|
4043
4216
|
let dir = abs;
|
|
4044
4217
|
if (!isDirectoryPath(dir)) {
|
|
4045
|
-
dir =
|
|
4218
|
+
dir = dirname8(dir);
|
|
4046
4219
|
}
|
|
4047
4220
|
if (!isPathInside(cwd, abs))
|
|
4048
4221
|
return findWorkspaceRootOutsideContext(dir);
|
|
@@ -4058,13 +4231,13 @@ function findWorkspaceRoot(filePath) {
|
|
|
4058
4231
|
}
|
|
4059
4232
|
if (dir === cwd)
|
|
4060
4233
|
break;
|
|
4061
|
-
dir =
|
|
4234
|
+
dir = dirname8(dir);
|
|
4062
4235
|
}
|
|
4063
4236
|
return fallbackRoot;
|
|
4064
4237
|
}
|
|
4065
4238
|
function resolveReadablePathInsideContext(filePath) {
|
|
4066
4239
|
const cwd = contextCwd();
|
|
4067
|
-
const abs =
|
|
4240
|
+
const abs = resolve8(cwd, filePath);
|
|
4068
4241
|
if (isPathInside(cwd, abs))
|
|
4069
4242
|
return abs;
|
|
4070
4243
|
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
@@ -4090,7 +4263,7 @@ function rebaseThroughCanonicalAncestor(path, cwd) {
|
|
|
4090
4263
|
if (isPathInside(cwd, canonical))
|
|
4091
4264
|
return suffix.length === 0 ? canonical : join5(canonical, ...suffix);
|
|
4092
4265
|
}
|
|
4093
|
-
const parent =
|
|
4266
|
+
const parent = dirname8(current);
|
|
4094
4267
|
if (parent === current)
|
|
4095
4268
|
return;
|
|
4096
4269
|
suffix.unshift(basename3(current));
|
|
@@ -4113,7 +4286,7 @@ function nearestExistingDirectoryInsideContext(directory, cwd) {
|
|
|
4113
4286
|
return canonical;
|
|
4114
4287
|
if (current === cwd)
|
|
4115
4288
|
return;
|
|
4116
|
-
current =
|
|
4289
|
+
current = dirname8(current);
|
|
4117
4290
|
}
|
|
4118
4291
|
return;
|
|
4119
4292
|
}
|
|
@@ -4140,6 +4313,19 @@ function formatServerLookupError(result) {
|
|
|
4140
4313
|
].join(`
|
|
4141
4314
|
`);
|
|
4142
4315
|
}
|
|
4316
|
+
function formatInstallOptions(serverId, installHint) {
|
|
4317
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
4318
|
+
if (localHint === undefined) {
|
|
4319
|
+
return ["To install, run:", ` ${installHint}`];
|
|
4320
|
+
}
|
|
4321
|
+
return [
|
|
4322
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
4323
|
+
` ${localHint}`,
|
|
4324
|
+
"",
|
|
4325
|
+
"Or install it globally:",
|
|
4326
|
+
` ${installHint}`
|
|
4327
|
+
];
|
|
4328
|
+
}
|
|
4143
4329
|
function formatNotInstalled(result) {
|
|
4144
4330
|
const { server: server2, installHint } = result;
|
|
4145
4331
|
const extensions = server2.extensions.join(", ");
|
|
@@ -4154,19 +4340,19 @@ function formatNotInstalled(result) {
|
|
|
4154
4340
|
`Command not found: ${server2.command[0]}`,
|
|
4155
4341
|
""
|
|
4156
4342
|
];
|
|
4343
|
+
const installOptions = formatInstallOptions(server2.id, installHint);
|
|
4157
4344
|
if (decision === "allowed") {
|
|
4158
4345
|
return [
|
|
4159
4346
|
...header,
|
|
4160
4347
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
4161
|
-
|
|
4348
|
+
...installOptions.slice(1)
|
|
4162
4349
|
].join(`
|
|
4163
4350
|
`);
|
|
4164
4351
|
}
|
|
4165
4352
|
if (!context.capabilities.installDecisionTool) {
|
|
4166
4353
|
return [
|
|
4167
4354
|
...header,
|
|
4168
|
-
|
|
4169
|
-
` ${installHint}`,
|
|
4355
|
+
...installOptions,
|
|
4170
4356
|
"",
|
|
4171
4357
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4172
4358
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines."
|
|
@@ -4175,8 +4361,7 @@ function formatNotInstalled(result) {
|
|
|
4175
4361
|
}
|
|
4176
4362
|
return [
|
|
4177
4363
|
...header,
|
|
4178
|
-
|
|
4179
|
-
` ${installHint}`,
|
|
4364
|
+
...installOptions,
|
|
4180
4365
|
"",
|
|
4181
4366
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
4182
4367
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -4232,7 +4417,7 @@ async function withLspClient(filePath, fn, toolName, options = {}) {
|
|
|
4232
4417
|
|
|
4233
4418
|
// ../lsp-core/src/lsp/directory-diagnostics.ts
|
|
4234
4419
|
import { existsSync as existsSync11, lstatSync as lstatSync4, readdirSync as readdirSync3 } from "node:fs";
|
|
4235
|
-
import { join as join6, resolve as
|
|
4420
|
+
import { join as join6, resolve as resolve9 } from "node:path";
|
|
4236
4421
|
|
|
4237
4422
|
// ../lsp-core/src/lsp/formatters.ts
|
|
4238
4423
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
@@ -4387,7 +4572,7 @@ async function aggregateDiagnosticsForDirectory(directory, extension, severity,
|
|
|
4387
4572
|
if (!extension.startsWith(".")) {
|
|
4388
4573
|
throw new LspInvalidPathError(`Extension must start with a dot (e.g., ".ts", not "${extension}"). Use ".${extension}" instead.`);
|
|
4389
4574
|
}
|
|
4390
|
-
const absDir =
|
|
4575
|
+
const absDir = resolve9(options.workspaceRoot ?? contextCwd(), directory);
|
|
4391
4576
|
if (!existsSync11(absDir)) {
|
|
4392
4577
|
throw new LspInvalidPathError(`Directory does not exist: ${absDir}`);
|
|
4393
4578
|
}
|
|
@@ -4744,6 +4929,96 @@ async function executeLspDiagnostics(params, signal) {
|
|
|
4744
4929
|
throw error;
|
|
4745
4930
|
}
|
|
4746
4931
|
}
|
|
4932
|
+
// ../lsp-core/src/lsp/format-document.ts
|
|
4933
|
+
import { readFileSync as readFileSync5, renameSync as renameSync3, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
4934
|
+
var DEFAULT_FORMATTING_OPTIONS = {
|
|
4935
|
+
tabSize: 4,
|
|
4936
|
+
insertSpaces: false,
|
|
4937
|
+
trimTrailingWhitespace: true,
|
|
4938
|
+
insertFinalNewline: true,
|
|
4939
|
+
trimFinalNewlines: true
|
|
4940
|
+
};
|
|
4941
|
+
var UNCHANGED = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
4942
|
+
async function formatDocumentWithClient(client, filePath, options = {}) {
|
|
4943
|
+
const edits = await client.formatDocument(filePath, options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS, options.signal);
|
|
4944
|
+
if (edits === null)
|
|
4945
|
+
return { status: "unavailable", reason: "capability_not_advertised" };
|
|
4946
|
+
if (edits.length === 0)
|
|
4947
|
+
return UNCHANGED;
|
|
4948
|
+
const before = readFileSync5(filePath, "utf-8");
|
|
4949
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
4950
|
+
if (normalized.text === before)
|
|
4951
|
+
return UNCHANGED;
|
|
4952
|
+
writeAtomically(filePath, normalized.text);
|
|
4953
|
+
await client.openFile(filePath);
|
|
4954
|
+
return {
|
|
4955
|
+
status: "formatted",
|
|
4956
|
+
...lineDelta(normalized.edits)
|
|
4957
|
+
};
|
|
4958
|
+
}
|
|
4959
|
+
function lineDelta(edits) {
|
|
4960
|
+
let linesAdded = 0;
|
|
4961
|
+
let linesRemoved = 0;
|
|
4962
|
+
for (const edit of edits) {
|
|
4963
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
4964
|
+
linesAdded += edit.newText.split(`
|
|
4965
|
+
`).length;
|
|
4966
|
+
}
|
|
4967
|
+
return { linesAdded, linesRemoved };
|
|
4968
|
+
}
|
|
4969
|
+
function writeAtomically(filePath, content) {
|
|
4970
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
4971
|
+
writeFileSync3(tempPath, content, "utf-8");
|
|
4972
|
+
try {
|
|
4973
|
+
renameSync3(tempPath, filePath);
|
|
4974
|
+
} catch (error) {
|
|
4975
|
+
try {
|
|
4976
|
+
unlinkSync(tempPath);
|
|
4977
|
+
} catch {}
|
|
4978
|
+
throw error;
|
|
4979
|
+
}
|
|
4980
|
+
}
|
|
4981
|
+
|
|
4982
|
+
// ../lsp-core/src/tools/format.ts
|
|
4983
|
+
async function executeLspFormat(params, signal) {
|
|
4984
|
+
const filePath = requireString(params, "filePath");
|
|
4985
|
+
try {
|
|
4986
|
+
const result = await withLspClient(filePath, async (client, _workspaceRoot, resolvedFilePath) => formatDocumentWithClient(client, resolvedFilePath, signal === undefined ? {} : { signal }), "format", clientOptions(signal));
|
|
4987
|
+
return text(describeResult(filePath, result), formatDetails(filePath, result));
|
|
4988
|
+
} catch (error) {
|
|
4989
|
+
const missingDependency = missingDependencyResult(error, {
|
|
4990
|
+
filePath,
|
|
4991
|
+
status: "unavailable",
|
|
4992
|
+
reason: "server_unavailable",
|
|
4993
|
+
linesAdded: 0,
|
|
4994
|
+
linesRemoved: 0
|
|
4995
|
+
});
|
|
4996
|
+
if (missingDependency)
|
|
4997
|
+
return missingDependency;
|
|
4998
|
+
throw error;
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
function formatDetails(filePath, result) {
|
|
5002
|
+
if (result.status === "unavailable") {
|
|
5003
|
+
return { filePath, status: "unavailable", reason: result.reason, linesAdded: 0, linesRemoved: 0 };
|
|
5004
|
+
}
|
|
5005
|
+
return {
|
|
5006
|
+
filePath,
|
|
5007
|
+
status: result.status,
|
|
5008
|
+
linesAdded: result.linesAdded,
|
|
5009
|
+
linesRemoved: result.linesRemoved
|
|
5010
|
+
};
|
|
5011
|
+
}
|
|
5012
|
+
function describeResult(filePath, result) {
|
|
5013
|
+
if (result.status === "unavailable") {
|
|
5014
|
+
return `Formatting unavailable for ${filePath}: the language server does not advertise documentFormattingProvider.`;
|
|
5015
|
+
}
|
|
5016
|
+
if (result.status === "unchanged") {
|
|
5017
|
+
return `Already formatted: ${filePath}`;
|
|
5018
|
+
}
|
|
5019
|
+
return `Formatted ${filePath} (+${result.linesAdded}/-${result.linesRemoved} lines)`;
|
|
5020
|
+
}
|
|
5021
|
+
|
|
4747
5022
|
// ../lsp-core/src/tools/install-decision.ts
|
|
4748
5023
|
async function executeLspInstallDecision(params) {
|
|
4749
5024
|
const serverId = requireString(params, "server_id");
|
|
@@ -5076,6 +5351,16 @@ var LSP_MCP_TOOLS = [
|
|
|
5076
5351
|
}, ["filePath", "line", "character", "newName"]),
|
|
5077
5352
|
execute: executeLspRename
|
|
5078
5353
|
},
|
|
5354
|
+
{
|
|
5355
|
+
name: "format",
|
|
5356
|
+
aliases: ["lsp_format"],
|
|
5357
|
+
title: "LSP Format",
|
|
5358
|
+
description: "Format a source file with its language server and write the returned edits to disk.",
|
|
5359
|
+
inputSchema: objectSchema({
|
|
5360
|
+
filePath: { type: "string", description: "Source file path to format." }
|
|
5361
|
+
}, ["filePath"]),
|
|
5362
|
+
execute: executeLspFormat
|
|
5363
|
+
},
|
|
5079
5364
|
{
|
|
5080
5365
|
name: "install_decision",
|
|
5081
5366
|
aliases: ["lsp_install_decision"],
|
|
@@ -5254,7 +5539,7 @@ function errorText(error) {
|
|
|
5254
5539
|
import { spawn as spawn2 } from "node:child_process";
|
|
5255
5540
|
import { closeSync as closeSync2, existsSync as existsSync12, mkdirSync as mkdirSync3, openSync as openSync2, writeSync as writeSync2 } from "node:fs";
|
|
5256
5541
|
import { Socket } from "node:net";
|
|
5257
|
-
import { dirname as
|
|
5542
|
+
import { dirname as dirname10, isAbsolute as isAbsolute5 } from "node:path";
|
|
5258
5543
|
import { argv0, execPath } from "node:process";
|
|
5259
5544
|
|
|
5260
5545
|
// src/ipc-protocol.ts
|
|
@@ -5268,11 +5553,11 @@ import {
|
|
|
5268
5553
|
lstatSync as lstatSync6,
|
|
5269
5554
|
mkdirSync as mkdirSync2,
|
|
5270
5555
|
openSync,
|
|
5271
|
-
readFileSync as
|
|
5272
|
-
unlinkSync,
|
|
5556
|
+
readFileSync as readFileSync6,
|
|
5557
|
+
unlinkSync as unlinkSync2,
|
|
5273
5558
|
writeSync
|
|
5274
5559
|
} from "node:fs";
|
|
5275
|
-
import { dirname as
|
|
5560
|
+
import { dirname as dirname9 } from "node:path";
|
|
5276
5561
|
var OMO_DAEMON_PROTOCOL_VERSION = 1;
|
|
5277
5562
|
var AUTH_ERROR_CODE = -32001;
|
|
5278
5563
|
var PROTOCOL_ERROR_CODE = -32002;
|
|
@@ -5292,7 +5577,7 @@ function authEnvelope(token) {
|
|
|
5292
5577
|
}
|
|
5293
5578
|
function readAuthToken(paths) {
|
|
5294
5579
|
try {
|
|
5295
|
-
const token =
|
|
5580
|
+
const token = readFileSync6(paths.auth, "utf8").trim();
|
|
5296
5581
|
return token.length > 0 ? token : null;
|
|
5297
5582
|
} catch (error) {
|
|
5298
5583
|
if (error instanceof Error)
|
|
@@ -5308,7 +5593,7 @@ function readOrCreateAuthToken(paths) {
|
|
|
5308
5593
|
}
|
|
5309
5594
|
function rotateAuthToken(paths) {
|
|
5310
5595
|
try {
|
|
5311
|
-
|
|
5596
|
+
unlinkSync2(paths.auth);
|
|
5312
5597
|
} catch (error) {
|
|
5313
5598
|
if (!(error instanceof Error))
|
|
5314
5599
|
throw error;
|
|
@@ -5380,7 +5665,7 @@ function setPrivateFileMode(path) {
|
|
|
5380
5665
|
chmodSync(path, 384);
|
|
5381
5666
|
}
|
|
5382
5667
|
function createAuthToken(paths) {
|
|
5383
|
-
ensurePrivateDirectory(
|
|
5668
|
+
ensurePrivateDirectory(dirname9(paths.auth));
|
|
5384
5669
|
const token = randomBytes(AUTH_TOKEN_BYTES).toString("base64url");
|
|
5385
5670
|
let fd;
|
|
5386
5671
|
try {
|
|
@@ -5461,7 +5746,7 @@ import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
|
5461
5746
|
|
|
5462
5747
|
// src/runtime-contract.ts
|
|
5463
5748
|
import { statSync as statSync4 } from "node:fs";
|
|
5464
|
-
import { isAbsolute as
|
|
5749
|
+
import { isAbsolute as isAbsolute4 } from "node:path";
|
|
5465
5750
|
var OMO_LSP_DAEMON_DIR = "OMO_LSP_DAEMON_DIR";
|
|
5466
5751
|
var OMO_LSP_DAEMON_CLI = "OMO_LSP_DAEMON_CLI";
|
|
5467
5752
|
var OMO_LSP_DAEMON_VERSION = "OMO_LSP_DAEMON_VERSION";
|
|
@@ -5498,12 +5783,12 @@ function resolveDaemonRuntime(env, defaults) {
|
|
|
5498
5783
|
throw new InvalidRuntimeOverrideError("paired_values_required", `${OMO_LSP_DAEMON_CLI} and ${OMO_LSP_DAEMON_VERSION} must be set together`);
|
|
5499
5784
|
}
|
|
5500
5785
|
if (!hasCliOverride || !hasVersionOverride) {
|
|
5501
|
-
if (!
|
|
5786
|
+
if (!isAbsolute4(defaults.cliPath)) {
|
|
5502
5787
|
throw new InvalidRuntimeOverrideError("packaged_cli_must_be_absolute", "Packaged LSP daemon CLI path must be absolute");
|
|
5503
5788
|
}
|
|
5504
5789
|
return { cliPath: defaults.cliPath, version: validateDaemonVersion(defaults.version) };
|
|
5505
5790
|
}
|
|
5506
|
-
if (!
|
|
5791
|
+
if (!isAbsolute4(cliOverride)) {
|
|
5507
5792
|
throw new InvalidRuntimeOverrideError("cli_must_be_absolute", `${OMO_LSP_DAEMON_CLI} must be an absolute path to an existing regular file`);
|
|
5508
5793
|
}
|
|
5509
5794
|
let cliStats;
|
|
@@ -5681,7 +5966,7 @@ async function probeDaemon(paths, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5681
5966
|
return await pingDaemon(paths, token, timeoutMs, signal) !== null;
|
|
5682
5967
|
}
|
|
5683
5968
|
function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
5684
|
-
return new Promise((
|
|
5969
|
+
return new Promise((resolve10) => {
|
|
5685
5970
|
const socket = new Socket;
|
|
5686
5971
|
let settled = false;
|
|
5687
5972
|
let timer;
|
|
@@ -5693,7 +5978,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5693
5978
|
clearTimeout(timer);
|
|
5694
5979
|
signal?.removeEventListener("abort", onAbort);
|
|
5695
5980
|
socket.destroy();
|
|
5696
|
-
|
|
5981
|
+
resolve10(value);
|
|
5697
5982
|
};
|
|
5698
5983
|
const onAbort = () => finish(null);
|
|
5699
5984
|
const decoder = createLineDecoder((message) => {
|
|
@@ -5717,7 +6002,7 @@ function pingDaemon(paths, token, timeoutMs = PROBE_TIMEOUT_MS, signal) {
|
|
|
5717
6002
|
});
|
|
5718
6003
|
}
|
|
5719
6004
|
function spawnDaemonProcess(paths) {
|
|
5720
|
-
mkdirSync3(
|
|
6005
|
+
mkdirSync3(dirname10(paths.log), { recursive: true });
|
|
5721
6006
|
const logFd = openSync2(paths.log, "a");
|
|
5722
6007
|
try {
|
|
5723
6008
|
const child = spawn2(resolveDaemonNodeExecutable(), [paths.cliPath, "daemon"], {
|
|
@@ -5740,7 +6025,7 @@ function spawnDaemonProcess(paths) {
|
|
|
5740
6025
|
function resolveDaemonNodeExecutable(cachedExecPath = execPath, originalArgv0 = argv0, pathExists = existsSync12) {
|
|
5741
6026
|
if (pathExists(cachedExecPath))
|
|
5742
6027
|
return cachedExecPath;
|
|
5743
|
-
if (
|
|
6028
|
+
if (isAbsolute5(originalArgv0) && pathExists(originalArgv0))
|
|
5744
6029
|
return originalArgv0;
|
|
5745
6030
|
return "node";
|
|
5746
6031
|
}
|
|
@@ -5753,7 +6038,7 @@ function defaultEnsureDaemonDeps() {
|
|
|
5753
6038
|
};
|
|
5754
6039
|
}
|
|
5755
6040
|
function sleepWithSignal(ms, signal) {
|
|
5756
|
-
return new Promise((
|
|
6041
|
+
return new Promise((resolve10) => {
|
|
5757
6042
|
let settled = false;
|
|
5758
6043
|
const finish = () => {
|
|
5759
6044
|
if (settled)
|
|
@@ -5761,7 +6046,7 @@ function sleepWithSignal(ms, signal) {
|
|
|
5761
6046
|
settled = true;
|
|
5762
6047
|
clearTimeout(timer);
|
|
5763
6048
|
signal?.removeEventListener("abort", finish);
|
|
5764
|
-
|
|
6049
|
+
resolve10();
|
|
5765
6050
|
};
|
|
5766
6051
|
const timer = setTimeout(finish, ms);
|
|
5767
6052
|
if (signal?.aborted) {
|
|
@@ -5776,7 +6061,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
5776
6061
|
return promise;
|
|
5777
6062
|
if (signal.aborted)
|
|
5778
6063
|
return Promise.reject(abortError3(signal));
|
|
5779
|
-
return new Promise((
|
|
6064
|
+
return new Promise((resolve10, reject) => {
|
|
5780
6065
|
let settled = false;
|
|
5781
6066
|
const finish = (run) => {
|
|
5782
6067
|
if (settled)
|
|
@@ -5787,7 +6072,7 @@ function awaitWithSignal2(promise, signal) {
|
|
|
5787
6072
|
};
|
|
5788
6073
|
const onAbort = () => finish(() => reject(abortError3(signal)));
|
|
5789
6074
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5790
|
-
promise.then((value) => finish(() =>
|
|
6075
|
+
promise.then((value) => finish(() => resolve10(value)), (error) => finish(() => reject(error)));
|
|
5791
6076
|
});
|
|
5792
6077
|
}
|
|
5793
6078
|
function throwIfAborted(signal) {
|
|
@@ -5955,6 +6240,9 @@ async function callToolViaDaemon(name, args, options) {
|
|
|
5955
6240
|
function callDiagnosticsViaDaemon(filePath, options) {
|
|
5956
6241
|
return callToolViaDaemon("diagnostics", { filePath, severity: "error" }, options);
|
|
5957
6242
|
}
|
|
6243
|
+
function callFormatViaDaemon(filePath, options) {
|
|
6244
|
+
return callToolViaDaemon("format", { filePath }, options);
|
|
6245
|
+
}
|
|
5958
6246
|
function currentRequestContext(env = process.env) {
|
|
5959
6247
|
const cwd = process.cwd();
|
|
5960
6248
|
const home = env["HOME"] ?? homedir3();
|
|
@@ -5977,7 +6265,7 @@ function withContext(args, context) {
|
|
|
5977
6265
|
function ensureDaemonAvailable(paths, ensure, signal) {
|
|
5978
6266
|
if (!signal)
|
|
5979
6267
|
return ensure(paths);
|
|
5980
|
-
return new Promise((
|
|
6268
|
+
return new Promise((resolve10, reject) => {
|
|
5981
6269
|
let settled = false;
|
|
5982
6270
|
const finish = (run) => {
|
|
5983
6271
|
if (settled)
|
|
@@ -5992,11 +6280,11 @@ function ensureDaemonAvailable(paths, ensure, signal) {
|
|
|
5992
6280
|
return;
|
|
5993
6281
|
}
|
|
5994
6282
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5995
|
-
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() =>
|
|
6283
|
+
Promise.resolve().then(() => ensure(paths, signal)).then(() => finish(() => resolve10()), (error) => finish(() => reject(signal.aborted ? new DaemonRequestCancelledError(false) : error)));
|
|
5996
6284
|
});
|
|
5997
6285
|
}
|
|
5998
6286
|
function sendToolCall(paths, token, name, args, options) {
|
|
5999
|
-
return new Promise((
|
|
6287
|
+
return new Promise((resolve10, reject) => {
|
|
6000
6288
|
const socket = connect(paths.socket);
|
|
6001
6289
|
const requestId = allocateProxyRequestId();
|
|
6002
6290
|
let settled = false;
|
|
@@ -6049,7 +6337,7 @@ function sendToolCall(paths, token, name, args, options) {
|
|
|
6049
6337
|
}
|
|
6050
6338
|
const result = toToolResult(message, requestId);
|
|
6051
6339
|
if (result)
|
|
6052
|
-
finish(() =>
|
|
6340
|
+
finish(() => resolve10(result));
|
|
6053
6341
|
else
|
|
6054
6342
|
finish(() => reject(new DaemonRequestError("invalid daemon response", requestWritten)));
|
|
6055
6343
|
});
|
|
@@ -6217,18 +6505,18 @@ function canonicalizePathList(value) {
|
|
|
6217
6505
|
return value.split(delimiter4).map((entry) => canonicalizePath(entry) ?? entry).join(delimiter4);
|
|
6218
6506
|
}
|
|
6219
6507
|
function canonicalizePath(value) {
|
|
6220
|
-
if (value === undefined || !
|
|
6508
|
+
if (value === undefined || !isAbsolute6(value) || !existsSync13(value))
|
|
6221
6509
|
return value;
|
|
6222
6510
|
return realpathSync6(value);
|
|
6223
6511
|
}
|
|
6224
6512
|
function projectRootFromOpenCodeConfigPath(path2) {
|
|
6225
6513
|
if (basename4(path2) !== "lsp.json" && basename4(path2) !== "lsp-client.json")
|
|
6226
6514
|
return;
|
|
6227
|
-
const configDir =
|
|
6515
|
+
const configDir = dirname11(path2);
|
|
6228
6516
|
const configDirName = basename4(configDir);
|
|
6229
6517
|
if (configDirName !== ".opencode" && configDirName !== ".omo")
|
|
6230
6518
|
return;
|
|
6231
|
-
return
|
|
6519
|
+
return dirname11(configDir);
|
|
6232
6520
|
}
|
|
6233
6521
|
|
|
6234
6522
|
// src/daemon-server.ts
|
|
@@ -6237,12 +6525,12 @@ import { createServer as createServer2 } from "node:net";
|
|
|
6237
6525
|
|
|
6238
6526
|
// src/ownership.ts
|
|
6239
6527
|
import { randomUUID } from "node:crypto";
|
|
6240
|
-
import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as
|
|
6241
|
-
import { dirname as
|
|
6528
|
+
import { existsSync as existsSync14, lstatSync as lstatSync7, readFileSync as readFileSync8, statSync as statSync5, unlinkSync as unlinkSync4 } from "node:fs";
|
|
6529
|
+
import { dirname as dirname13 } from "node:path";
|
|
6242
6530
|
|
|
6243
6531
|
// src/lock.ts
|
|
6244
|
-
import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as
|
|
6245
|
-
import { dirname as
|
|
6532
|
+
import { closeSync as closeSync3, mkdirSync as mkdirSync4, openSync as openSync3, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync as writeSync3 } from "node:fs";
|
|
6533
|
+
import { dirname as dirname12 } from "node:path";
|
|
6246
6534
|
function isProcessAlive2(pid) {
|
|
6247
6535
|
if (!Number.isInteger(pid) || pid <= 0)
|
|
6248
6536
|
return false;
|
|
@@ -6257,14 +6545,14 @@ function isProcessAlive2(pid) {
|
|
|
6257
6545
|
}
|
|
6258
6546
|
function readLockPid(lockPath) {
|
|
6259
6547
|
try {
|
|
6260
|
-
const pid = Number.parseInt(
|
|
6548
|
+
const pid = Number.parseInt(readFileSync7(lockPath, "utf8").trim(), 10);
|
|
6261
6549
|
return Number.isInteger(pid) ? pid : null;
|
|
6262
6550
|
} catch {
|
|
6263
6551
|
return null;
|
|
6264
6552
|
}
|
|
6265
6553
|
}
|
|
6266
6554
|
function tryAcquireLock(lockPath, ownerPid = process.pid) {
|
|
6267
|
-
mkdirSync4(
|
|
6555
|
+
mkdirSync4(dirname12(lockPath), { recursive: true });
|
|
6268
6556
|
for (let attempt = 0;attempt < 2; attempt += 1) {
|
|
6269
6557
|
const handle = writeLockFile(lockPath, ownerPid);
|
|
6270
6558
|
if (handle)
|
|
@@ -6296,7 +6584,7 @@ function reapStaleLock(lockPath) {
|
|
|
6296
6584
|
}
|
|
6297
6585
|
function unlinkQuietly(path2) {
|
|
6298
6586
|
try {
|
|
6299
|
-
|
|
6587
|
+
unlinkSync3(path2);
|
|
6300
6588
|
} catch (error) {
|
|
6301
6589
|
if (error instanceof Error)
|
|
6302
6590
|
return;
|
|
@@ -6347,11 +6635,11 @@ async function acquireStartupLease(paths, pingOwner) {
|
|
|
6347
6635
|
function ensureDaemonDirectories(paths) {
|
|
6348
6636
|
ensurePrivateDirectory(paths.dir);
|
|
6349
6637
|
if (process.platform !== "win32")
|
|
6350
|
-
ensurePrivateDirectory(
|
|
6638
|
+
ensurePrivateDirectory(dirname13(paths.socket));
|
|
6351
6639
|
}
|
|
6352
6640
|
function readDaemonOwner(paths) {
|
|
6353
6641
|
try {
|
|
6354
|
-
return parseOwner(JSON.parse(
|
|
6642
|
+
return parseOwner(JSON.parse(readFileSync8(paths.owner, "utf8")));
|
|
6355
6643
|
} catch (error) {
|
|
6356
6644
|
if (error instanceof Error)
|
|
6357
6645
|
return null;
|
|
@@ -6430,7 +6718,7 @@ function cleanupDeadOwner(paths, owner) {
|
|
|
6430
6718
|
if (process.platform !== "win32" && existsSync14(owner.endpoint.path)) {
|
|
6431
6719
|
const stat = lstatSync7(owner.endpoint.path);
|
|
6432
6720
|
if (stat.isSocket())
|
|
6433
|
-
|
|
6721
|
+
unlinkSync4(owner.endpoint.path);
|
|
6434
6722
|
}
|
|
6435
6723
|
unlinkQuietly(paths.pid);
|
|
6436
6724
|
unlinkQuietly(paths.endpoint);
|
|
@@ -6478,7 +6766,7 @@ function parseEndpoint(value) {
|
|
|
6478
6766
|
// src/version-reap.ts
|
|
6479
6767
|
import { execFile } from "node:child_process";
|
|
6480
6768
|
import { readdir, readFile, rm } from "node:fs/promises";
|
|
6481
|
-
import { basename as basename5, dirname as
|
|
6769
|
+
import { basename as basename5, dirname as dirname14, join as join9 } from "node:path";
|
|
6482
6770
|
var TERM_GRACE_MS = 5000;
|
|
6483
6771
|
var KILL_GRACE_MS = 1000;
|
|
6484
6772
|
var VERSION_ENTRY_PATTERN = /^v([A-Za-z0-9][A-Za-z0-9._+-]{0,127})$/;
|
|
@@ -6499,7 +6787,7 @@ async function attestDaemonCliProcess(pid, platform, deps = {}) {
|
|
|
6499
6787
|
return isNodeCliDaemonCommand(command.trim());
|
|
6500
6788
|
}
|
|
6501
6789
|
async function reapStaleDaemonVersions(ownPaths, deps = {}) {
|
|
6502
|
-
const baseDir =
|
|
6790
|
+
const baseDir = dirname14(ownPaths.dir);
|
|
6503
6791
|
const platform = deps.platform ?? process.platform;
|
|
6504
6792
|
const isAlive = deps.isAlive ?? isProcessAlive2;
|
|
6505
6793
|
const attest = deps.attest ?? ((pid) => attestDaemonCliProcess(pid, platform));
|
|
@@ -6620,13 +6908,13 @@ function defaultReadProcFile(path2) {
|
|
|
6620
6908
|
return readFile(path2);
|
|
6621
6909
|
}
|
|
6622
6910
|
function defaultExecuteForStdout(file, args) {
|
|
6623
|
-
return new Promise((
|
|
6911
|
+
return new Promise((resolve10) => {
|
|
6624
6912
|
execFile(file, [...args], { encoding: "utf8", maxBuffer: 1024 * 1024, timeout: 1000, windowsHide: true }, (error, stdout) => {
|
|
6625
6913
|
if (error !== null) {
|
|
6626
|
-
|
|
6914
|
+
resolve10(null);
|
|
6627
6915
|
return;
|
|
6628
6916
|
}
|
|
6629
|
-
|
|
6917
|
+
resolve10(stdout);
|
|
6630
6918
|
});
|
|
6631
6919
|
});
|
|
6632
6920
|
}
|
|
@@ -6645,7 +6933,7 @@ async function defaultWaitForExit(pid, timeoutMs) {
|
|
|
6645
6933
|
return true;
|
|
6646
6934
|
if (Date.now() >= deadline)
|
|
6647
6935
|
return false;
|
|
6648
|
-
await new Promise((
|
|
6936
|
+
await new Promise((resolve10) => setTimeout(resolve10, 100));
|
|
6649
6937
|
}
|
|
6650
6938
|
}
|
|
6651
6939
|
function defaultLog(message) {
|
|
@@ -6752,17 +7040,17 @@ async function assertSelfProbe(paths, token, owner) {
|
|
|
6752
7040
|
throw new DaemonStartupDeferredError("self_probe_failed");
|
|
6753
7041
|
}
|
|
6754
7042
|
function listen(server2, socketPath) {
|
|
6755
|
-
return new Promise((
|
|
7043
|
+
return new Promise((resolve10, reject) => {
|
|
6756
7044
|
const onError = (error) => reject(error);
|
|
6757
7045
|
server2.once("error", onError);
|
|
6758
7046
|
server2.listen(socketPath, () => {
|
|
6759
7047
|
server2.removeListener("error", onError);
|
|
6760
|
-
|
|
7048
|
+
resolve10();
|
|
6761
7049
|
});
|
|
6762
7050
|
});
|
|
6763
7051
|
}
|
|
6764
7052
|
function closeServer(server2) {
|
|
6765
|
-
return new Promise((
|
|
7053
|
+
return new Promise((resolve10) => server2.close(() => resolve10()));
|
|
6766
7054
|
}
|
|
6767
7055
|
function installSignalHandlers(close) {
|
|
6768
7056
|
const handler = () => {
|