@trim21/personal-pi-extensions 0.0.360 → 0.0.362

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trim21/personal-pi-extensions",
3
- "version": "0.0.360",
3
+ "version": "0.0.362",
4
4
  "type": "module",
5
5
  "description": "Custom pi coding-agent extensions: bwrap sandbox, workspace guard, opencode edit, and more",
6
6
  "keywords": [
@@ -259,11 +259,8 @@ export async function create(input: CreateInput): Promise<LspClient> {
259
259
  (params: { uri: string; version?: number; diagnostics: Diagnostic[] }) => {
260
260
  const filePath = getFilePath(params.uri);
261
261
  if (!filePath) return;
262
- // 支持 pull 诊断的服务器:push 的结果可能来自旧内容(异步重算迟到),
263
- // 直接忽略,只信任 pull 返回的当前文档结果,从源头避免 stale。
264
- if (supportsPullDiagnostics()) return;
265
- // 纯 push 服务器:服务器版本滞后于已发送版本时,该 push 对应的是旧内容
266
- // (重算未完成时的迟到结果),同样忽略。
262
+ // 服务器版本滞后于已发送版本时,该 push 对应的是旧内容(异步重算未完成
263
+ // 时的迟到结果)。忽略,避免与当前版本结果混淆。
267
264
  const currentVersion = documentVersions.get(filePath);
268
265
  const isStalePush =
269
266
  typeof params.version === "number" &&
@@ -461,15 +458,6 @@ export async function create(input: CreateInput): Promise<LspClient> {
461
458
  return { handled: true, matched, byFile, timedOut };
462
459
  }
463
460
 
464
- /** 是否支持文档级 pull 诊断:静态 diagnosticProvider 或动态注册的 document 诊断。 */
465
- function supportsPullDiagnostics(): boolean {
466
- if (hasStaticPullDiagnostics) return true;
467
- for (const registration of diagnosticRegistrations.values()) {
468
- if (registration.registerOptions?.workspaceDiagnostics !== true) return true;
469
- }
470
- return false;
471
- }
472
-
473
461
  function documentPullState() {
474
462
  const documentRegistrations = [...diagnosticRegistrations.values()].filter(
475
463
  (registration) => registration.registerOptions?.workspaceDiagnostics !== true,
@@ -478,7 +466,7 @@ export async function create(input: CreateInput): Promise<LspClient> {
478
466
  documentIdentifiers: [
479
467
  ...new Set(documentRegistrations.flatMap((r) => r.registerOptions?.identifier ?? [])),
480
468
  ],
481
- supported: supportsPullDiagnostics(),
469
+ supported: hasStaticPullDiagnostics || documentRegistrations.length > 0,
482
470
  };
483
471
  }
484
472
 
@@ -634,18 +622,9 @@ export async function create(input: CreateInput): Promise<LspClient> {
634
622
  signal?: AbortSignal;
635
623
  }): Promise<void> {
636
624
  const startedAt = request.after ?? Date.now();
637
- // 支持 pull 的服务器:push 已被忽略,pull 是唯一通道。正常返回但未拿到
638
- // 当前文档结果时重试;请求超时(服务器未响应)则中断,避免阻塞编辑。
639
- if (supportsPullDiagnostics()) {
640
- while (!connectionClosed && !request.signal?.aborted) {
641
- const result = await requestDocumentDiagnostics(request.path);
642
- if (result.matched) return;
643
- if (result.timedOut) return;
644
- await sleep(PULL_RETRY_INTERVAL_MS);
645
- }
646
- return;
647
- }
648
-
625
+ // pull push 语义相同:都是等「当前文档版本」的诊断结果,统一一个循环。
626
+ // 先 pull(拿到即返回);pull 超时说明服务器未响应,不再重试 pull,只等
627
+ // 版本匹配的 push 兜底;版本不匹配的 push 一律忽略(防迟到旧结果)。
649
628
  const pushWait = waitForFreshPush({
650
629
  path: request.path,
651
630
  version: request.version,
@@ -653,18 +632,23 @@ export async function create(input: CreateInput): Promise<LspClient> {
653
632
  timeout: diagnosticsDocumentWaitTimeoutMs,
654
633
  });
655
634
 
656
- while (Date.now() - startedAt < diagnosticsDocumentWaitTimeoutMs) {
657
- const result = await requestDocumentDiagnostics(request.path);
658
- if (result.matched) return;
635
+ while (!connectionClosed && !request.signal?.aborted) {
659
636
  const remaining = diagnosticsDocumentWaitTimeoutMs - (Date.now() - startedAt);
660
637
  if (remaining <= 0) return;
638
+ const result = await requestDocumentDiagnostics(request.path);
639
+ if (result.matched) return;
640
+ if (result.timedOut) {
641
+ await pushWait;
642
+ return;
643
+ }
661
644
  const next = await Promise.race([
662
- pushWait.then((ready) => (ready ? "push" : ("timeout" as const))),
645
+ pushWait.then((ready) => (ready ? ("push" as const) : ("timeout" as const))),
663
646
  waitForRegistrationChange(remaining).then((changed) =>
664
647
  changed ? ("registration" as const) : ("timeout" as const),
665
648
  ),
649
+ sleep(Math.min(remaining, PULL_RETRY_INTERVAL_MS)).then(() => "interval" as const),
666
650
  ]);
667
- if (next !== "registration") return;
651
+ if (next === "push") return;
668
652
  }
669
653
  }
670
654
 
@@ -675,16 +659,6 @@ export async function create(input: CreateInput): Promise<LspClient> {
675
659
  signal?: AbortSignal;
676
660
  }): Promise<void> {
677
661
  const startedAt = request.after ?? Date.now();
678
- if (supportsPullDiagnostics()) {
679
- while (!connectionClosed && !request.signal?.aborted) {
680
- const result = await requestFullDiagnostics(request.path);
681
- if (result.handled || result.matched) return;
682
- if (result.timedOut) return;
683
- await sleep(PULL_RETRY_INTERVAL_MS);
684
- }
685
- return;
686
- }
687
-
688
662
  const pushWait = waitForFreshPush({
689
663
  path: request.path,
690
664
  version: request.version,
@@ -692,18 +666,23 @@ export async function create(input: CreateInput): Promise<LspClient> {
692
666
  timeout: diagnosticsFullWaitTimeoutMs,
693
667
  });
694
668
 
695
- while (Date.now() - startedAt < diagnosticsFullWaitTimeoutMs) {
696
- const result = await requestFullDiagnostics(request.path);
697
- if (result.handled || result.matched) return;
669
+ while (!connectionClosed && !request.signal?.aborted) {
698
670
  const remaining = diagnosticsFullWaitTimeoutMs - (Date.now() - startedAt);
699
671
  if (remaining <= 0) return;
672
+ const result = await requestFullDiagnostics(request.path);
673
+ if (result.handled || result.matched) return;
674
+ if (result.timedOut) {
675
+ await pushWait;
676
+ return;
677
+ }
700
678
  const next = await Promise.race([
701
- pushWait.then((ready) => (ready ? "push" : ("timeout" as const))),
679
+ pushWait.then((ready) => (ready ? ("push" as const) : ("timeout" as const))),
702
680
  waitForRegistrationChange(remaining).then((changed) =>
703
681
  changed ? ("registration" as const) : ("timeout" as const),
704
682
  ),
683
+ sleep(Math.min(remaining, PULL_RETRY_INTERVAL_MS)).then(() => "interval" as const),
705
684
  ]);
706
- if (next !== "registration") return;
685
+ if (next === "push") return;
707
686
  }
708
687
  }
709
688