@epoch-agent/plugin-lsp 4.0.0 → 4.1.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.
Files changed (2) hide show
  1. package/dist/index.d.ts +29 -44
  2. package/package.json +3 -3
package/dist/index.d.ts CHANGED
@@ -193,50 +193,40 @@ interface ResolveServerOptions {
193
193
  declare function resolveServer(spec: ServerSpec, projectRoot: string, options?: ResolveServerOptions): ServerResolution;
194
194
 
195
195
  /**
196
- * 一个 language server 连接(方案 38)。
196
+ * 一个 language server 连接。
197
197
  *
198
198
  * 协议实现**不手写**:`vscode-jsonrpc` 负责分帧和 JSON-RPC,
199
199
  * `vscode-languageserver-protocol` 提供消息描述符和类型。真正用到的只有五条:
200
200
  * `initialize` / `initialized` / `didOpen` / `didChange` / `publishDiagnostics`
201
201
  * (外加 `didClose` 做逐出、`shutdown` + `exit` 做优雅退出)。
202
202
  *
203
- * 进程**一律走 infra 的 `startLongLivedProcess`**(方案 36),这个包里不长
204
- * 第二套进程管理 —— 顺带的好处是 `epoch` 退出时 server 被天然一并收掉(验收 7),
205
- * 我们一行清理代码都不用写。
203
+ * 进程**一律走 infra 的 `startLongLivedProcess`**,这个包里不长第二套进程管理 ——
204
+ * 顺带的好处是 `epoch` 退出时 server 被天然一并收掉,我们一行清理代码都不用写。
206
205
  *
207
- * 收它的那条链子(方案 60 之后):`startLongLivedProcess` 登记进的是**进程级
208
- * 兜底表** —— 这个池是模块级单例、按项目根共享,压根没有 `sessionId`,归兜底表
209
- * 是结论不是妥协(判据在 [README](../README.md))。最后一个 runtime
210
- * `dispose()` → `OwnedProcessTable.release()` 把兜底表的引用计数减到 0,那一下
211
- * 连兜底表一起收。一个进程一个 runtime 的 CLI / TUI 每次 dispose 都归零,
212
- * 所以和方案 60 之前逐字节相同;两个 runtime 并存时先走的那个碰不到这个池
206
+ * 收它的那条链子:`startLongLivedProcess` 登记进的是**进程级兜底表** —— 这个池是
207
+ * 模块级单例、按项目根共享,压根没有 `sessionId`,归兜底表是结论不是妥协(判据在
208
+ * [README](../README.md))。最后一个 runtime `dispose()` → `OwnedProcessTable.release()`
209
+ * 把引用计数减到 0 时连兜底表一起收;两个 runtime 并存时先走的那个碰不到这个池
213
210
  * (否则表现是「跑了条定时任务,之后 `lsp_diagnostics` 每次都要重新冷启 tsserver」)。
214
211
  *
215
212
  * ## 诊断是**推**过来的,所以「什么时候算收全了」得自己判
216
213
  *
217
- * 这个协议里没有「诊断请求」这种东西(typescript-language-server 4.4 也不支持
218
- * 3.17 的 pull 模式 —— `initialize` 的结果里没有 `diagnosticProvider`)。
219
- * server 想发就发,而 tsserver 一个文件会**分三次**发(语法 / 语义 / 建议,
220
- * 各自 50ms 去抖),先到的那一份是不全的。
221
- *
222
- * 判据因此是**静默**:请求的文件都答过了,且最近一次动静距今超过 `settleMs`。
214
+ * 这个协议里没有「诊断请求」这种东西(typescript-language-server 4.4 也不支持 3.17
215
+ * 的 pull 模式 —— `initialize` 的结果里没有 `diagnosticProvider`)。server 想发就发,
216
+ * 而 tsserver 一个文件会**分三次**发(语法 / 语义 / 建议,各自 50ms 去抖),先到的
217
+ * 那一份是不全的。判据因此是**静默**:请求的文件都答过了,且最近一次动静距今超过
218
+ * `settleMs`。
223
219
  *
224
220
  * ### 还有一条更阴的:内容没变时 server 干脆不发
225
221
  *
226
- * typescript-language-server 的 `FileDiagnostics.update()` 里有这么一句
227
- * (lib/cli.mjs):
228
- *
229
- * ```js
230
- * if (this.diagnosticsPerKind.get(kind)?.length === 0 && diagnostics.length === 0) return;
231
- * ```
232
- *
233
- * 也就是「这一类上次是空、这次还是空」就**不推送**。于是一个干净的文件被诊断
234
- * 第二次时一条消息都收不到 —— 如果按「没答复 = 没结果」处理,就会把它报成
235
- * 「server 没回答」,而它其实是最正常的那种情况。
222
+ * typescript-language-server 的 `FileDiagnostics.update()`(lib/cli.mjs)里有一句
223
+ * `if (this.diagnosticsPerKind.get(kind)?.length === 0 && diagnostics.length === 0) return;`
224
+ * —— 「这一类上次是空、这次还是空」就**不推送**。于是一个干净的文件被诊断第二次时
225
+ * 一条消息都收不到;按「没答复 = 没结果」处理就会把它报成「server 没回答」,而它
226
+ * 其实是最正常的那种情况。
236
227
  *
237
- * 所以有第二条判据:**没答复但有上一次的结果,就用上一次的**。这在语义上是
238
- * 对的,因为那句 `return` 恰好只在「什么都没变、也没什么可报」时生效;一旦某一类
239
- * 从有变没或从没变有,它就会照常推送。
228
+ * 所以有第二条判据:**没答复但有上一次的结果,就用上一次的**。那句 `return` 恰好只在
229
+ * 「什么都没变、也没什么可报」时生效;一旦某一类从有变没或从没变有,它就会照常推送。
240
230
  */
241
231
 
242
232
  /** 一次批量诊断的输入 */
@@ -315,14 +305,13 @@ declare class LspClient implements DiagnosticsClient {
315
305
  private stderr;
316
306
  private constructor();
317
307
  get pid(): number;
318
- /** 还能用吗。池按这个决定要不要重启(验收 9) */
308
+ /** 还能用吗。池按这个决定要不要重启 */
319
309
  get alive(): boolean;
320
310
  /**
321
311
  * 起进程 + `initialize` + `initialized`。
322
312
  *
323
- * 起不来 / 初始化超时都**返回 `null` 而不抛** —— 调用方据此把这个语言标记
324
- * 不可用,整轮照常出结果(验收 8)。抛出去的话一个慢 server 就能让整次工具
325
- * 调用失败,而那正是这条验收要避免的。
313
+ * 起不来 / 初始化超时都**返回 `null` 而不抛** —— 调用方据此把这个语言标记不可用,
314
+ * 整轮照常出结果。抛出去的话一个慢 server 就能让整次工具调用失败。
326
315
  */
327
316
  static start(options: StartClientOptions): Promise<LspClient | null>;
328
317
  /** 订阅推送 + 兜住 server 反过来发的那几种请求 */
@@ -333,7 +322,7 @@ declare class LspClient implements DiagnosticsClient {
333
322
  /**
334
323
  * 打开 / 更新这批文件,等到静默,交出诊断。
335
324
  *
336
- * @throws {LspServerDownError} 进程中途没了(验收 9 的输入)
325
+ * @throws {LspServerDownError} 进程中途没了
337
326
  */
338
327
  diagnose(documents: DocumentInput[], wait: WaitOptions): Promise<DiagnoseBatch>;
339
328
  /** 没打开过就 `didOpen`,打开过就 `didChange`(全量) */
@@ -345,21 +334,17 @@ declare class LspClient implements DiagnosticsClient {
345
334
  *
346
335
  * 先按协议 `shutdown` + `exit`,给它清临时文件的机会;超预算就直接杀树。
347
336
  * **杀树那一步不能省** —— `typescript-language-server` 自己还 fork 了一个
348
- * `tsserver.js`,只杀父进程会留下孤儿(验收 7)。
337
+ * `tsserver.js`,只杀父进程会留下孤儿。
349
338
  *
350
339
  * ## ⚠️ 三步的**顺序**是判据:拍快照 → 优雅关 → 清扫快照
351
340
  *
352
- * 这里原来只有两步(优雅关 → `killTrackedProcess`),而那是**漏的**:
353
341
  * `killTrackedProcess` 底下是 `killProcessTree`,靠的是**现场遍历**
354
- * (`pgrep -P` / `taskkill /t`)。等我们优雅关完,直接子进程已经退了 ——
355
- * 树的根没了,孙进程的 PPID 指向一个死 pid,遍历再也找不到它们。
356
- * 于是 `tsserver` 那一层在 POSIX 上被 init 收养、在 Windows 上直接常驻到关机。
342
+ * (`pgrep -P` / `taskkill /t`)。等我们优雅关完,直接子进程已经退了 —— 树的根
343
+ * 没了,孙进程的 PPID 指向一个死 pid,遍历再也找不到它们:`tsserver` 那一层在
344
+ * POSIX 上被 init 收养、在 Windows 上直接常驻到关机。所以快照必须在**动手之前**拍。
357
345
  *
358
- * 所以快照必须在**动手之前**拍。这不是新发明:`plugin-mcp` 的
359
- * `closeTransportAndReap` 就是这三步,而它有一条会红的用例守着;
360
- * 我们这边验收 #7 一直挂着「双平台手验」没人做,于是漏了一年半。
361
- * 2026-08-12 补的 [orphan-reap.test.ts](../__tests__/orphan-reap.test.ts)
362
- * 把这条钉死了 —— 把下面的快照挪到 `killTrackedProcess` 之后,它当场红。
346
+ * `orphan-reap.test.ts` 把这条钉死了 —— 把下面的快照挪到 `killTrackedProcess`
347
+ * 之后,它当场红。
363
348
  */
364
349
  dispose(): Promise<void>;
365
350
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@epoch-agent/plugin-lsp",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "private": false,
5
5
  "description": "LSP 诊断插件 — 探测项目自带的 language server,按文件取语义诊断",
6
6
  "repository": {
@@ -24,8 +24,8 @@
24
24
  "dependencies": {
25
25
  "vscode-jsonrpc": "^9.0.1",
26
26
  "vscode-languageserver-protocol": "^3.17.5",
27
- "@epoch-agent/infra": "4.0.0",
28
- "@epoch-agent/protocol": "4.0.0"
27
+ "@epoch-agent/infra": "4.1.0",
28
+ "@epoch-agent/protocol": "4.1.0"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^26.1.2",