@trim21/personal-pi-extensions 0.0.414 → 0.0.422
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/package.json +3 -3
- package/src/lib/lsp/lsp.ts +110 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trim21/personal-pi-extensions",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.422",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
|
|
6
6
|
"keywords": [
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"node": ">=24"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@cortexkit/aft-bridge": "0.
|
|
90
|
+
"@cortexkit/aft-bridge": "0.53.0",
|
|
91
91
|
"@mozilla/readability": "^0.6.0",
|
|
92
92
|
"@vscode/tree-sitter-wasm": "^0.3.1",
|
|
93
93
|
"jsonc-parser": "^3.3.1",
|
|
@@ -99,6 +99,6 @@
|
|
|
99
99
|
"web-tree-sitter": "^0.26.12"
|
|
100
100
|
},
|
|
101
101
|
"optionalDependencies": {
|
|
102
|
-
"@cortexkit/aft-linux-x64": "0.
|
|
102
|
+
"@cortexkit/aft-linux-x64": "0.53.0"
|
|
103
103
|
}
|
|
104
104
|
}
|
package/src/lib/lsp/lsp.ts
CHANGED
|
@@ -175,6 +175,8 @@ interface LspState {
|
|
|
175
175
|
broken: Set<string>;
|
|
176
176
|
spawning: Map<string, Promise<LspClient | undefined>>;
|
|
177
177
|
closing: boolean;
|
|
178
|
+
/** /lsp-stop 置 true:所有工具调用不再 spawn 服务器,直到 start/reload。 */
|
|
179
|
+
disabled: boolean;
|
|
178
180
|
/** root+serverID → 服务器状态,用于 footer status 显示。 */
|
|
179
181
|
servers: Map<string, { serverID: string; root: string; state: "running" | "broken" }>;
|
|
180
182
|
}
|
|
@@ -214,6 +216,17 @@ export interface LspService {
|
|
|
214
216
|
options?: LspRequestOptions,
|
|
215
217
|
): Promise<{ text: string; errorCount: number; warningCount: number }>;
|
|
216
218
|
shutdownAll(): Promise<void>;
|
|
219
|
+
/** 停止全部服务器并禁用 LSP:之后工具调用不再 spawn,直到 start/reload。 */
|
|
220
|
+
stop(): Promise<void>;
|
|
221
|
+
/** 解除禁用并清空 broken 缓存;服务器在下次工具调用时惰性启动。 */
|
|
222
|
+
start(): void;
|
|
223
|
+
/**
|
|
224
|
+
* 重启指定服务器:关闭其全部 client、清除对应 broken 记录并解除禁用;
|
|
225
|
+
* 其余服务器不受影响。配置在下次工具调用时重新读取。
|
|
226
|
+
*/
|
|
227
|
+
reload(serverID: string): Promise<void>;
|
|
228
|
+
/** 已知服务器 id(running 或 broken 的去重集合),供命令补全与提示。 */
|
|
229
|
+
serverIDs(): string[];
|
|
217
230
|
/** 注入 status 渲染回调;传入 undefined 表示不再渲染。 */
|
|
218
231
|
attachStatus(render: StatusRenderer | undefined): void;
|
|
219
232
|
/** 用当前服务器状态主动刷新一次 status(agent start/end 等生命周期边界)。 */
|
|
@@ -247,6 +260,7 @@ export function createLspService(
|
|
|
247
260
|
broken: new Set(),
|
|
248
261
|
spawning: new Map(),
|
|
249
262
|
closing: false,
|
|
263
|
+
disabled: false,
|
|
250
264
|
servers: new Map(),
|
|
251
265
|
};
|
|
252
266
|
|
|
@@ -255,6 +269,10 @@ export function createLspService(
|
|
|
255
269
|
/** 汇总当前所有 LSP server 状态并渲染到 footer status。 */
|
|
256
270
|
function updateStatusText(): void {
|
|
257
271
|
if (!renderStatus) return;
|
|
272
|
+
if (state.disabled) {
|
|
273
|
+
renderStatus("lsp: disabled");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
258
276
|
if (state.servers.size === 0) {
|
|
259
277
|
renderStatus(undefined);
|
|
260
278
|
return;
|
|
@@ -275,7 +293,7 @@ export function createLspService(
|
|
|
275
293
|
cwd: string,
|
|
276
294
|
notify?: ExtensionUIContext["notify"],
|
|
277
295
|
): Promise<LspClient[]> {
|
|
278
|
-
if (state.closing) return [];
|
|
296
|
+
if (state.closing || state.disabled) return [];
|
|
279
297
|
if (!containsPath(file, cwd)) return [];
|
|
280
298
|
const config = await loadLspConfig(cwd, globalConfigPath);
|
|
281
299
|
const timeout = timeoutOptions(config);
|
|
@@ -326,7 +344,7 @@ export function createLspService(
|
|
|
326
344
|
diagnosticsDocumentWaitTimeoutMs:
|
|
327
345
|
adapter.diagnosticsWaitMs ?? timeout.diagnosticsDocumentWaitTimeoutMs,
|
|
328
346
|
});
|
|
329
|
-
if (state.closing) {
|
|
347
|
+
if (state.closing || state.disabled) {
|
|
330
348
|
await client.shutdown();
|
|
331
349
|
return;
|
|
332
350
|
}
|
|
@@ -426,9 +444,8 @@ export function createLspService(
|
|
|
426
444
|
return { text: report(normalized, issues), errorCount, warningCount };
|
|
427
445
|
}
|
|
428
446
|
|
|
429
|
-
/**
|
|
430
|
-
async function
|
|
431
|
-
if (state.closing) return;
|
|
447
|
+
/** 关闭全部 client 并清空缓存;closing 置 true 让 in-flight spawn 自行退出。 */
|
|
448
|
+
async function closeAll(): Promise<void> {
|
|
432
449
|
state.closing = true;
|
|
433
450
|
await Promise.all(state.clients.map((client) => client.shutdown())).catch(() => {
|
|
434
451
|
// 个别进程退出失败不阻止清理流程
|
|
@@ -439,11 +456,55 @@ export function createLspService(
|
|
|
439
456
|
updateStatusText();
|
|
440
457
|
}
|
|
441
458
|
|
|
459
|
+
/** 终止全部服务器进程(session_shutdown 时调用,终态)。 */
|
|
460
|
+
async function shutdownAll(): Promise<void> {
|
|
461
|
+
await closeAll();
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
async function stop(): Promise<void> {
|
|
465
|
+
await closeAll();
|
|
466
|
+
state.closing = false;
|
|
467
|
+
state.disabled = true;
|
|
468
|
+
updateStatusText();
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
function start(): void {
|
|
472
|
+
state.closing = false;
|
|
473
|
+
state.disabled = false;
|
|
474
|
+
state.broken.clear();
|
|
475
|
+
updateStatusText();
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
async function reload(serverID: string): Promise<void> {
|
|
479
|
+
state.closing = true;
|
|
480
|
+
const targets = state.clients.filter((client) => client.serverID === serverID);
|
|
481
|
+
await Promise.all(targets.map((client) => client.shutdown())).catch(() => {
|
|
482
|
+
// 个别进程退出失败不阻止清理流程
|
|
483
|
+
});
|
|
484
|
+
state.clients = state.clients.filter((client) => client.serverID !== serverID);
|
|
485
|
+
for (const [key, server] of state.servers) {
|
|
486
|
+
if (server.serverID !== serverID) continue;
|
|
487
|
+
state.broken.delete(key);
|
|
488
|
+
state.servers.delete(key);
|
|
489
|
+
}
|
|
490
|
+
state.closing = false;
|
|
491
|
+
state.disabled = false;
|
|
492
|
+
updateStatusText();
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function serverIDs(): string[] {
|
|
496
|
+
return [...new Set([...state.servers.values()].map((server) => server.serverID))];
|
|
497
|
+
}
|
|
498
|
+
|
|
442
499
|
return {
|
|
443
500
|
touchFile,
|
|
444
501
|
diagnostics,
|
|
445
502
|
lspDiagnosticsForFile,
|
|
446
503
|
shutdownAll,
|
|
504
|
+
stop,
|
|
505
|
+
start,
|
|
506
|
+
reload,
|
|
507
|
+
serverIDs,
|
|
447
508
|
attachStatus,
|
|
448
509
|
refreshStatus: updateStatusText,
|
|
449
510
|
};
|
|
@@ -476,5 +537,49 @@ export function registerLsp(pi: ExtensionAPI, options?: LspServiceOptions): LspS
|
|
|
476
537
|
// spawn(首次工具调用),start/end 时保证 footer 反映当前实际状态。
|
|
477
538
|
pi.on?.("agent_start", () => service.refreshStatus());
|
|
478
539
|
pi.on?.("agent_end", () => service.refreshStatus());
|
|
540
|
+
|
|
541
|
+
pi.registerCommand?.("lsp-stop", {
|
|
542
|
+
description: "Stop all LSP servers and disable LSP until /lsp-start or /lsp-reload",
|
|
543
|
+
handler: async (_args, ctx) => {
|
|
544
|
+
await service.stop();
|
|
545
|
+
ctx.ui.notify?.("LSP disabled: all servers stopped", "info");
|
|
546
|
+
},
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
pi.registerCommand?.("lsp-start", {
|
|
550
|
+
description: "Re-enable LSP; servers start on the next tool call",
|
|
551
|
+
handler: (_args, ctx) => {
|
|
552
|
+
service.start();
|
|
553
|
+
ctx.ui.notify?.("LSP enabled: servers will start on the next tool call", "info");
|
|
554
|
+
return Promise.resolve();
|
|
555
|
+
},
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
pi.registerCommand?.("lsp-reload", {
|
|
559
|
+
description: "Restart a specific LSP server: /lsp-reload <server-id>",
|
|
560
|
+
getArgumentCompletions: (prefix) =>
|
|
561
|
+
service
|
|
562
|
+
.serverIDs()
|
|
563
|
+
.toSorted()
|
|
564
|
+
.filter((id) => id.startsWith(prefix))
|
|
565
|
+
.map((id) => ({ value: id, label: id })),
|
|
566
|
+
handler: async (args, ctx) => {
|
|
567
|
+
const serverID = args.trim();
|
|
568
|
+
const known = service.serverIDs().toSorted();
|
|
569
|
+
if (!serverID) {
|
|
570
|
+
ctx.ui.notify?.(
|
|
571
|
+
`usage: /lsp-reload <server-id>${known.length > 0 ? ` (known: ${known.join(", ")})` : ""}`,
|
|
572
|
+
"warning",
|
|
573
|
+
);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
576
|
+
await service.reload(serverID);
|
|
577
|
+
ctx.ui.notify?.(
|
|
578
|
+
`LSP server "${serverID}" reloaded: will restart on the next tool call`,
|
|
579
|
+
"info",
|
|
580
|
+
);
|
|
581
|
+
},
|
|
582
|
+
});
|
|
583
|
+
|
|
479
584
|
return service;
|
|
480
585
|
}
|