@ai-agent-forge/plugin-lsp-diagnostics 0.85.0

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.
@@ -0,0 +1,396 @@
1
+ import { spawn } from "node:child_process";
2
+ import { existsSync, statSync } from "node:fs";
3
+ import { readFile } from "node:fs/promises";
4
+ import { isAbsolute, join, resolve } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { sanitizeLspDiagnosticsTextV1 } from "./node-adapter.js";
7
+ const LSP_DIAGNOSTICS_STABLE_MS_V1 = 300;
8
+ const LSP_DIAGNOSTICS_TIMEOUT_MS_V1 = 15_000;
9
+ const TSSERVER_DIAGNOSTICS_TIMEOUT_MS_V1 = 15_000;
10
+ const MAX_SERVER_STDOUT_BYTES_V1 = 8 * 1024 * 1024;
11
+ const SERVER_LANGUAGE_V1 = {
12
+ typescript: "typescript",
13
+ javascript: "typescript",
14
+ python: "python",
15
+ c: "c",
16
+ cpp: "c",
17
+ };
18
+ function pathExecutableV1(name, pathEnv) {
19
+ if (typeof pathEnv !== "string" || pathEnv.trim() === "")
20
+ return undefined;
21
+ const names = process.platform === "win32" ? [`${name}.exe`, `${name}.cmd`] : [name];
22
+ for (const directory of pathEnv.split(process.platform === "win32" ? ";" : ":")) {
23
+ if (directory.trim() === "")
24
+ continue;
25
+ for (const candidate of names) {
26
+ const resolved = join(directory, candidate);
27
+ if (existsSync(resolved))
28
+ return resolved;
29
+ }
30
+ }
31
+ return undefined;
32
+ }
33
+ /**
34
+ * Host-owned language-server resolution: tsserver from the workspace-local
35
+ * TypeScript install, pyright from the workspace-local npm package or PATH,
36
+ * clangd from PATH. Unresolved languages stay absent so the wiring fails
37
+ * closed; `servers` injects deterministic overrides for tests.
38
+ */
39
+ export function resolveLspServersV1(options) {
40
+ if (options.servers !== undefined)
41
+ return options.servers;
42
+ const pathEnv = options.pathEnv ?? process.env.PATH;
43
+ const map = {};
44
+ const tsserver = join(options.workspaceDirectory, "node_modules", "typescript", "lib", "tsserver.js");
45
+ if (isAbsolute(options.workspaceDirectory) && existsSync(tsserver))
46
+ map.typescript = { command: process.execPath, args: [tsserver] };
47
+ const pyrightLocal = join(options.workspaceDirectory, "node_modules", "pyright", "dist", "pyright-langserver.js");
48
+ if (isAbsolute(options.workspaceDirectory) && existsSync(pyrightLocal))
49
+ map.python = { command: process.execPath, args: [pyrightLocal, "--stdio"] };
50
+ const pyrightPath = pathExecutableV1("pyright-langserver", pathEnv);
51
+ if (map.python === undefined && pyrightPath !== undefined)
52
+ map.python = { command: pyrightPath, args: ["--stdio"] };
53
+ const clangd = pathExecutableV1("clangd", pathEnv);
54
+ if (clangd !== undefined)
55
+ map.c = { command: clangd, args: [] };
56
+ return map;
57
+ }
58
+ function lspSeverityV1(value) {
59
+ if (value === 1)
60
+ return "error";
61
+ if (value === 2)
62
+ return "warning";
63
+ if (value === 3)
64
+ return "info";
65
+ if (value === 4)
66
+ return "hint";
67
+ return "info";
68
+ }
69
+ function tsserverCategoryV1(value) {
70
+ if (value === "error")
71
+ return "error";
72
+ if (value === "warning")
73
+ return "warning";
74
+ if (value === "suggestion")
75
+ return "hint";
76
+ return "info";
77
+ }
78
+ function spawnServerV1(spec, signal) {
79
+ const child = spawn(spec.command, spec.args, {
80
+ shell: false,
81
+ windowsHide: true,
82
+ stdio: ["pipe", "pipe", "ignore"],
83
+ signal,
84
+ });
85
+ if (child.stdout === null || child.stdin === null) {
86
+ child.kill();
87
+ return undefined;
88
+ }
89
+ return {
90
+ stdout: child.stdout,
91
+ write: (chunk) => child.stdin.write(chunk),
92
+ kill: () => child.kill(),
93
+ exit: new Promise((resolveExit) => {
94
+ child.once("exit", () => resolveExit());
95
+ child.once("error", () => resolveExit());
96
+ }),
97
+ };
98
+ }
99
+ /** Frame reader over stdio: either Content-Length framed (LSP) or line-delimited JSON (tsserver). */
100
+ async function* readMessagesV1(server, framed) {
101
+ let buffer = "";
102
+ for await (const chunk of server.stdout) {
103
+ buffer += chunk.toString("utf8");
104
+ if (buffer.length > MAX_SERVER_STDOUT_BYTES_V1)
105
+ return;
106
+ if (framed) {
107
+ for (;;) {
108
+ const headerEnd = buffer.indexOf("\r\n\r\n");
109
+ if (headerEnd === -1)
110
+ break;
111
+ const header = buffer.slice(0, headerEnd);
112
+ const lengthMatch = header.match(/Content-Length:\s*(\d+)/i);
113
+ if (lengthMatch === null)
114
+ return;
115
+ const length = Number(lengthMatch[1]);
116
+ const bodyStart = headerEnd + 4;
117
+ if (buffer.length < bodyStart + length)
118
+ break;
119
+ yield buffer.slice(bodyStart, bodyStart + length);
120
+ buffer = buffer.slice(bodyStart + length);
121
+ }
122
+ }
123
+ else {
124
+ for (;;) {
125
+ const lineEnd = buffer.indexOf("\n");
126
+ if (lineEnd === -1)
127
+ break;
128
+ const line = buffer.slice(0, lineEnd).trim();
129
+ buffer = buffer.slice(lineEnd + 1);
130
+ if (line !== "")
131
+ yield line;
132
+ }
133
+ }
134
+ }
135
+ }
136
+ function safePositionV1(value) {
137
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0 ? value : 0;
138
+ }
139
+ function parseLspDiagnosticsV1(documentPath, params) {
140
+ if (typeof params !== "object" || params === null)
141
+ return [];
142
+ const diagnostics = params.diagnostics;
143
+ if (!Array.isArray(diagnostics))
144
+ return [];
145
+ const projected = [];
146
+ for (const raw of diagnostics) {
147
+ if (typeof raw !== "object" || raw === null)
148
+ continue;
149
+ const item = raw;
150
+ const message = typeof item.message === "string" ? sanitizeLspDiagnosticsTextV1(item.message) : "";
151
+ if (message === "")
152
+ continue;
153
+ const line = safePositionV1(item.range?.start?.line);
154
+ const column = safePositionV1(item.range?.start?.character);
155
+ const endLine = Math.max(line, safePositionV1(item.range?.end?.line));
156
+ const endColumn = endLine === line
157
+ ? Math.max(column, safePositionV1(item.range?.end?.character))
158
+ : safePositionV1(item.range?.end?.character);
159
+ projected.push({
160
+ file: documentPath,
161
+ range: { start: { line, column }, end: { line: endLine, column: endColumn } },
162
+ severity: lspSeverityV1(item.severity),
163
+ ...(typeof item.code === "string" || (typeof item.code === "number" && Number.isSafeInteger(item.code))
164
+ ? { code: item.code }
165
+ : {}),
166
+ ...(typeof item.source === "string" ? { source: sanitizeLspDiagnosticsTextV1(item.source, 128) } : {}),
167
+ message,
168
+ });
169
+ }
170
+ return projected;
171
+ }
172
+ function parseTsserverDiagnosticsV1(documentPath, body) {
173
+ if (typeof body !== "object" || body === null)
174
+ return [];
175
+ const diagnostics = body.diagnostics;
176
+ if (!Array.isArray(diagnostics))
177
+ return [];
178
+ const projected = [];
179
+ for (const raw of diagnostics) {
180
+ if (typeof raw !== "object" || raw === null)
181
+ continue;
182
+ const item = raw;
183
+ const message = typeof item.text === "string" ? sanitizeLspDiagnosticsTextV1(item.text) : "";
184
+ if (message === "")
185
+ continue;
186
+ // tsserver positions are 1-based; normalize to the 0-based public shape.
187
+ const line = Math.max(0, safePositionV1(item.start?.line) - 1);
188
+ const column = Math.max(0, safePositionV1(item.start?.offset) - 1);
189
+ const endLine = Math.max(line, Math.max(0, safePositionV1(item.end?.line) - 1));
190
+ const endColumn = endLine === line
191
+ ? Math.max(column, Math.max(0, safePositionV1(item.end?.offset) - 1))
192
+ : Math.max(0, safePositionV1(item.end?.offset) - 1);
193
+ projected.push({
194
+ file: documentPath,
195
+ range: { start: { line, column }, end: { line: endLine, column: endColumn } },
196
+ severity: tsserverCategoryV1(item.category),
197
+ ...(typeof item.code === "number" && Number.isSafeInteger(item.code) ? { code: item.code } : {}),
198
+ message,
199
+ });
200
+ }
201
+ return projected;
202
+ }
203
+ /**
204
+ * LSP push client: initialize → didOpen → collect publishDiagnostics →
205
+ * shutdown. The server stream is consumed by exactly one loop — breaking out
206
+ * of a for-await over a Node stream destroys it, so phase transitions happen
207
+ * inside the loop and the stability window resolves the shared promise
208
+ * without interrupting the iteration.
209
+ */
210
+ async function diagnoseWithLspServerV1(spec, relativePath, absolutePath, language, text, signal) {
211
+ const server = spawnServerV1(spec, signal);
212
+ if (server === undefined)
213
+ return undefined;
214
+ let sequence = 0;
215
+ const nextId = () => ++sequence;
216
+ const send = (message) => {
217
+ const payload = Buffer.from(JSON.stringify(message), "utf8");
218
+ server.write(`Content-Length: ${payload.byteLength}\r\n\r\n${payload.toString("utf8")}`);
219
+ };
220
+ const uri = pathToFileURL(absolutePath).href;
221
+ try {
222
+ const consumed = new Promise((resolveConsume) => {
223
+ let stableTimer;
224
+ let latest;
225
+ // The stability window arms only after the first push so cold-start
226
+ // servers are not cut off before their first diagnostics.
227
+ const arm = () => {
228
+ clearTimeout(stableTimer);
229
+ stableTimer = setTimeout(() => resolveConsume(latest), LSP_DIAGNOSTICS_STABLE_MS_V1);
230
+ };
231
+ void (async () => {
232
+ send({ jsonrpc: "2.0", id: nextId(), method: "initialize", params: { processId: null, capabilities: {} } });
233
+ let initialized = false;
234
+ for await (const raw of readMessagesV1(server, true)) {
235
+ let message;
236
+ try {
237
+ message = JSON.parse(raw);
238
+ }
239
+ catch {
240
+ continue;
241
+ }
242
+ if (message.id !== undefined && message.method === undefined) {
243
+ if (!initialized) {
244
+ initialized = true;
245
+ send({ jsonrpc: "2.0", method: "initialized", params: {} });
246
+ send({
247
+ jsonrpc: "2.0",
248
+ method: "textDocument/didOpen",
249
+ params: { textDocument: { uri, languageId: language, version: 1, text } },
250
+ });
251
+ }
252
+ continue;
253
+ }
254
+ if (message.method === "textDocument/publishDiagnostics") {
255
+ const pushed = parseLspDiagnosticsV1(relativePath, message.params);
256
+ if (pushed.length > 0) {
257
+ latest = pushed;
258
+ arm();
259
+ }
260
+ }
261
+ }
262
+ resolveConsume(latest);
263
+ })().catch(() => resolveConsume(latest));
264
+ });
265
+ const timeout = new Promise((resolveTimeout) => {
266
+ setTimeout(() => resolveTimeout(undefined), LSP_DIAGNOSTICS_TIMEOUT_MS_V1);
267
+ });
268
+ const result = await Promise.race([consumed, timeout]);
269
+ send({ jsonrpc: "2.0", id: nextId(), method: "shutdown", params: null });
270
+ send({ jsonrpc: "2.0", method: "exit" });
271
+ return result;
272
+ }
273
+ finally {
274
+ server.kill();
275
+ await server.exit;
276
+ }
277
+ }
278
+ /** tsserver client: configure → open → geterr → syntaxDiag/semanticDiag events. */
279
+ async function diagnoseWithTsserverV1(spec, relativePath, absolutePath, text, signal) {
280
+ const server = spawnServerV1(spec, signal);
281
+ if (server === undefined)
282
+ return undefined;
283
+ let sequence = 0;
284
+ const send = (command, argumentsValue) => {
285
+ server.write(`${JSON.stringify({ seq: ++sequence, type: "request", command, arguments: argumentsValue })}\n`);
286
+ };
287
+ const collected = [];
288
+ const received = { syntax: false, semantic: false };
289
+ try {
290
+ send("configure", { hostInfo: "agent-forge" });
291
+ send("open", { file: absolutePath, fileContent: text });
292
+ send("geterr", { file: absolutePath, delay: 0 });
293
+ const timeout = new Promise((resolveTimeout) => {
294
+ setTimeout(() => resolveTimeout(undefined), TSSERVER_DIAGNOSTICS_TIMEOUT_MS_V1);
295
+ });
296
+ const collectedPromise = (async () => {
297
+ for await (const raw of readMessagesV1(server, false)) {
298
+ let message;
299
+ try {
300
+ message = JSON.parse(raw);
301
+ }
302
+ catch {
303
+ continue;
304
+ }
305
+ if (message.type !== "event")
306
+ continue;
307
+ if (message.event === "syntaxDiag" || message.event === "syntacticDiag") {
308
+ collected.push(...parseTsserverDiagnosticsV1(relativePath, message.body));
309
+ received.syntax = true;
310
+ }
311
+ if (message.event === "semanticDiag") {
312
+ collected.push(...parseTsserverDiagnosticsV1(relativePath, message.body));
313
+ received.semantic = true;
314
+ }
315
+ if (received.syntax && received.semantic)
316
+ break;
317
+ }
318
+ return collected;
319
+ })().catch(() => collected);
320
+ const result = await Promise.race([collectedPromise, timeout]);
321
+ send("exit", {});
322
+ return result;
323
+ }
324
+ finally {
325
+ server.kill();
326
+ await server.exit;
327
+ }
328
+ }
329
+ function resolveDocumentPathV1(workspaceDirectory, request) {
330
+ const documentPath = request.documentPath;
331
+ if (typeof documentPath !== "string" || documentPath.trim() === "" || !isAbsolute(workspaceDirectory))
332
+ return undefined;
333
+ const absolute = resolve(workspaceDirectory, documentPath);
334
+ const root = resolve(workspaceDirectory);
335
+ if (!absolute.startsWith(root + (root.endsWith("\\") || root.endsWith("/") ? "" : "\\")) && absolute !== root)
336
+ return undefined;
337
+ try {
338
+ if (!existsSync(absolute) || !statSync(absolute).isFile())
339
+ return undefined;
340
+ }
341
+ catch {
342
+ return undefined;
343
+ }
344
+ return absolute;
345
+ }
346
+ /**
347
+ * Real language-server host over one workspace directory: resolves servers per
348
+ * language (tsserver/pyright/clangd), opens the requested workspace-relative
349
+ * document, collects push diagnostics over LSP or the tsserver protocol, and
350
+ * never returns server argv, cwd, environment, or absolute paths. Servers are
351
+ * injected per resolution; a workspace without a resolvable server reports
352
+ * `unsupported`.
353
+ */
354
+ export function createNodeLspRealHostV1(options) {
355
+ const workspaceDirectory = resolve(options.workspaceDirectory);
356
+ const servers = resolveLspServersV1({
357
+ workspaceDirectory,
358
+ ...(options.pathEnv === undefined ? {} : { pathEnv: options.pathEnv }),
359
+ ...(options.servers === undefined ? {} : { servers: options.servers }),
360
+ });
361
+ return {
362
+ resolver: {
363
+ async resolve(request) {
364
+ const language = SERVER_LANGUAGE_V1[request.language];
365
+ if (language === undefined)
366
+ return undefined;
367
+ if (servers[language] === undefined)
368
+ return undefined;
369
+ return { sessionRef: `lsp-${language}` };
370
+ },
371
+ },
372
+ client: {
373
+ async diagnose({ request }, signal) {
374
+ const language = SERVER_LANGUAGE_V1[request.language];
375
+ const spec = language === undefined ? undefined : servers[language];
376
+ if (spec === undefined)
377
+ return { status: "unsupported" };
378
+ const documentPath = resolveDocumentPathV1(workspaceDirectory, request);
379
+ if (documentPath === undefined)
380
+ return { status: "unsupported" };
381
+ const abortSignal = signal ?? new AbortController().signal;
382
+ const text = await readFile(documentPath, "utf8").catch(() => undefined);
383
+ if (text === undefined)
384
+ return { status: "unsupported" };
385
+ const relativePath = request.documentPath ?? request.documentRef;
386
+ const diagnostics = language === "typescript"
387
+ ? await diagnoseWithTsserverV1(spec, relativePath, documentPath, text, abortSignal)
388
+ : await diagnoseWithLspServerV1(spec, relativePath, documentPath, request.language, text, abortSignal);
389
+ if (diagnostics === undefined)
390
+ return { status: "unsupported" };
391
+ return { status: "completed", diagnostics };
392
+ },
393
+ },
394
+ };
395
+ }
396
+ //# sourceMappingURL=node-lsp-real-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-lsp-real-host.js","sourceRoot":"","sources":["../src/node-lsp-real-host.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { existsSync, statSync } from \"node:fs\";\nimport { readFile } from \"node:fs/promises\";\nimport { isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport { sanitizeLspDiagnosticsTextV1 } from \"./node-adapter.ts\";\nimport type {\n\tLspClientV1,\n\tLspDiagnosticsRequestV1,\n\tLspDiagnosticV1,\n\tLspHostDiagnosticResultV1,\n\tLspSessionResolverV1,\n\tLspSessionV1,\n} from \"./types.ts\";\n\nconst LSP_DIAGNOSTICS_STABLE_MS_V1 = 300;\nconst LSP_DIAGNOSTICS_TIMEOUT_MS_V1 = 15_000;\nconst TSSERVER_DIAGNOSTICS_TIMEOUT_MS_V1 = 15_000;\nconst MAX_SERVER_STDOUT_BYTES_V1 = 8 * 1024 * 1024;\n\nexport interface LspServerSpecV1 {\n\treadonly command: string;\n\treadonly args: readonly string[];\n}\n\nexport interface LspServerMapV1 {\n\treadonly typescript?: LspServerSpecV1;\n\treadonly python?: LspServerSpecV1;\n\treadonly c?: LspServerSpecV1;\n}\n\nconst SERVER_LANGUAGE_V1: Record<string, keyof LspServerMapV1> = {\n\ttypescript: \"typescript\",\n\tjavascript: \"typescript\",\n\tpython: \"python\",\n\tc: \"c\",\n\tcpp: \"c\",\n};\n\nfunction pathExecutableV1(name: string, pathEnv: string | undefined): string | undefined {\n\tif (typeof pathEnv !== \"string\" || pathEnv.trim() === \"\") return undefined;\n\tconst names = process.platform === \"win32\" ? [`${name}.exe`, `${name}.cmd`] : [name];\n\tfor (const directory of pathEnv.split(process.platform === \"win32\" ? \";\" : \":\")) {\n\t\tif (directory.trim() === \"\") continue;\n\t\tfor (const candidate of names) {\n\t\t\tconst resolved = join(directory, candidate);\n\t\t\tif (existsSync(resolved)) return resolved;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Host-owned language-server resolution: tsserver from the workspace-local\n * TypeScript install, pyright from the workspace-local npm package or PATH,\n * clangd from PATH. Unresolved languages stay absent so the wiring fails\n * closed; `servers` injects deterministic overrides for tests.\n */\nexport function resolveLspServersV1(options: {\n\treadonly workspaceDirectory: string;\n\treadonly pathEnv?: string;\n\treadonly servers?: LspServerMapV1;\n}): LspServerMapV1 {\n\tif (options.servers !== undefined) return options.servers;\n\tconst pathEnv = options.pathEnv ?? process.env.PATH;\n\tconst map: {\n\t\ttypescript?: LspServerSpecV1;\n\t\tpython?: LspServerSpecV1;\n\t\tc?: LspServerSpecV1;\n\t} = {};\n\tconst tsserver = join(options.workspaceDirectory, \"node_modules\", \"typescript\", \"lib\", \"tsserver.js\");\n\tif (isAbsolute(options.workspaceDirectory) && existsSync(tsserver))\n\t\tmap.typescript = { command: process.execPath, args: [tsserver] };\n\tconst pyrightLocal = join(options.workspaceDirectory, \"node_modules\", \"pyright\", \"dist\", \"pyright-langserver.js\");\n\tif (isAbsolute(options.workspaceDirectory) && existsSync(pyrightLocal))\n\t\tmap.python = { command: process.execPath, args: [pyrightLocal, \"--stdio\"] };\n\tconst pyrightPath = pathExecutableV1(\"pyright-langserver\", pathEnv);\n\tif (map.python === undefined && pyrightPath !== undefined) map.python = { command: pyrightPath, args: [\"--stdio\"] };\n\tconst clangd = pathExecutableV1(\"clangd\", pathEnv);\n\tif (clangd !== undefined) map.c = { command: clangd, args: [] };\n\treturn map;\n}\n\ninterface BoundedDiagnosticV1 {\n\treadonly file: string;\n\treadonly range: LspDiagnosticV1[\"range\"];\n\treadonly severity: LspDiagnosticV1[\"severity\"];\n\treadonly code?: string | number;\n\treadonly source?: string;\n\treadonly message: string;\n}\n\nfunction lspSeverityV1(value: unknown): LspDiagnosticV1[\"severity\"] {\n\tif (value === 1) return \"error\";\n\tif (value === 2) return \"warning\";\n\tif (value === 3) return \"info\";\n\tif (value === 4) return \"hint\";\n\treturn \"info\";\n}\n\nfunction tsserverCategoryV1(value: unknown): LspDiagnosticV1[\"severity\"] {\n\tif (value === \"error\") return \"error\";\n\tif (value === \"warning\") return \"warning\";\n\tif (value === \"suggestion\") return \"hint\";\n\treturn \"info\";\n}\n\ninterface SpawnedServerV1 {\n\treadonly stdout: AsyncIterable<Buffer>;\n\treadonly write: (chunk: string) => void;\n\treadonly kill: () => void;\n\treadonly exit: Promise<void>;\n}\n\nfunction spawnServerV1(spec: LspServerSpecV1, signal: AbortSignal): SpawnedServerV1 | undefined {\n\tconst child = spawn(spec.command, spec.args, {\n\t\tshell: false,\n\t\twindowsHide: true,\n\t\tstdio: [\"pipe\", \"pipe\", \"ignore\"],\n\t\tsignal,\n\t});\n\tif (child.stdout === null || child.stdin === null) {\n\t\tchild.kill();\n\t\treturn undefined;\n\t}\n\treturn {\n\t\tstdout: child.stdout,\n\t\twrite: (chunk) => child.stdin!.write(chunk),\n\t\tkill: () => child.kill(),\n\t\texit: new Promise((resolveExit) => {\n\t\t\tchild.once(\"exit\", () => resolveExit());\n\t\t\tchild.once(\"error\", () => resolveExit());\n\t\t}),\n\t};\n}\n\n/** Frame reader over stdio: either Content-Length framed (LSP) or line-delimited JSON (tsserver). */\nasync function* readMessagesV1(server: SpawnedServerV1, framed: boolean): AsyncGenerator<string> {\n\tlet buffer = \"\";\n\tfor await (const chunk of server.stdout) {\n\t\tbuffer += chunk.toString(\"utf8\");\n\t\tif (buffer.length > MAX_SERVER_STDOUT_BYTES_V1) return;\n\t\tif (framed) {\n\t\t\tfor (;;) {\n\t\t\t\tconst headerEnd = buffer.indexOf(\"\\r\\n\\r\\n\");\n\t\t\t\tif (headerEnd === -1) break;\n\t\t\t\tconst header = buffer.slice(0, headerEnd);\n\t\t\t\tconst lengthMatch = header.match(/Content-Length:\\s*(\\d+)/i);\n\t\t\t\tif (lengthMatch === null) return;\n\t\t\t\tconst length = Number(lengthMatch[1]);\n\t\t\t\tconst bodyStart = headerEnd + 4;\n\t\t\t\tif (buffer.length < bodyStart + length) break;\n\t\t\t\tyield buffer.slice(bodyStart, bodyStart + length);\n\t\t\t\tbuffer = buffer.slice(bodyStart + length);\n\t\t\t}\n\t\t} else {\n\t\t\tfor (;;) {\n\t\t\t\tconst lineEnd = buffer.indexOf(\"\\n\");\n\t\t\t\tif (lineEnd === -1) break;\n\t\t\t\tconst line = buffer.slice(0, lineEnd).trim();\n\t\t\t\tbuffer = buffer.slice(lineEnd + 1);\n\t\t\t\tif (line !== \"\") yield line;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction safePositionV1(value: unknown): number {\n\treturn typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0 ? value : 0;\n}\n\nfunction parseLspDiagnosticsV1(documentPath: string, params: unknown): BoundedDiagnosticV1[] {\n\tif (typeof params !== \"object\" || params === null) return [];\n\tconst diagnostics = (params as { diagnostics?: unknown }).diagnostics;\n\tif (!Array.isArray(diagnostics)) return [];\n\tconst projected: BoundedDiagnosticV1[] = [];\n\tfor (const raw of diagnostics) {\n\t\tif (typeof raw !== \"object\" || raw === null) continue;\n\t\tconst item = raw as {\n\t\t\trange?: { start?: { line?: unknown; character?: unknown }; end?: { line?: unknown; character?: unknown } };\n\t\t\tseverity?: unknown;\n\t\t\tcode?: unknown;\n\t\t\tsource?: unknown;\n\t\t\tmessage?: unknown;\n\t\t};\n\t\tconst message = typeof item.message === \"string\" ? sanitizeLspDiagnosticsTextV1(item.message) : \"\";\n\t\tif (message === \"\") continue;\n\t\tconst line = safePositionV1(item.range?.start?.line);\n\t\tconst column = safePositionV1(item.range?.start?.character);\n\t\tconst endLine = Math.max(line, safePositionV1(item.range?.end?.line));\n\t\tconst endColumn =\n\t\t\tendLine === line\n\t\t\t\t? Math.max(column, safePositionV1(item.range?.end?.character))\n\t\t\t\t: safePositionV1(item.range?.end?.character);\n\t\tprojected.push({\n\t\t\tfile: documentPath,\n\t\t\trange: { start: { line, column }, end: { line: endLine, column: endColumn } },\n\t\t\tseverity: lspSeverityV1(item.severity),\n\t\t\t...(typeof item.code === \"string\" || (typeof item.code === \"number\" && Number.isSafeInteger(item.code))\n\t\t\t\t? { code: item.code }\n\t\t\t\t: {}),\n\t\t\t...(typeof item.source === \"string\" ? { source: sanitizeLspDiagnosticsTextV1(item.source, 128) } : {}),\n\t\t\tmessage,\n\t\t});\n\t}\n\treturn projected;\n}\n\nfunction parseTsserverDiagnosticsV1(documentPath: string, body: unknown): BoundedDiagnosticV1[] {\n\tif (typeof body !== \"object\" || body === null) return [];\n\tconst diagnostics = (body as { diagnostics?: unknown }).diagnostics;\n\tif (!Array.isArray(diagnostics)) return [];\n\tconst projected: BoundedDiagnosticV1[] = [];\n\tfor (const raw of diagnostics) {\n\t\tif (typeof raw !== \"object\" || raw === null) continue;\n\t\tconst item = raw as {\n\t\t\tstart?: { line?: unknown; offset?: unknown };\n\t\t\tend?: { line?: unknown; offset?: unknown };\n\t\t\ttext?: unknown;\n\t\t\tcode?: unknown;\n\t\t\tcategory?: unknown;\n\t\t};\n\t\tconst message = typeof item.text === \"string\" ? sanitizeLspDiagnosticsTextV1(item.text) : \"\";\n\t\tif (message === \"\") continue;\n\t\t// tsserver positions are 1-based; normalize to the 0-based public shape.\n\t\tconst line = Math.max(0, safePositionV1(item.start?.line) - 1);\n\t\tconst column = Math.max(0, safePositionV1(item.start?.offset) - 1);\n\t\tconst endLine = Math.max(line, Math.max(0, safePositionV1(item.end?.line) - 1));\n\t\tconst endColumn =\n\t\t\tendLine === line\n\t\t\t\t? Math.max(column, Math.max(0, safePositionV1(item.end?.offset) - 1))\n\t\t\t\t: Math.max(0, safePositionV1(item.end?.offset) - 1);\n\t\tprojected.push({\n\t\t\tfile: documentPath,\n\t\t\trange: { start: { line, column }, end: { line: endLine, column: endColumn } },\n\t\t\tseverity: tsserverCategoryV1(item.category),\n\t\t\t...(typeof item.code === \"number\" && Number.isSafeInteger(item.code) ? { code: item.code } : {}),\n\t\t\tmessage,\n\t\t});\n\t}\n\treturn projected;\n}\n\n/**\n * LSP push client: initialize → didOpen → collect publishDiagnostics →\n * shutdown. The server stream is consumed by exactly one loop — breaking out\n * of a for-await over a Node stream destroys it, so phase transitions happen\n * inside the loop and the stability window resolves the shared promise\n * without interrupting the iteration.\n */\nasync function diagnoseWithLspServerV1(\n\tspec: LspServerSpecV1,\n\trelativePath: string,\n\tabsolutePath: string,\n\tlanguage: string,\n\ttext: string,\n\tsignal: AbortSignal,\n): Promise<BoundedDiagnosticV1[] | undefined> {\n\tconst server = spawnServerV1(spec, signal);\n\tif (server === undefined) return undefined;\n\tlet sequence = 0;\n\tconst nextId = () => ++sequence;\n\tconst send = (message: Record<string, unknown>): void => {\n\t\tconst payload = Buffer.from(JSON.stringify(message), \"utf8\");\n\t\tserver.write(`Content-Length: ${payload.byteLength}\\r\\n\\r\\n${payload.toString(\"utf8\")}`);\n\t};\n\tconst uri = pathToFileURL(absolutePath).href;\n\ttry {\n\t\tconst consumed = new Promise<BoundedDiagnosticV1[] | undefined>((resolveConsume) => {\n\t\t\tlet stableTimer: NodeJS.Timeout | undefined;\n\t\t\tlet latest: BoundedDiagnosticV1[] | undefined;\n\t\t\t// The stability window arms only after the first push so cold-start\n\t\t\t// servers are not cut off before their first diagnostics.\n\t\t\tconst arm = () => {\n\t\t\t\tclearTimeout(stableTimer);\n\t\t\t\tstableTimer = setTimeout(() => resolveConsume(latest), LSP_DIAGNOSTICS_STABLE_MS_V1);\n\t\t\t};\n\t\t\tvoid (async () => {\n\t\t\t\tsend({ jsonrpc: \"2.0\", id: nextId(), method: \"initialize\", params: { processId: null, capabilities: {} } });\n\t\t\t\tlet initialized = false;\n\t\t\t\tfor await (const raw of readMessagesV1(server, true)) {\n\t\t\t\t\tlet message: Record<string, unknown>;\n\t\t\t\t\ttry {\n\t\t\t\t\t\tmessage = JSON.parse(raw) as Record<string, unknown>;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (message.id !== undefined && message.method === undefined) {\n\t\t\t\t\t\tif (!initialized) {\n\t\t\t\t\t\t\tinitialized = true;\n\t\t\t\t\t\t\tsend({ jsonrpc: \"2.0\", method: \"initialized\", params: {} });\n\t\t\t\t\t\t\tsend({\n\t\t\t\t\t\t\t\tjsonrpc: \"2.0\",\n\t\t\t\t\t\t\t\tmethod: \"textDocument/didOpen\",\n\t\t\t\t\t\t\t\tparams: { textDocument: { uri, languageId: language, version: 1, text } },\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (message.method === \"textDocument/publishDiagnostics\") {\n\t\t\t\t\t\tconst pushed = parseLspDiagnosticsV1(relativePath, message.params);\n\t\t\t\t\t\tif (pushed.length > 0) {\n\t\t\t\t\t\t\tlatest = pushed;\n\t\t\t\t\t\t\tarm();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tresolveConsume(latest);\n\t\t\t})().catch(() => resolveConsume(latest));\n\t\t});\n\t\tconst timeout = new Promise<undefined>((resolveTimeout) => {\n\t\t\tsetTimeout(() => resolveTimeout(undefined), LSP_DIAGNOSTICS_TIMEOUT_MS_V1);\n\t\t});\n\t\tconst result = await Promise.race([consumed, timeout]);\n\t\tsend({ jsonrpc: \"2.0\", id: nextId(), method: \"shutdown\", params: null });\n\t\tsend({ jsonrpc: \"2.0\", method: \"exit\" });\n\t\treturn result;\n\t} finally {\n\t\tserver.kill();\n\t\tawait server.exit;\n\t}\n}\n\n/** tsserver client: configure → open → geterr → syntaxDiag/semanticDiag events. */\nasync function diagnoseWithTsserverV1(\n\tspec: LspServerSpecV1,\n\trelativePath: string,\n\tabsolutePath: string,\n\ttext: string,\n\tsignal: AbortSignal,\n): Promise<BoundedDiagnosticV1[] | undefined> {\n\tconst server = spawnServerV1(spec, signal);\n\tif (server === undefined) return undefined;\n\tlet sequence = 0;\n\tconst send = (command: string, argumentsValue: Record<string, unknown>): void => {\n\t\tserver.write(`${JSON.stringify({ seq: ++sequence, type: \"request\", command, arguments: argumentsValue })}\\n`);\n\t};\n\tconst collected: BoundedDiagnosticV1[] = [];\n\tconst received = { syntax: false, semantic: false };\n\ttry {\n\t\tsend(\"configure\", { hostInfo: \"agent-forge\" });\n\t\tsend(\"open\", { file: absolutePath, fileContent: text });\n\t\tsend(\"geterr\", { file: absolutePath, delay: 0 });\n\t\tconst timeout = new Promise<undefined>((resolveTimeout) => {\n\t\t\tsetTimeout(() => resolveTimeout(undefined), TSSERVER_DIAGNOSTICS_TIMEOUT_MS_V1);\n\t\t});\n\t\tconst collectedPromise = (async () => {\n\t\t\tfor await (const raw of readMessagesV1(server, false)) {\n\t\t\t\tlet message: Record<string, unknown>;\n\t\t\t\ttry {\n\t\t\t\t\tmessage = JSON.parse(raw) as Record<string, unknown>;\n\t\t\t\t} catch {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (message.type !== \"event\") continue;\n\t\t\t\tif (message.event === \"syntaxDiag\" || message.event === \"syntacticDiag\") {\n\t\t\t\t\tcollected.push(...parseTsserverDiagnosticsV1(relativePath, message.body));\n\t\t\t\t\treceived.syntax = true;\n\t\t\t\t}\n\t\t\t\tif (message.event === \"semanticDiag\") {\n\t\t\t\t\tcollected.push(...parseTsserverDiagnosticsV1(relativePath, message.body));\n\t\t\t\t\treceived.semantic = true;\n\t\t\t\t}\n\t\t\t\tif (received.syntax && received.semantic) break;\n\t\t\t}\n\t\t\treturn collected;\n\t\t})().catch(() => collected);\n\t\tconst result = await Promise.race([collectedPromise, timeout]);\n\t\tsend(\"exit\", {});\n\t\treturn result;\n\t} finally {\n\t\tserver.kill();\n\t\tawait server.exit;\n\t}\n}\n\nfunction resolveDocumentPathV1(workspaceDirectory: string, request: LspDiagnosticsRequestV1): string | undefined {\n\tconst documentPath = request.documentPath;\n\tif (typeof documentPath !== \"string\" || documentPath.trim() === \"\" || !isAbsolute(workspaceDirectory))\n\t\treturn undefined;\n\tconst absolute = resolve(workspaceDirectory, documentPath);\n\tconst root = resolve(workspaceDirectory);\n\tif (!absolute.startsWith(root + (root.endsWith(\"\\\\\") || root.endsWith(\"/\") ? \"\" : \"\\\\\")) && absolute !== root)\n\t\treturn undefined;\n\ttry {\n\t\tif (!existsSync(absolute) || !statSync(absolute).isFile()) return undefined;\n\t} catch {\n\t\treturn undefined;\n\t}\n\treturn absolute;\n}\n\n/**\n * Real language-server host over one workspace directory: resolves servers per\n * language (tsserver/pyright/clangd), opens the requested workspace-relative\n * document, collects push diagnostics over LSP or the tsserver protocol, and\n * never returns server argv, cwd, environment, or absolute paths. Servers are\n * injected per resolution; a workspace without a resolvable server reports\n * `unsupported`.\n */\nexport function createNodeLspRealHostV1(options: {\n\treadonly workspaceDirectory: string;\n\treadonly pathEnv?: string;\n\treadonly servers?: LspServerMapV1;\n}): { readonly resolver: LspSessionResolverV1; readonly client: LspClientV1 } {\n\tconst workspaceDirectory = resolve(options.workspaceDirectory);\n\tconst servers = resolveLspServersV1({\n\t\tworkspaceDirectory,\n\t\t...(options.pathEnv === undefined ? {} : { pathEnv: options.pathEnv }),\n\t\t...(options.servers === undefined ? {} : { servers: options.servers }),\n\t});\n\treturn {\n\t\tresolver: {\n\t\t\tasync resolve(request: LspDiagnosticsRequestV1): Promise<LspSessionV1 | undefined> {\n\t\t\t\tconst language = SERVER_LANGUAGE_V1[request.language];\n\t\t\t\tif (language === undefined) return undefined;\n\t\t\t\tif (servers[language] === undefined) return undefined;\n\t\t\t\treturn { sessionRef: `lsp-${language}` };\n\t\t\t},\n\t\t},\n\t\tclient: {\n\t\t\tasync diagnose({ request }, signal): Promise<LspHostDiagnosticResultV1> {\n\t\t\t\tconst language = SERVER_LANGUAGE_V1[request.language];\n\t\t\t\tconst spec = language === undefined ? undefined : servers[language];\n\t\t\t\tif (spec === undefined) return { status: \"unsupported\" };\n\t\t\t\tconst documentPath = resolveDocumentPathV1(workspaceDirectory, request);\n\t\t\t\tif (documentPath === undefined) return { status: \"unsupported\" };\n\t\t\t\tconst abortSignal = signal ?? new AbortController().signal;\n\t\t\t\tconst text = await readFile(documentPath, \"utf8\").catch(() => undefined);\n\t\t\t\tif (text === undefined) return { status: \"unsupported\" };\n\t\t\t\tconst relativePath = request.documentPath ?? request.documentRef;\n\t\t\t\tconst diagnostics =\n\t\t\t\t\tlanguage === \"typescript\"\n\t\t\t\t\t\t? await diagnoseWithTsserverV1(spec, relativePath, documentPath, text, abortSignal)\n\t\t\t\t\t\t: await diagnoseWithLspServerV1(\n\t\t\t\t\t\t\t\tspec,\n\t\t\t\t\t\t\t\trelativePath,\n\t\t\t\t\t\t\t\tdocumentPath,\n\t\t\t\t\t\t\t\trequest.language,\n\t\t\t\t\t\t\t\ttext,\n\t\t\t\t\t\t\t\tabortSignal,\n\t\t\t\t\t\t\t);\n\t\t\t\tif (diagnostics === undefined) return { status: \"unsupported\" };\n\t\t\t\treturn { status: \"completed\", diagnostics };\n\t\t\t},\n\t\t},\n\t};\n}\n"]}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Inlined from agent-forge `src/utils/shell.ts` (D-075 S3 extraction) so this
3
+ * package keeps its dependency closure limited to the plugin SDK and typebox.
4
+ * Semantics are unchanged.
5
+ */
6
+ /**
7
+ * Sanitize binary output for display/storage.
8
+ * Removes characters that crash string-width or cause display issues:
9
+ * - Control characters (except tab, newline, carriage return)
10
+ * - Lone surrogates
11
+ * - Unicode Format characters (crash string-width due to a bug)
12
+ * - Characters with undefined code points
13
+ */
14
+ export declare function sanitizeBinaryOutput(str: string): string;
15
+ //# sourceMappingURL=shell-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-utils.d.ts","sourceRoot":"","sources":["../src/shell-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CA8BxD","sourcesContent":["/**\n * Inlined from agent-forge `src/utils/shell.ts` (D-075 S3 extraction) so this\n * package keeps its dependency closure limited to the plugin SDK and typebox.\n * Semantics are unchanged.\n */\n\n/**\n * Sanitize binary output for display/storage.\n * Removes characters that crash string-width or cause display issues:\n * - Control characters (except tab, newline, carriage return)\n * - Lone surrogates\n * - Unicode Format characters (crash string-width due to a bug)\n * - Characters with undefined code points\n */\nexport function sanitizeBinaryOutput(str: string): string {\n\t// Use Array.from to properly iterate over code points (not code units)\n\t// This handles surrogate pairs correctly and catches edge cases where\n\t// codePointAt() might return undefined\n\treturn Array.from(str)\n\t\t.filter((char) => {\n\t\t\t// Filter out characters that cause string-width to crash\n\t\t\t// This includes:\n\t\t\t// - Unicode format characters\n\t\t\t// - Lone surrogates (already filtered by Array.from)\n\t\t\t// - Control chars except \\t \\n \\r\n\t\t\t// - Characters with undefined code points\n\n\t\t\tconst code = char.codePointAt(0);\n\n\t\t\t// v8 ignore next -- Array.from iterating over a legal string, codePointAt will not return undefined\n\t\t\tif (code === undefined) return false;\n\n\t\t\t// Allow tab, newline, carriage return\n\t\t\tif (code === 0x09 || code === 0x0a || code === 0x0d) return true;\n\n\t\t\t// Filter out control characters (0x00-0x1F, except 0x09, 0x0a, 0x0d)\n\t\t\tif (code <= 0x1f) return false;\n\n\t\t\t// Filter out Unicode format characters\n\t\t\tif (code >= 0xfff9 && code <= 0xfffb) return false;\n\n\t\t\treturn true;\n\t\t})\n\t\t.join(\"\");\n}\n"]}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Inlined from agent-forge `src/utils/shell.ts` (D-075 S3 extraction) so this
3
+ * package keeps its dependency closure limited to the plugin SDK and typebox.
4
+ * Semantics are unchanged.
5
+ */
6
+ /**
7
+ * Sanitize binary output for display/storage.
8
+ * Removes characters that crash string-width or cause display issues:
9
+ * - Control characters (except tab, newline, carriage return)
10
+ * - Lone surrogates
11
+ * - Unicode Format characters (crash string-width due to a bug)
12
+ * - Characters with undefined code points
13
+ */
14
+ export function sanitizeBinaryOutput(str) {
15
+ // Use Array.from to properly iterate over code points (not code units)
16
+ // This handles surrogate pairs correctly and catches edge cases where
17
+ // codePointAt() might return undefined
18
+ return Array.from(str)
19
+ .filter((char) => {
20
+ // Filter out characters that cause string-width to crash
21
+ // This includes:
22
+ // - Unicode format characters
23
+ // - Lone surrogates (already filtered by Array.from)
24
+ // - Control chars except \t \n \r
25
+ // - Characters with undefined code points
26
+ const code = char.codePointAt(0);
27
+ // v8 ignore next -- Array.from iterating over a legal string, codePointAt will not return undefined
28
+ if (code === undefined)
29
+ return false;
30
+ // Allow tab, newline, carriage return
31
+ if (code === 0x09 || code === 0x0a || code === 0x0d)
32
+ return true;
33
+ // Filter out control characters (0x00-0x1F, except 0x09, 0x0a, 0x0d)
34
+ if (code <= 0x1f)
35
+ return false;
36
+ // Filter out Unicode format characters
37
+ if (code >= 0xfff9 && code <= 0xfffb)
38
+ return false;
39
+ return true;
40
+ })
41
+ .join("");
42
+ }
43
+ //# sourceMappingURL=shell-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-utils.js","sourceRoot":"","sources":["../src/shell-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW,EAAU;IACzD,uEAAuE;IACvE,sEAAsE;IACtE,uCAAuC;IACvC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;SACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QACjB,yDAAyD;QACzD,iBAAiB;QACjB,8BAA8B;QAC9B,qDAAqD;QACrD,kCAAkC;QAClC,0CAA0C;QAE1C,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAEjC,oGAAoG;QACpG,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,KAAK,CAAC;QAErC,sCAAsC;QACtC,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QAEjE,qEAAqE;QACrE,IAAI,IAAI,IAAI,IAAI;YAAE,OAAO,KAAK,CAAC;QAE/B,uCAAuC;QACvC,IAAI,IAAI,IAAI,MAAM,IAAI,IAAI,IAAI,MAAM;YAAE,OAAO,KAAK,CAAC;QAEnD,OAAO,IAAI,CAAC;IAAA,CACZ,CAAC;SACD,IAAI,CAAC,EAAE,CAAC,CAAC;AAAA,CACX","sourcesContent":["/**\n * Inlined from agent-forge `src/utils/shell.ts` (D-075 S3 extraction) so this\n * package keeps its dependency closure limited to the plugin SDK and typebox.\n * Semantics are unchanged.\n */\n\n/**\n * Sanitize binary output for display/storage.\n * Removes characters that crash string-width or cause display issues:\n * - Control characters (except tab, newline, carriage return)\n * - Lone surrogates\n * - Unicode Format characters (crash string-width due to a bug)\n * - Characters with undefined code points\n */\nexport function sanitizeBinaryOutput(str: string): string {\n\t// Use Array.from to properly iterate over code points (not code units)\n\t// This handles surrogate pairs correctly and catches edge cases where\n\t// codePointAt() might return undefined\n\treturn Array.from(str)\n\t\t.filter((char) => {\n\t\t\t// Filter out characters that cause string-width to crash\n\t\t\t// This includes:\n\t\t\t// - Unicode format characters\n\t\t\t// - Lone surrogates (already filtered by Array.from)\n\t\t\t// - Control chars except \\t \\n \\r\n\t\t\t// - Characters with undefined code points\n\n\t\t\tconst code = char.codePointAt(0);\n\n\t\t\t// v8 ignore next -- Array.from iterating over a legal string, codePointAt will not return undefined\n\t\t\tif (code === undefined) return false;\n\n\t\t\t// Allow tab, newline, carriage return\n\t\t\tif (code === 0x09 || code === 0x0a || code === 0x0d) return true;\n\n\t\t\t// Filter out control characters (0x00-0x1F, except 0x09, 0x0a, 0x0d)\n\t\t\tif (code <= 0x1f) return false;\n\n\t\t\t// Filter out Unicode format characters\n\t\t\tif (code >= 0xfff9 && code <= 0xfffb) return false;\n\n\t\t\treturn true;\n\t\t})\n\t\t.join(\"\");\n}\n"]}
@@ -0,0 +1,105 @@
1
+ import type { PluginErrorV1, PluginResultStatusV1 } from "@agent-forge/plugin-sdk";
2
+ export declare const LSP_DIAGNOSTICS_PLUGIN_ID_V1: "agent-forge.plugin.lsp-diagnostics";
3
+ export declare const LSP_DIAGNOSTICS_CAPABILITY_VERSION_V1: 1;
4
+ export declare const LSP_DIAGNOSTICS_HOST_ADAPTER_ID_V1: "node-lsp";
5
+ export declare const LSP_DIAGNOSTICS_HOST_ADAPTER_VERSION_V1: "1.0.0";
6
+ export declare const LSP_DIAGNOSTICS_MAX_ITEMS_V1: 128;
7
+ export type LspDiagnosticSeverityV1 = "error" | "warning" | "info" | "hint";
8
+ export interface LspDiagnosticPositionV1 {
9
+ readonly line: number;
10
+ readonly column: number;
11
+ }
12
+ export interface LspDiagnosticRangeV1 {
13
+ readonly start: LspDiagnosticPositionV1;
14
+ readonly end: LspDiagnosticPositionV1;
15
+ }
16
+ /** Opaque model request. The host resolves refs to a language-server session. */
17
+ export interface LspDiagnosticsRequestV1 {
18
+ readonly version: 1;
19
+ readonly operationId: string;
20
+ /** Opaque host-owned workspace handle; never a path. */
21
+ readonly workspaceRef: string;
22
+ readonly language: string;
23
+ /** Opaque host-owned document handle; never source text or a path. */
24
+ readonly documentRef: string;
25
+ /**
26
+ * Workspace-relative file identifier the real host opens in the language
27
+ * server. Optional: deterministic fixture hosts can ignore it, the real
28
+ * host requires it, and it never carries an absolute or host path.
29
+ */
30
+ readonly documentPath?: string;
31
+ readonly diagnosticsLimit?: number;
32
+ }
33
+ /** Model-visible diagnostic. `file` is a relative identifier, never a host path. */
34
+ export interface LspDiagnosticV1 {
35
+ readonly file: string;
36
+ readonly range: LspDiagnosticRangeV1;
37
+ readonly severity: LspDiagnosticSeverityV1;
38
+ readonly code?: string | number;
39
+ readonly source?: string;
40
+ readonly message: string;
41
+ }
42
+ export interface LspDiagnosticsSummaryV1 {
43
+ readonly total: number;
44
+ readonly error: number;
45
+ readonly warning: number;
46
+ readonly info: number;
47
+ readonly hint: number;
48
+ }
49
+ export interface LspDiagnosticsResultV1 {
50
+ readonly version: 1;
51
+ readonly operationId: string;
52
+ readonly status: PluginResultStatusV1;
53
+ readonly summary: LspDiagnosticsSummaryV1;
54
+ readonly diagnostics: readonly LspDiagnosticV1[];
55
+ readonly diagnosticsTruncated: boolean;
56
+ readonly reportArtifactRef?: string;
57
+ readonly error?: PluginErrorV1;
58
+ }
59
+ /** Host-private session identity. It intentionally exposes no path, argv, cwd, or environment. */
60
+ export interface LspSessionV1 {
61
+ readonly sessionRef: string;
62
+ }
63
+ export interface LspSessionResolverV1 {
64
+ resolve(request: LspDiagnosticsRequestV1, signal?: AbortSignal): Promise<LspSessionV1 | undefined>;
65
+ }
66
+ export interface LspClientV1 {
67
+ diagnose(input: {
68
+ readonly session: LspSessionV1;
69
+ readonly request: LspDiagnosticsRequestV1;
70
+ }, signal?: AbortSignal): Promise<LspHostDiagnosticResultV1>;
71
+ }
72
+ /** Host output before the adapter applies strict model-facing projection. */
73
+ export type LspHostDiagnosticResultV1 = {
74
+ readonly status: "completed";
75
+ readonly diagnostics?: readonly unknown[];
76
+ readonly reportArtifactRef?: unknown;
77
+ } | {
78
+ readonly status: "unsupported";
79
+ };
80
+ export interface NodeLspAdapterOptionsV1 {
81
+ readonly resolver?: LspSessionResolverV1;
82
+ readonly client?: LspClientV1;
83
+ readonly defaultTimeoutMs?: number;
84
+ }
85
+ export interface LspDiagnosticsAdapterV1 {
86
+ readonly adapterId: string;
87
+ readonly adapterVersion: string;
88
+ run(request: LspDiagnosticsRequestV1, signal?: AbortSignal): Promise<LspDiagnosticsResultV1>;
89
+ }
90
+ export interface LspDeterministicFixtureV1 {
91
+ readonly workspaceRef: string;
92
+ readonly language: string;
93
+ readonly documentRef: string;
94
+ readonly result: LspHostDiagnosticResultV1;
95
+ }
96
+ export interface LspDiagnosticsPluginManifestV1 {
97
+ readonly id: typeof LSP_DIAGNOSTICS_PLUGIN_ID_V1;
98
+ readonly pluginVersion: string;
99
+ readonly apiVersion: "1";
100
+ readonly capabilityRefs: readonly [{
101
+ readonly id: "lsp.diagnostics";
102
+ readonly version: 1;
103
+ }];
104
+ }
105
+ //# sourceMappingURL=types.d.ts.map