oh-my-opencode 4.2.2 → 4.2.3
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/README.ja.md +7 -0
- package/README.ko.md +7 -0
- package/README.md +13 -0
- package/README.ru.md +7 -0
- package/README.zh-cn.md +7 -0
- package/dist/cli/doctor/checks/tools-lsp.d.ts +6 -1
- package/dist/cli/index.js +2367 -1240
- package/dist/features/background-agent/parent-wake-notifier.d.ts +1 -1
- package/dist/hooks/comment-checker/apply-patch-edits.d.ts +2 -0
- package/dist/hooks/comment-checker/hook.d.ts +1 -0
- package/dist/hooks/comment-checker/initialization-gate.d.ts +1 -0
- package/dist/hooks/directory-agents-injector/finder.d.ts +4 -2
- package/dist/hooks/directory-agents-injector/injector.d.ts +2 -0
- package/dist/hooks/rules-injector/injector.d.ts +7 -3
- package/dist/hooks/rules-injector/matcher.d.ts +3 -24
- package/dist/hooks/rules-injector/parser.d.ts +2 -18
- package/dist/hooks/rules-injector/project-root-finder.d.ts +1 -13
- package/dist/hooks/rules-injector/rule-distance.d.ts +1 -10
- package/dist/hooks/rules-injector/rule-file-finder.d.ts +2 -6
- package/dist/hooks/rules-injector/rule-file-scanner.d.ts +2 -13
- package/dist/hooks/rules-injector/rule-scan-cache.d.ts +2 -13
- package/dist/hooks/rules-injector/transcript-hydration.d.ts +18 -0
- package/dist/hooks/rules-injector/types.d.ts +2 -38
- package/dist/hooks/runtime-fallback/types.d.ts +1 -0
- package/dist/hooks/team-session-events/team-member-error-handler.d.ts +14 -1
- package/dist/hooks/unstable-agent-babysitter/unstable-agent-babysitter-hook.d.ts +0 -21
- package/dist/index.js +4094 -3170
- package/dist/mcp/ast-grep.d.ts +9 -0
- package/dist/mcp/index.d.ts +4 -1
- package/dist/mcp/types.d.ts +1 -0
- package/dist/plugin/tool-execute-after.d.ts +15 -9
- package/dist/plugin/tool-registry.d.ts +1 -2
- package/dist/plugin-handlers/mcp-config-handler.d.ts +3 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/prompt-async-gate.d.ts +13 -1
- package/dist/shared/prompt-failure-classifier.d.ts +9 -0
- package/dist/shared/prompt-timeout-context.d.ts +1 -0
- package/dist/tools/delegate-task/sync-prompt-sender.d.ts +1 -2
- package/dist/tools/index.d.ts +0 -1
- package/package.json +38 -28
- package/packages/ast-grep-mcp/dist/cli.js +861 -0
- package/packages/lsp-tools-mcp/dist/cli.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/cli.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.js +1 -2
- package/packages/lsp-tools-mcp/dist/lsp/client-wrapper.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client-wrapper.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/config-loader.d.ts +1 -10
- package/packages/lsp-tools-mcp/dist/lsp/config-loader.js +55 -10
- package/packages/lsp-tools-mcp/dist/lsp/connection.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/connection.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/constants.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/directory-diagnostics.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/directory-diagnostics.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/errors.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/errors.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/formatters.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/formatters.js +7 -10
- package/packages/lsp-tools-mcp/dist/lsp/infer-extension.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/infer-extension.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/json-rpc-connection.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/json-rpc-connection.js +10 -11
- package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/language-mappings.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/manager.d.ts +1 -3
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +6 -23
- package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +1 -0
- package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.js +17 -0
- package/packages/lsp-tools-mcp/dist/lsp/process.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/process.js +41 -12
- package/packages/lsp-tools-mcp/dist/lsp/server-definitions.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-definitions.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-installation.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-installation.js +3 -4
- package/packages/lsp-tools-mcp/dist/lsp/server-resolution.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-resolution.js +18 -7
- package/packages/lsp-tools-mcp/dist/lsp/transport.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/transport.js +20 -11
- package/packages/lsp-tools-mcp/dist/lsp/types.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/types.js +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/utils.d.ts +0 -2
- package/packages/lsp-tools-mcp/dist/lsp/utils.js +0 -8
- package/packages/lsp-tools-mcp/dist/lsp/workspace-edit.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/workspace-edit.js +0 -1
- package/packages/lsp-tools-mcp/dist/mcp.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/mcp.js +14 -14
- package/packages/lsp-tools-mcp/dist/tools.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/tools.js +21 -14
- package/dist/tools/ast-grep/cli-binary-path-resolution.d.ts +0 -5
- package/dist/tools/ast-grep/cli.d.ts +0 -12
- package/dist/tools/ast-grep/constants.d.ts +0 -5
- package/dist/tools/ast-grep/downloader.d.ts +0 -5
- package/dist/tools/ast-grep/environment-check.d.ts +0 -20
- package/dist/tools/ast-grep/index.d.ts +0 -5
- package/dist/tools/ast-grep/language-support.d.ts +0 -6
- package/dist/tools/ast-grep/pattern-hints.d.ts +0 -4
- package/dist/tools/ast-grep/process-output-timeout.d.ts +0 -12
- package/dist/tools/ast-grep/result-formatter.d.ts +0 -5
- package/dist/tools/ast-grep/sg-cli-path.d.ts +0 -3
- package/dist/tools/ast-grep/sg-compact-json-output.d.ts +0 -2
- package/dist/tools/ast-grep/tool-descriptions.d.ts +0 -3
- package/dist/tools/ast-grep/tools.d.ts +0 -3
- package/dist/tools/ast-grep/types.d.ts +0 -58
- package/packages/lsp-tools-mcp/dist/cli.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/cli.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client-wrapper.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client-wrapper.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/client.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/config-loader.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/config-loader.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/connection.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/connection.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/constants.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/directory-diagnostics.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/directory-diagnostics.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/errors.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/errors.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/formatters.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/formatters.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/infer-extension.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/infer-extension.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/json-rpc-connection.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/json-rpc-connection.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/language-mappings.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/manager.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/manager.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/process.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/process.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-definitions.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-definitions.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-installation.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-installation.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-resolution.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/server-resolution.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/transport.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/transport.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/types.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/types.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/utils.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/utils.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/workspace-edit.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/workspace-edit.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/mcp.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/mcp.js.map +0 -1
- package/packages/lsp-tools-mcp/dist/tools.d.ts.map +0 -1
- package/packages/lsp-tools-mcp/dist/tools.js.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export function reportBestEffortCleanupError(operation, error) {
|
|
2
|
-
if (process.env
|
|
2
|
+
if (process.env["CODEX_LSP_DEBUG_CLEANUP"] !== "1")
|
|
3
3
|
return;
|
|
4
4
|
const message = error instanceof Error ? error.message : String(error);
|
|
5
5
|
console.error(`[codex-lsp] ignored ${operation} failure during cleanup: ${message}`);
|
|
6
6
|
}
|
|
7
|
-
//# sourceMappingURL=cleanup-errors.js.map
|
|
@@ -11,4 +11,3 @@ export interface WithLspClientOptions {
|
|
|
11
11
|
manager?: LspManager;
|
|
12
12
|
}
|
|
13
13
|
export declare function withLspClient<T>(filePath: string, fn: (client: LspClient) => Promise<T>, toolName: string, options?: WithLspClientOptions): Promise<T>;
|
|
14
|
-
//# sourceMappingURL=client-wrapper.d.ts.map
|
|
@@ -18,4 +18,3 @@ export declare class LspClient extends LspClientConnection {
|
|
|
18
18
|
prepareRename(filePath: string, line: number, character: number): Promise<PrepareRenameResult | PrepareRenameDefaultBehavior | Range | null>;
|
|
19
19
|
rename(filePath: string, line: number, character: number, newName: string): Promise<WorkspaceEdit | null>;
|
|
20
20
|
}
|
|
21
|
-
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import type { ResolvedServer } from "./types.js";
|
|
2
|
-
interface LspEntry {
|
|
3
|
-
disabled?: boolean;
|
|
4
|
-
command?: string[];
|
|
5
|
-
extensions?: string[];
|
|
6
|
-
priority?: number;
|
|
7
|
-
env?: Record<string, string>;
|
|
8
|
-
initialization?: Record<string, unknown>;
|
|
9
|
-
}
|
|
10
2
|
interface ConfigJson {
|
|
11
|
-
lsp?: Record<string,
|
|
3
|
+
lsp?: Record<string, unknown>;
|
|
12
4
|
}
|
|
13
5
|
type ConfigSource = "project" | "user";
|
|
14
6
|
export interface ServerWithSource extends ResolvedServer {
|
|
@@ -22,4 +14,3 @@ export declare function loadAllConfigs(): Map<ConfigSource, ConfigJson>;
|
|
|
22
14
|
export declare function getMergedServers(): ServerWithSource[];
|
|
23
15
|
export declare function getDisabledServerIds(): Set<string>;
|
|
24
16
|
export {};
|
|
25
|
-
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -4,8 +4,8 @@ import { isAbsolute, join } from "node:path";
|
|
|
4
4
|
import { BUILTIN_SERVERS } from "./server-definitions.js";
|
|
5
5
|
export function getConfigPaths() {
|
|
6
6
|
const cwd = process.cwd();
|
|
7
|
-
const projectOverride = process.env
|
|
8
|
-
const userOverride = process.env
|
|
7
|
+
const projectOverride = process.env["LSP_TOOLS_MCP_PROJECT_CONFIG"];
|
|
8
|
+
const userOverride = process.env["LSP_TOOLS_MCP_USER_CONFIG"];
|
|
9
9
|
return {
|
|
10
10
|
project: projectOverride
|
|
11
11
|
? isAbsolute(projectOverride)
|
|
@@ -23,7 +23,8 @@ function loadJsonFile(path) {
|
|
|
23
23
|
if (!existsSync(path))
|
|
24
24
|
return null;
|
|
25
25
|
try {
|
|
26
|
-
|
|
26
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
27
|
+
return isConfigJson(parsed) ? parsed : null;
|
|
27
28
|
}
|
|
28
29
|
catch {
|
|
29
30
|
return null;
|
|
@@ -50,7 +51,10 @@ export function getMergedServers() {
|
|
|
50
51
|
const config = configs.get(source);
|
|
51
52
|
if (!config?.lsp)
|
|
52
53
|
continue;
|
|
53
|
-
for (const [id,
|
|
54
|
+
for (const [id, rawEntry] of Object.entries(config.lsp)) {
|
|
55
|
+
const entry = parseLspEntry(rawEntry);
|
|
56
|
+
if (!entry)
|
|
57
|
+
continue;
|
|
54
58
|
if (entry.disabled) {
|
|
55
59
|
disabled.add(id);
|
|
56
60
|
continue;
|
|
@@ -59,15 +63,20 @@ export function getMergedServers() {
|
|
|
59
63
|
continue;
|
|
60
64
|
if (!entry.command || !entry.extensions)
|
|
61
65
|
continue;
|
|
62
|
-
|
|
66
|
+
const server = {
|
|
63
67
|
id,
|
|
64
68
|
command: entry.command,
|
|
65
69
|
extensions: entry.extensions,
|
|
66
70
|
priority: entry.priority ?? 0,
|
|
67
|
-
env: entry.env,
|
|
68
|
-
initialization: entry.initialization,
|
|
69
71
|
source,
|
|
70
|
-
}
|
|
72
|
+
};
|
|
73
|
+
if (entry.env !== undefined) {
|
|
74
|
+
server.env = entry.env;
|
|
75
|
+
}
|
|
76
|
+
if (entry.initialization !== undefined) {
|
|
77
|
+
server.initialization = entry.initialization;
|
|
78
|
+
}
|
|
79
|
+
servers.push(server);
|
|
71
80
|
seen.add(id);
|
|
72
81
|
}
|
|
73
82
|
}
|
|
@@ -94,17 +103,53 @@ export function getMergedServers() {
|
|
|
94
103
|
return b.priority - a.priority;
|
|
95
104
|
});
|
|
96
105
|
}
|
|
106
|
+
function isConfigJson(value) {
|
|
107
|
+
if (!isRecord(value))
|
|
108
|
+
return false;
|
|
109
|
+
const lsp = value["lsp"];
|
|
110
|
+
return lsp === undefined || isRecord(lsp);
|
|
111
|
+
}
|
|
112
|
+
function parseLspEntry(value) {
|
|
113
|
+
return isLspEntry(value) ? value : null;
|
|
114
|
+
}
|
|
115
|
+
function isLspEntry(value) {
|
|
116
|
+
if (!isRecord(value))
|
|
117
|
+
return false;
|
|
118
|
+
const disabled = value["disabled"];
|
|
119
|
+
const command = value["command"];
|
|
120
|
+
const extensions = value["extensions"];
|
|
121
|
+
const priority = value["priority"];
|
|
122
|
+
const env = value["env"];
|
|
123
|
+
const initialization = value["initialization"];
|
|
124
|
+
return ((disabled === undefined || typeof disabled === "boolean") &&
|
|
125
|
+
(command === undefined || isStringArray(command)) &&
|
|
126
|
+
(extensions === undefined || isStringArray(extensions)) &&
|
|
127
|
+
(priority === undefined || typeof priority === "number") &&
|
|
128
|
+
(env === undefined || isStringRecord(env)) &&
|
|
129
|
+
(initialization === undefined || isRecord(initialization)));
|
|
130
|
+
}
|
|
131
|
+
function isStringArray(value) {
|
|
132
|
+
return Array.isArray(value) && value.every((item) => typeof item === "string");
|
|
133
|
+
}
|
|
134
|
+
function isStringRecord(value) {
|
|
135
|
+
return isRecord(value) && Object.values(value).every((item) => typeof item === "string");
|
|
136
|
+
}
|
|
137
|
+
function isRecord(value) {
|
|
138
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
139
|
+
}
|
|
97
140
|
export function getDisabledServerIds() {
|
|
98
141
|
const configs = loadAllConfigs();
|
|
99
142
|
const disabled = new Set();
|
|
100
143
|
for (const config of configs.values()) {
|
|
101
144
|
if (!config.lsp)
|
|
102
145
|
continue;
|
|
103
|
-
for (const [id,
|
|
146
|
+
for (const [id, rawEntry] of Object.entries(config.lsp)) {
|
|
147
|
+
const entry = parseLspEntry(rawEntry);
|
|
148
|
+
if (!entry)
|
|
149
|
+
continue;
|
|
104
150
|
if (entry.disabled)
|
|
105
151
|
disabled.add(id);
|
|
106
152
|
}
|
|
107
153
|
}
|
|
108
154
|
return disabled;
|
|
109
155
|
}
|
|
110
|
-
//# sourceMappingURL=config-loader.js.map
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import type { SeverityFilter } from "./types.js";
|
|
2
2
|
export declare function collectFilesWithExtension(dir: string, extension: string, maxFiles: number): string[];
|
|
3
3
|
export declare function aggregateDiagnosticsForDirectory(directory: string, extension: string, severity?: SeverityFilter, maxFiles?: number): Promise<string>;
|
|
4
|
-
//# sourceMappingURL=directory-diagnostics.d.ts.map
|
|
@@ -10,4 +10,3 @@ export declare function formatDiagnostic(diag: Diagnostic): string;
|
|
|
10
10
|
export declare function filterDiagnosticsBySeverity(diagnostics: Diagnostic[], severityFilter?: SeverityFilter): Diagnostic[];
|
|
11
11
|
export declare function formatPrepareRenameResult(result: PrepareRenameResult | PrepareRenameDefaultBehavior | Range | null): string;
|
|
12
12
|
export declare function formatApplyResult(result: ApplyResult): string;
|
|
13
|
-
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import { fileURLToPath } from "node:url";
|
|
2
2
|
import { SEVERITY_MAP, SYMBOL_KIND_MAP } from "./language-mappings.js";
|
|
3
|
+
const DIAGNOSTIC_SEVERITY_FILTERS = {
|
|
4
|
+
error: 1,
|
|
5
|
+
warning: 2,
|
|
6
|
+
information: 3,
|
|
7
|
+
hint: 4,
|
|
8
|
+
};
|
|
3
9
|
export function uriToPath(uri) {
|
|
4
10
|
return fileURLToPath(uri);
|
|
5
11
|
}
|
|
@@ -53,15 +59,7 @@ export function filterDiagnosticsBySeverity(diagnostics, severityFilter) {
|
|
|
53
59
|
if (!severityFilter || severityFilter === "all") {
|
|
54
60
|
return diagnostics;
|
|
55
61
|
}
|
|
56
|
-
const
|
|
57
|
-
error: 1,
|
|
58
|
-
warning: 2,
|
|
59
|
-
information: 3,
|
|
60
|
-
hint: 4,
|
|
61
|
-
};
|
|
62
|
-
const targetSeverity = severityMap[severityFilter];
|
|
63
|
-
if (targetSeverity === undefined)
|
|
64
|
-
return diagnostics;
|
|
62
|
+
const targetSeverity = DIAGNOSTIC_SEVERITY_FILTERS[severityFilter];
|
|
65
63
|
return diagnostics.filter((d) => d.severity === targetSeverity);
|
|
66
64
|
}
|
|
67
65
|
export function formatPrepareRenameResult(result) {
|
|
@@ -106,4 +104,3 @@ export function formatApplyResult(result) {
|
|
|
106
104
|
}
|
|
107
105
|
return lines.join("\n");
|
|
108
106
|
}
|
|
109
|
-
//# sourceMappingURL=formatters.js.map
|
|
@@ -135,7 +135,7 @@ export class JsonRpcConnection {
|
|
|
135
135
|
this.handleResponse(parsed);
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
|
-
if (typeof parsed
|
|
138
|
+
if (typeof parsed["method"] !== "string") {
|
|
139
139
|
const id = getMessageId(parsed) ?? null;
|
|
140
140
|
void this.writeError(id, INVALID_REQUEST, "Invalid JSON-RPC method").catch((error) => this.emitError(toError(error)));
|
|
141
141
|
return;
|
|
@@ -144,7 +144,7 @@ export class JsonRpcConnection {
|
|
|
144
144
|
this.handleRequest(parsed);
|
|
145
145
|
return;
|
|
146
146
|
}
|
|
147
|
-
this.handleNotification(parsed
|
|
147
|
+
this.handleNotification(parsed["method"], parsed["params"]);
|
|
148
148
|
}
|
|
149
149
|
handleResponse(message) {
|
|
150
150
|
const id = getMessageId(message);
|
|
@@ -155,10 +155,10 @@ export class JsonRpcConnection {
|
|
|
155
155
|
return;
|
|
156
156
|
this.pendingRequests.delete(String(id));
|
|
157
157
|
if ("error" in message) {
|
|
158
|
-
pending.reject(jsonRpcErrorToError(message
|
|
158
|
+
pending.reject(jsonRpcErrorToError(message["error"]));
|
|
159
159
|
return;
|
|
160
160
|
}
|
|
161
|
-
pending.resolve(message
|
|
161
|
+
pending.resolve(message["result"]);
|
|
162
162
|
}
|
|
163
163
|
handleNotification(method, params) {
|
|
164
164
|
const handler = this.notificationHandlers.get(method);
|
|
@@ -177,14 +177,14 @@ export class JsonRpcConnection {
|
|
|
177
177
|
void this.writeError(null, INVALID_REQUEST, "Invalid JSON-RPC id").catch((error) => this.emitError(toError(error)));
|
|
178
178
|
return;
|
|
179
179
|
}
|
|
180
|
-
const method = typeof message
|
|
180
|
+
const method = typeof message["method"] === "string" ? message["method"] : "";
|
|
181
181
|
const handler = this.requestHandlers.get(method);
|
|
182
182
|
if (!handler) {
|
|
183
183
|
void this.writeError(id, METHOD_NOT_FOUND, `Method not found: ${method}`).catch((error) => this.emitError(toError(error)));
|
|
184
184
|
return;
|
|
185
185
|
}
|
|
186
186
|
Promise.resolve()
|
|
187
|
-
.then(() => handler(message
|
|
187
|
+
.then(() => handler(message["params"]))
|
|
188
188
|
.then((result) => this.writeMessage({ jsonrpc: "2.0", id, result }), (error) => this.writeError(id, INTERNAL_ERROR, toError(error).message))
|
|
189
189
|
.catch((error) => this.emitError(toError(error)));
|
|
190
190
|
}
|
|
@@ -227,7 +227,7 @@ function isJsonRpcObject(value) {
|
|
|
227
227
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
228
228
|
}
|
|
229
229
|
function getMessageId(message) {
|
|
230
|
-
const id = message
|
|
230
|
+
const id = message["id"];
|
|
231
231
|
if (typeof id === "number" || typeof id === "string" || id === null)
|
|
232
232
|
return id;
|
|
233
233
|
return undefined;
|
|
@@ -235,14 +235,13 @@ function getMessageId(message) {
|
|
|
235
235
|
function jsonRpcErrorToError(value) {
|
|
236
236
|
if (!isJsonRpcObject(value))
|
|
237
237
|
return new Error("JSON-RPC request failed");
|
|
238
|
-
const message = typeof value
|
|
238
|
+
const message = typeof value["message"] === "string" ? value["message"] : "JSON-RPC request failed";
|
|
239
239
|
const error = new Error(message);
|
|
240
|
-
if (typeof value
|
|
241
|
-
error.name = `JsonRpcError(${value
|
|
240
|
+
if (typeof value["code"] === "number") {
|
|
241
|
+
error.name = `JsonRpcError(${value["code"]})`;
|
|
242
242
|
}
|
|
243
243
|
return error;
|
|
244
244
|
}
|
|
245
245
|
function toError(error) {
|
|
246
246
|
return error instanceof Error ? error : new Error(String(error));
|
|
247
247
|
}
|
|
248
|
-
//# sourceMappingURL=json-rpc-connection.js.map
|
|
@@ -2,4 +2,3 @@ export declare const SYMBOL_KIND_MAP: Record<number, string>;
|
|
|
2
2
|
export declare const SEVERITY_MAP: Record<number, string>;
|
|
3
3
|
export declare const EXT_TO_LANG: Record<string, string>;
|
|
4
4
|
export declare function getLanguageId(ext: string): string;
|
|
5
|
-
//# sourceMappingURL=language-mappings.d.ts.map
|
|
@@ -20,7 +20,7 @@ export interface LspManagerOptions {
|
|
|
20
20
|
export declare class LspManager {
|
|
21
21
|
private readonly clients;
|
|
22
22
|
private reaperHandle;
|
|
23
|
-
private
|
|
23
|
+
private signalDisposer;
|
|
24
24
|
private disposed;
|
|
25
25
|
private readonly idleTimeoutMs;
|
|
26
26
|
private readonly initTimeoutMs;
|
|
@@ -29,7 +29,6 @@ export declare class LspManager {
|
|
|
29
29
|
private readonly now;
|
|
30
30
|
constructor(options?: LspManagerOptions);
|
|
31
31
|
private startReaper;
|
|
32
|
-
private installProcessExitHandler;
|
|
33
32
|
private getKey;
|
|
34
33
|
private reapStale;
|
|
35
34
|
private tryDeleteIfOrphaned;
|
|
@@ -45,4 +44,3 @@ export declare class LspManager {
|
|
|
45
44
|
}
|
|
46
45
|
export declare function getLspManager(): LspManager;
|
|
47
46
|
export declare function disposeDefaultLspManager(): Promise<void>;
|
|
48
|
-
//# sourceMappingURL=manager.d.ts.map
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { reportBestEffortCleanupError } from "./cleanup-errors.js";
|
|
2
2
|
import { LspClient } from "./client.js";
|
|
3
3
|
import { IDLE_TIMEOUT_MS, INIT_TIMEOUT_MS, REAPER_INTERVAL_MS } from "./constants.js";
|
|
4
|
+
import { installProcessSignalCleanup } from "./process-signal-cleanup.js";
|
|
4
5
|
async function stopClientBestEffort(client) {
|
|
5
6
|
try {
|
|
6
7
|
await client.stop();
|
|
@@ -44,7 +45,7 @@ export class LspManager {
|
|
|
44
45
|
constructor(options = {}) {
|
|
45
46
|
this.clients = new Map();
|
|
46
47
|
this.reaperHandle = null;
|
|
47
|
-
this.
|
|
48
|
+
this.signalDisposer = null;
|
|
48
49
|
this.disposed = false;
|
|
49
50
|
this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
|
|
50
51
|
this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
|
|
@@ -52,7 +53,7 @@ export class LspManager {
|
|
|
52
53
|
this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
|
|
53
54
|
this.now = options.now ?? (() => Date.now());
|
|
54
55
|
this.startReaper();
|
|
55
|
-
this.
|
|
56
|
+
this.signalDisposer = installProcessSignalCleanup(() => this.stopAll());
|
|
56
57
|
}
|
|
57
58
|
startReaper() {
|
|
58
59
|
if (this.reaperHandle)
|
|
@@ -64,23 +65,6 @@ export class LspManager {
|
|
|
64
65
|
this.reaperHandle.unref();
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
|
-
installProcessExitHandler() {
|
|
68
|
-
const handler = () => {
|
|
69
|
-
for (const managed of this.clients.values()) {
|
|
70
|
-
try {
|
|
71
|
-
void stopClientBestEffort(managed.client);
|
|
72
|
-
}
|
|
73
|
-
catch (error) {
|
|
74
|
-
reportBestEffortCleanupError("exit handler client stop", error);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
this.clients.clear();
|
|
78
|
-
};
|
|
79
|
-
process.on("exit", handler);
|
|
80
|
-
this.exitDisposer = () => {
|
|
81
|
-
process.removeListener("exit", handler);
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
68
|
getKey(root, serverId) {
|
|
85
69
|
return `${root}::${serverId}`;
|
|
86
70
|
}
|
|
@@ -279,9 +263,9 @@ export class LspManager {
|
|
|
279
263
|
clearInterval(this.reaperHandle);
|
|
280
264
|
this.reaperHandle = null;
|
|
281
265
|
}
|
|
282
|
-
if (this.
|
|
283
|
-
this.
|
|
284
|
-
this.
|
|
266
|
+
if (this.signalDisposer) {
|
|
267
|
+
this.signalDisposer();
|
|
268
|
+
this.signalDisposer = null;
|
|
285
269
|
}
|
|
286
270
|
const stopPromises = [];
|
|
287
271
|
for (const managed of this.clients.values()) {
|
|
@@ -305,4 +289,3 @@ export async function disposeDefaultLspManager() {
|
|
|
305
289
|
await m.stopAll();
|
|
306
290
|
}
|
|
307
291
|
}
|
|
308
|
-
//# sourceMappingURL=manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function installProcessSignalCleanup(cleanup: () => Promise<void>): () => void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { reportBestEffortCleanupError } from "./cleanup-errors.js";
|
|
2
|
+
export function installProcessSignalCleanup(cleanup) {
|
|
3
|
+
const signals = process.platform === "win32" ? ["SIGINT", "SIGTERM", "SIGBREAK"] : ["SIGINT", "SIGTERM"];
|
|
4
|
+
const handler = () => {
|
|
5
|
+
void cleanup().catch((error) => {
|
|
6
|
+
reportBestEffortCleanupError("signal cleanup", error);
|
|
7
|
+
});
|
|
8
|
+
};
|
|
9
|
+
for (const signal of signals) {
|
|
10
|
+
process.on(signal, handler);
|
|
11
|
+
}
|
|
12
|
+
return () => {
|
|
13
|
+
for (const signal of signals) {
|
|
14
|
+
process.removeListener(signal, handler);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}
|
|
@@ -23,4 +23,3 @@ export declare function validateCwd(cwd: string): {
|
|
|
23
23
|
};
|
|
24
24
|
export declare function createSpawnCommand(command: string[], platform?: NodeJS.Platform, commandProcessor?: string, env?: Record<string, string | undefined>): PreparedSpawnCommand;
|
|
25
25
|
export declare function spawnProcess(command: string[], options: SpawnOptions): SpawnedProcess;
|
|
26
|
-
//# sourceMappingURL=process.d.ts.map
|
|
@@ -1,8 +1,18 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
1
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, statSync } from "node:fs";
|
|
3
3
|
import { delimiter, join } from "node:path";
|
|
4
4
|
import { reportBestEffortCleanupError } from "./cleanup-errors.js";
|
|
5
5
|
import { LspInvalidPathError, LspProcessSpawnError } from "./errors.js";
|
|
6
|
+
function isMissingProcessError(error) {
|
|
7
|
+
if (!(error instanceof Error) || !("code" in error))
|
|
8
|
+
return false;
|
|
9
|
+
return error.code === "ESRCH";
|
|
10
|
+
}
|
|
11
|
+
function reportKillError(context, error) {
|
|
12
|
+
if (!isMissingProcessError(error)) {
|
|
13
|
+
reportBestEffortCleanupError(context, error);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
6
16
|
export function validateCwd(cwd) {
|
|
7
17
|
try {
|
|
8
18
|
if (!existsSync(cwd)) {
|
|
@@ -44,15 +54,34 @@ function wrap(proc) {
|
|
|
44
54
|
},
|
|
45
55
|
exited: exitedPromise,
|
|
46
56
|
kill(signal) {
|
|
47
|
-
|
|
48
|
-
proc.kill(signal ?? "SIGTERM");
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
reportBestEffortCleanupError("process kill", error);
|
|
52
|
-
}
|
|
57
|
+
killProcessTree(proc, signal ?? "SIGTERM");
|
|
53
58
|
},
|
|
54
59
|
};
|
|
55
60
|
}
|
|
61
|
+
function killProcessTree(proc, signal) {
|
|
62
|
+
if (process.platform === "win32" && proc.pid) {
|
|
63
|
+
const result = spawnSync("taskkill", ["/pid", String(proc.pid), "/f", "/t"], { stdio: "ignore" });
|
|
64
|
+
if (!result.error && result.status === 0)
|
|
65
|
+
return;
|
|
66
|
+
if (result.error)
|
|
67
|
+
reportKillError("windows process tree kill", result.error);
|
|
68
|
+
}
|
|
69
|
+
if (process.platform !== "win32" && proc.pid) {
|
|
70
|
+
try {
|
|
71
|
+
process.kill(-proc.pid, signal);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
reportKillError("process group kill", error);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
proc.kill(signal);
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
reportKillError("process kill", error);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
56
85
|
function isWindowsShellShim(command) {
|
|
57
86
|
const lowerCommand = command.toLowerCase();
|
|
58
87
|
return lowerCommand.endsWith(".cmd") || lowerCommand.endsWith(".bat");
|
|
@@ -62,7 +91,7 @@ function splitPath(pathValue, platform) {
|
|
|
62
91
|
return pathValue.split(separator).filter(Boolean);
|
|
63
92
|
}
|
|
64
93
|
function getWindowsPathExtensions(env) {
|
|
65
|
-
const rawExtensions = env
|
|
94
|
+
const rawExtensions = env["PATHEXT"] ?? ".COM;.EXE;.BAT;.CMD";
|
|
66
95
|
const extensions = rawExtensions
|
|
67
96
|
.split(";")
|
|
68
97
|
.map((extension) => extension.trim())
|
|
@@ -72,7 +101,7 @@ function getWindowsPathExtensions(env) {
|
|
|
72
101
|
}
|
|
73
102
|
function resolveWindowsCommand(command, env) {
|
|
74
103
|
const hasPathSeparator = command.includes("/") || command.includes("\\");
|
|
75
|
-
const pathValue = env
|
|
104
|
+
const pathValue = env["PATH"] ?? env["Path"] ?? "";
|
|
76
105
|
const baseDirectories = hasPathSeparator ? [""] : splitPath(pathValue, "win32");
|
|
77
106
|
const extensions = getWindowsPathExtensions(env);
|
|
78
107
|
for (const baseDirectory of baseDirectories) {
|
|
@@ -84,7 +113,7 @@ function resolveWindowsCommand(command, env) {
|
|
|
84
113
|
}
|
|
85
114
|
return command;
|
|
86
115
|
}
|
|
87
|
-
export function createSpawnCommand(command, platform = process.platform, commandProcessor = process.env
|
|
116
|
+
export function createSpawnCommand(command, platform = process.platform, commandProcessor = process.env["ComSpec"] ?? "cmd.exe", env = process.env) {
|
|
88
117
|
const [cmd, ...args] = command;
|
|
89
118
|
if (!cmd) {
|
|
90
119
|
throw new LspProcessSpawnError("[lsp] empty command");
|
|
@@ -111,14 +140,14 @@ export function spawnProcess(command, options) {
|
|
|
111
140
|
if (!cmd) {
|
|
112
141
|
throw new LspProcessSpawnError("[lsp] empty command");
|
|
113
142
|
}
|
|
114
|
-
const preparedCommand = createSpawnCommand(command, process.platform, process.env
|
|
143
|
+
const preparedCommand = createSpawnCommand(command, process.platform, process.env["ComSpec"] ?? "cmd.exe", options.env);
|
|
115
144
|
const proc = spawn(preparedCommand.command, preparedCommand.args, {
|
|
116
145
|
cwd: options.cwd,
|
|
117
146
|
env: options.env,
|
|
118
147
|
stdio: ["pipe", "pipe", "pipe"],
|
|
119
148
|
windowsHide: true,
|
|
120
149
|
shell: preparedCommand.shell,
|
|
150
|
+
detached: process.platform !== "win32",
|
|
121
151
|
});
|
|
122
152
|
return wrap(proc);
|
|
123
153
|
}
|
|
124
|
-
//# sourceMappingURL=process.js.map
|
|
@@ -2,4 +2,3 @@ import type { LspServerConfig } from "./types.js";
|
|
|
2
2
|
export declare const LSP_INSTALL_HINTS: Record<string, string>;
|
|
3
3
|
export declare const BUILTIN_SERVERS: Record<string, Omit<LspServerConfig, "id">>;
|
|
4
4
|
export declare const AUTO_INSTALLABLE_SERVERS: Record<string, string[]>;
|
|
5
|
-
//# sourceMappingURL=server-definitions.d.ts.map
|
|
@@ -16,7 +16,7 @@ export function isServerInstalled(command) {
|
|
|
16
16
|
const isWindows = process.platform === "win32";
|
|
17
17
|
let exts = [""];
|
|
18
18
|
if (isWindows) {
|
|
19
|
-
const pathExt = process.env
|
|
19
|
+
const pathExt = process.env["PATHEXT"] ?? "";
|
|
20
20
|
if (pathExt) {
|
|
21
21
|
const systemExts = pathExt.split(";").filter(Boolean);
|
|
22
22
|
exts = [...new Set([...exts, ...systemExts, ".exe", ".cmd", ".bat", ".ps1"])];
|
|
@@ -25,9 +25,9 @@ export function isServerInstalled(command) {
|
|
|
25
25
|
exts = ["", ".exe", ".cmd", ".bat", ".ps1"];
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
let pathEnv = process.env
|
|
28
|
+
let pathEnv = process.env["PATH"] ?? "";
|
|
29
29
|
if (isWindows && !pathEnv) {
|
|
30
|
-
pathEnv = process.env
|
|
30
|
+
pathEnv = process.env["Path"] ?? "";
|
|
31
31
|
}
|
|
32
32
|
const paths = pathEnv.split(delimiter);
|
|
33
33
|
for (const p of paths) {
|
|
@@ -48,4 +48,3 @@ export function isServerInstalled(command) {
|
|
|
48
48
|
return true;
|
|
49
49
|
return false;
|
|
50
50
|
}
|
|
51
|
-
//# sourceMappingURL=server-installation.js.map
|