@epoch-agent/plugin-lsp 0.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.
- package/LICENSE +219 -0
- package/README.md +185 -0
- package/dist/index.d.ts +580 -0
- package/dist/index.js +972 -0
- package/package.json +46 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
|
203
|
+
|
|
204
|
+
--------------------------------------------------------------------------------
|
|
205
|
+
|
|
206
|
+
epoch-agent
|
|
207
|
+
Copyright 2024-2026 bowen
|
|
208
|
+
|
|
209
|
+
Portions of this software are derived from the Gemini CLI
|
|
210
|
+
(https://github.com/google-gemini/gemini-cli), Copyright 2025 Google LLC,
|
|
211
|
+
licensed under the Apache License, Version 2.0. Those files have been modified;
|
|
212
|
+
each one retains its original copyright notice and SPDX-License-Identifier
|
|
213
|
+
header. See the NOTICE file in the project source repository for the complete
|
|
214
|
+
list of derived files.
|
|
215
|
+
|
|
216
|
+
This software also quotes, with attribution, two lines of prose from OpenAI
|
|
217
|
+
Codex (https://github.com/openai/codex), Copyright 2025 OpenAI, licensed under
|
|
218
|
+
the Apache License, Version 2.0. No source file is a derived work of Codex.
|
|
219
|
+
See the NOTICE file for details.
|
package/README.md
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# @epoch-agent/plugin-lsp
|
|
2
|
+
|
|
3
|
+
LSP 诊断插件。**一个工具**:`lsp_diagnostics` —— 用**项目自己的** language server
|
|
4
|
+
回答「我刚改的这几个文件,编译器怎么说」。
|
|
5
|
+
|
|
6
|
+
- ✅ **做**:探测 language server(项目 `node_modules` → PATH)、起一个常驻连接、
|
|
7
|
+
`didOpen` / `didChange` 后收 `publishDiagnostics`、判「收全了没」、排版给模型看
|
|
8
|
+
- ❌ **不做**:**不捆绑任何 server**(探不到就如实报「跳过 + 装法」)、不做补全 /
|
|
9
|
+
跳转 / 重命名、不做项目级构建、不自己 spawn(进程一律走
|
|
10
|
+
[infra](../../infra) 的 `startLongLivedProcess`)
|
|
11
|
+
- **依赖**:[protocol](../../protocol) + [infra](../../infra) +
|
|
12
|
+
`vscode-jsonrpc` / `vscode-languageserver-protocol`
|
|
13
|
+
|
|
14
|
+
## 工具参数
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{ "paths": ["src/a.ts", "src/b.tsx"] }
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| 参数 | 必填 | 说明 |
|
|
21
|
+
| ------- | ---- | -------------------------------------------------------- |
|
|
22
|
+
| `paths` | ✅ | 文件路径数组,相对工作目录或绝对路径。一次最多 50 个文件 |
|
|
23
|
+
|
|
24
|
+
单个路径写成字符串(`"paths": "src/a.ts"`)也收 —— 那是很自然的手误,
|
|
25
|
+
为它回一条参数错误等于白烧一轮。
|
|
26
|
+
|
|
27
|
+
当前认得 8 个扩展名:`.cjs` `.cts` `.js` `.jsx` `.mjs` `.mts` `.ts` `.tsx`
|
|
28
|
+
(唯一真源是 [servers.ts](src/servers.ts) 的 `supportedExtensions()`,
|
|
29
|
+
工具描述和报错提示都从那儿取)。不认的扩展名进 `unsupported`,
|
|
30
|
+
工作目录外的路径进 `rejected`,**都不会让这次调用失败**。
|
|
31
|
+
|
|
32
|
+
## 输出是文本,不是 JSON 数组
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
2 条诊断(1 error · 1 warning) · 已检查 2 个文件
|
|
36
|
+
|
|
37
|
+
src/a.ts:12:5 error typescript(2322): 不能将类型 "string" 分配给类型 "number"
|
|
38
|
+
src/b.tsx:3:10 warning typescript(6133): "unused" 已声明但从未读取
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
core 的 tool-executor 对非字符串 `output` 一律 `JSON.stringify`,那一行 JSON 里
|
|
42
|
+
每条诊断都要重复七个键名 —— 对 30 条诊断是白烧一倍多的 token,而模型从
|
|
43
|
+
`src/a.ts:12:5 error …` 里读到的信息一模一样(它每天在 tsc / eslint 的输出里
|
|
44
|
+
见的就是这个)。字段一个没少,只是换了排布。
|
|
45
|
+
|
|
46
|
+
**三件事一定在输出里**:检查了哪些文件(没这行,「没发现问题」和「一个文件都没
|
|
47
|
+
检查」长得一样)、跳过的语言 + 安装命令、被截断了多少(上限 100 条,
|
|
48
|
+
按 severity 优先保留 error)。
|
|
49
|
+
|
|
50
|
+
## 两处与方案 38 原文的偏差
|
|
51
|
+
|
|
52
|
+
1. **`paths` 是必填的。** 方案里「不传就检查本轮改过的文件」要拿
|
|
53
|
+
`CheckpointManager` 那份本轮改动清单,而插件的 `ToolContext` 只有
|
|
54
|
+
`{sessionId, workDir, extraRoots, permissionLevel, signal, onOutput}` —— 补这条得改
|
|
55
|
+
core 的 checkpoint 接口。先做成必填(模型知道自己刚改了哪几个文件),那条留给后续 PR
|
|
56
|
+
([验收记录 8.2](../../../docs/verify/VERIFY_RECORD-38-lsp-diagnostics.md))。
|
|
57
|
+
2. **输出是排好版的文本而不是 `[{file, line, ...}]`**,理由见上一节。
|
|
58
|
+
|
|
59
|
+
## 三级探测,一个 server 都不捆绑
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
1. 项目本地 node_modules/<pkg> ← TypeScript 那条「版本跟项目走」的硬要求
|
|
63
|
+
2. PATH
|
|
64
|
+
3. 都没有 → 该语言 skipped + 安装命令,其它语言不受影响
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
和 [infra 的 ripgrep 探测](../../infra/src/ripgrep.ts)反着来:那边捆绑一个 6MB
|
|
68
|
+
单文件,这边一个都不捆。language server 是一堆文件,而且**强绑定用户的项目配置**
|
|
69
|
+
—— 拿全局的 tsc 去检查一个 pin 了 5.8 的项目,报出来的错是假的。所以还额外把项目
|
|
70
|
+
自己那份 `node_modules/typescript/lib/tsserver.js` 显式传进
|
|
71
|
+
`initializationOptions.tsserver.path`:server 自己也会找 workspace 版本,
|
|
72
|
+
但那是它内部的一条兜底顺序,它升一版换个顺序我们就悄悄换了 TS 版本报错。
|
|
73
|
+
|
|
74
|
+
**故意不碰 `node_modules/.bin`。** Windows 上那儿躺的是 npm 生成的 `.cmd` 垫片,
|
|
75
|
+
Node 的 `spawn` 不过 shell 就执行不了;而 pnpm 下它是符号链接,跟到哪儿要看安装
|
|
76
|
+
布局。走 `node_modules/<pkg>/package.json` 的 `bin` 字段拿真实入口、用
|
|
77
|
+
`process.execPath` 跑它,两个平台同一条代码路径,且**必然是项目里那一份**。
|
|
78
|
+
PATH 命中 `.cmd` / `.bat` 时才走 `cmd.exe /d /s /c "<整条命令>"` + `verbatim`。
|
|
79
|
+
|
|
80
|
+
> ⚠️ **项目本地那一档带 `ELECTRON_RUN_AS_NODE=1`**(`launch.env`,值来自 infra 的
|
|
81
|
+
> `EXEC_PATH_AS_NODE_ENV`)。嵌进 Electron 主进程的宿主里 `process.execPath`
|
|
82
|
+
> **不是 node** 而是宿主自己的可执行文件,少了那一格,起 language server 等于
|
|
83
|
+
> 启动第二个 app 实例。PATH 那两档起的是真可执行文件,不需要。
|
|
84
|
+
> 全仓「谁把 execPath 当 node 使」由根 `__tests__/exec-path-as-node.test.ts` 数着。
|
|
85
|
+
|
|
86
|
+
> PATH 扫描**保留绝对路径**去 spawn,而不是像 ripgrep 那样丢掉路径 spawn 裸名字。
|
|
87
|
+
> 因为这个工具的输入正是「别人的仓库」:`shell: true` + 裸名字在 Windows 上,
|
|
88
|
+
> 目标仓库根目录里放一个同名 `.cmd` 就能劫持。我们的扫描列表里没有 cwd。
|
|
89
|
+
|
|
90
|
+
## 诊断是**推**过来的,所以「收全了没」要自己判
|
|
91
|
+
|
|
92
|
+
LSP 里没有「诊断请求」这种东西 —— typescript-language-server 4.4 也不支持 3.17 的
|
|
93
|
+
pull 模式(`initialize` 的结果里没有 `diagnosticProvider`)。server 想发就发,
|
|
94
|
+
而 tsserver 一个文件会**分三次**发(语法 / 语义 / 建议,各自 50ms 去抖),
|
|
95
|
+
先到的那一份是不全的。
|
|
96
|
+
|
|
97
|
+
**判据是静默**:请求的文件都答过了,且最近一次动静距今超过 `settleMs`(默认 400ms,
|
|
98
|
+
`fallbackMs` 1.5s,硬超时 15s)。
|
|
99
|
+
|
|
100
|
+
还有一条更阴的:**内容没变时 server 干脆不发。** `FileDiagnostics.update()` 里有
|
|
101
|
+
一句「这一类上次是空、这次还是空就不推送」,于是一个干净的文件被诊断第二次时
|
|
102
|
+
一条消息都收不到。按「没答复 = 没结果」处理就会把最正常的那种情况报成
|
|
103
|
+
「server 没回答」。所以有第二条判据:**没答复但有上一次的结果,就用上一次的**。
|
|
104
|
+
[e2e.test.ts](__tests__/e2e.test.ts) 拿真 server 盯着这一条。
|
|
105
|
+
|
|
106
|
+
## 进程池:懒启动 / 10 分钟回收 / 崩一次重启一次
|
|
107
|
+
|
|
108
|
+
| 策略 | 值 |
|
|
109
|
+
| ---------- | --------------------------------------------- |
|
|
110
|
+
| 启动时机 | 懒启动 —— 第一次 `lsp_diagnostics` 才起 |
|
|
111
|
+
| 空闲回收 | 10 分钟没用就关(大项目的 tsserver 吃几个 G) |
|
|
112
|
+
| 并发 | 每种语言一个实例,**按项目根隔离** |
|
|
113
|
+
| 初始化超时 | 每种 server 自己给(TypeScript 是 30s) |
|
|
114
|
+
| 崩溃 | 下次调用重启一次;再崩就本会话内不再试 |
|
|
115
|
+
|
|
116
|
+
池是**模块级单例**:工具每次调用都是一次新的 `execute`,而 language server 的意义
|
|
117
|
+
全在于「活着、缓存着上次的语法树」。挂在调用上等于每次冷启一个 tsserver,
|
|
118
|
+
那比让模型自己跑 tsc 还慢。
|
|
119
|
+
|
|
120
|
+
「不可用」的每一条路径 —— 没装、起不来、初始化超时、崩了 —— 交出来的都是
|
|
121
|
+
`{ ok: false, reason }` 而不是 throw。一个 server 起不来只该让它那门语言的文件被
|
|
122
|
+
跳过。**「没装」不计入失败次数**:那不是「试了没成」,计进去的话用户装完 server
|
|
123
|
+
还得重启 epoch 才能用上。
|
|
124
|
+
|
|
125
|
+
**退出时宿主什么都不用做**:进程在 infra 的进程表里,`cleanupBackgroundProcesses()`
|
|
126
|
+
会一并收掉。`disposeLspServers()` 是给「想早点收、且要走 LSP `shutdown` 礼节」的
|
|
127
|
+
宿主用的。
|
|
128
|
+
|
|
129
|
+
## 为什么是 `file_read` 而不是 `command`
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
annotations: { readOnlyHint: true, idempotentHint: false, openWorldHint: false }
|
|
133
|
+
operation: 'file_read'
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
这个工具对外的语义就是「读几个文件、报问题」。底下确实起了子进程,但那个进程是
|
|
137
|
+
**我们表里写死的**([servers.ts](src/servers.ts)),参数里没有任何一段来自模型。
|
|
138
|
+
归到 `command` 只会让每次诊断都弹一次审批 —— 而 core 的 system prompt 恰恰要求
|
|
139
|
+
模型每轮改完都调它。`idempotentHint: false` 是因为文件内容会变:同一批路径
|
|
140
|
+
这一秒和下一秒的诊断可以不一样。
|
|
141
|
+
|
|
142
|
+
`describeTarget` 给的是文件清单,不给就退回 `JSON.stringify(args)`,
|
|
143
|
+
换个顺序传同样几个文件就不命中审批缓存了。
|
|
144
|
+
|
|
145
|
+
## 加一门语言 = 往 `SERVERS` 里加一条
|
|
146
|
+
|
|
147
|
+
[servers.ts](src/servers.ts) 的 `SERVERS` 是**唯一**需要改的地方,client / pool /
|
|
148
|
+
diagnose 一行都不用动。别让语言判定漏到别处去。Python / Rust / Go 是方案 38 的
|
|
149
|
+
PR-3,**刻意砍掉的**(不是做到一半放弃)—— 砍的判据和真要做时的两条成本写在
|
|
150
|
+
[验收记录 8.1](../../../docs/verify/VERIFY_RECORD-38-lsp-diagnostics.md)。
|
|
151
|
+
|
|
152
|
+
## 文件
|
|
153
|
+
|
|
154
|
+
| 文件 | 内容 |
|
|
155
|
+
| ------------- | ----------------------------------------------------------- |
|
|
156
|
+
| `index.ts` | `lspPlugin` + 模块级池 + `disposeLspServers()` |
|
|
157
|
+
| `servers.ts` | 支持哪些语言、怎么起、`tsserver.path` 怎么找 |
|
|
158
|
+
| `detect.ts` | 三级探测(不 spawn,纯文件系统问题) |
|
|
159
|
+
| `client.ts` | 一个 server 连接:五条消息 + 静默判据 + 崩溃回调 + 优雅退出 |
|
|
160
|
+
| `pool.ts` | 懒启动 / 空闲回收 / 并发去重 / 失败计数 |
|
|
161
|
+
| `diagnose.ts` | 编排:路径归一 → 边界校验 → 按 server 分组 → 收结果 |
|
|
162
|
+
| `format.ts` | 渲染成模型读的那段文字(截断 + 按 severity 优先) |
|
|
163
|
+
| `find-up.ts` | 逐级往上找一个相对路径 |
|
|
164
|
+
| `types.ts` | 本包的类型 |
|
|
165
|
+
|
|
166
|
+
错误码占 **8xxx 段**:`8001` 参数不对、`8002` 我们没想到的形态。别复用别人的段 ——
|
|
167
|
+
用户报错时那四位数是唯一能一眼定位到哪个包的东西。
|
|
168
|
+
|
|
169
|
+
## 开发
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
pnpm --filter @epoch-agent/plugin-lsp test
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
七个用例文件。两处值得先看:
|
|
176
|
+
|
|
177
|
+
- [fixtures/fake-server.mjs](__tests__/fixtures/fake-server.mjs) 是一个**手写分帧**
|
|
178
|
+
的假 LSP server(故意不用 `vscode-jsonrpc`,那样才是一份独立的参照实现)。
|
|
179
|
+
`process.argv[2]` 选行为:`normal` / `three-kinds` / `silent` / `once` /
|
|
180
|
+
`hang-init` / `crash-on-open`
|
|
181
|
+
- [e2e.test.ts](__tests__/e2e.test.ts) 用**真的** typescript-language-server,
|
|
182
|
+
被检查的文件写在临时目录里 —— 故意报错的 fixture 不该进本仓库的 tsc / lint 范围
|
|
183
|
+
|
|
184
|
+
`vitest.config.ts` 的 `testTimeout` 是 60s:起一个真 tsserver 加初始化,
|
|
185
|
+
默认的 5000ms 不够。
|