@oh-my-pi/pi-coding-agent 5.2.0 → 5.2.1
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/CHANGELOG.md +6 -0
- package/package.json +5 -5
- package/src/core/tools/lsp/index.ts +39 -7
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.2.1] - 2026-01-14
|
|
6
|
+
### Fixed
|
|
7
|
+
|
|
8
|
+
- Fixed stale diagnostic results by tracking diagnostic versions before file sync operations
|
|
9
|
+
- Fixed race condition where LSP diagnostics could return outdated results after file modifications
|
|
10
|
+
|
|
5
11
|
## [5.2.0] - 2026-01-14
|
|
6
12
|
|
|
7
13
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "5.2.
|
|
3
|
+
"version": "5.2.1",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"ompConfig": {
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"prepublishOnly": "bun run generate-template && bun run clean && bun run build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@oh-my-pi/pi-agent-core": "5.2.
|
|
43
|
-
"@oh-my-pi/pi-ai": "5.2.
|
|
44
|
-
"@oh-my-pi/pi-git-tool": "5.2.
|
|
45
|
-
"@oh-my-pi/pi-tui": "5.2.
|
|
42
|
+
"@oh-my-pi/pi-agent-core": "5.2.1",
|
|
43
|
+
"@oh-my-pi/pi-ai": "5.2.1",
|
|
44
|
+
"@oh-my-pi/pi-git-tool": "5.2.1",
|
|
45
|
+
"@oh-my-pi/pi-tui": "5.2.1",
|
|
46
46
|
"@openai/agents": "^0.3.7",
|
|
47
47
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
48
48
|
"@sinclair/typebox": "^0.34.46",
|
|
@@ -331,12 +331,14 @@ async function waitForDiagnostics(
|
|
|
331
331
|
uri: string,
|
|
332
332
|
timeoutMs = 3000,
|
|
333
333
|
signal?: AbortSignal,
|
|
334
|
+
minVersion?: number,
|
|
334
335
|
): Promise<Diagnostic[]> {
|
|
335
336
|
const start = Date.now();
|
|
336
337
|
while (Date.now() - start < timeoutMs) {
|
|
337
338
|
signal?.throwIfAborted();
|
|
338
339
|
const diagnostics = client.diagnostics.get(uri);
|
|
339
|
-
|
|
340
|
+
const versionOk = minVersion === undefined || client.diagnosticsVersion > minVersion;
|
|
341
|
+
if (diagnostics !== undefined && versionOk) return diagnostics;
|
|
340
342
|
await sleep(100);
|
|
341
343
|
}
|
|
342
344
|
return client.diagnostics.get(uri) ?? [];
|
|
@@ -462,12 +464,35 @@ export interface FileDiagnosticsResult {
|
|
|
462
464
|
formatter?: FileFormatResult;
|
|
463
465
|
}
|
|
464
466
|
|
|
467
|
+
/** Captured diagnostic versions per server (before sync) */
|
|
468
|
+
type DiagnosticVersions = Map<string, number>;
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Capture current diagnostic versions for all LSP servers.
|
|
472
|
+
* Call this BEFORE syncing content to detect stale diagnostics later.
|
|
473
|
+
*/
|
|
474
|
+
async function captureDiagnosticVersions(
|
|
475
|
+
cwd: string,
|
|
476
|
+
servers: Array<[string, ServerConfig]>,
|
|
477
|
+
): Promise<DiagnosticVersions> {
|
|
478
|
+
const versions = new Map<string, number>();
|
|
479
|
+
await Promise.allSettled(
|
|
480
|
+
servers.map(async ([serverName, serverConfig]) => {
|
|
481
|
+
if (serverConfig.createClient) return;
|
|
482
|
+
const client = await getOrCreateClient(serverConfig, cwd);
|
|
483
|
+
versions.set(serverName, client.diagnosticsVersion);
|
|
484
|
+
}),
|
|
485
|
+
);
|
|
486
|
+
return versions;
|
|
487
|
+
}
|
|
488
|
+
|
|
465
489
|
/**
|
|
466
490
|
* Get diagnostics for a file using LSP or custom linter client.
|
|
467
491
|
*
|
|
468
492
|
* @param absolutePath - Absolute path to the file
|
|
469
493
|
* @param cwd - Working directory for LSP config resolution
|
|
470
494
|
* @param servers - Servers to query diagnostics for
|
|
495
|
+
* @param minVersions - Minimum diagnostic versions per server (to detect stale results)
|
|
471
496
|
* @returns Diagnostic results or undefined if no servers
|
|
472
497
|
*/
|
|
473
498
|
async function getDiagnosticsForFile(
|
|
@@ -475,6 +500,7 @@ async function getDiagnosticsForFile(
|
|
|
475
500
|
cwd: string,
|
|
476
501
|
servers: Array<[string, ServerConfig]>,
|
|
477
502
|
signal?: AbortSignal,
|
|
503
|
+
minVersions?: DiagnosticVersions,
|
|
478
504
|
): Promise<FileDiagnosticsResult | undefined> {
|
|
479
505
|
if (servers.length === 0) {
|
|
480
506
|
return undefined;
|
|
@@ -499,8 +525,9 @@ async function getDiagnosticsForFile(
|
|
|
499
525
|
// Default: use LSP
|
|
500
526
|
const client = await getOrCreateClient(serverConfig, cwd);
|
|
501
527
|
signal?.throwIfAborted();
|
|
502
|
-
// Content already synced + didSave sent,
|
|
503
|
-
const
|
|
528
|
+
// Content already synced + didSave sent, wait for fresh diagnostics
|
|
529
|
+
const minVersion = minVersions?.get(serverName);
|
|
530
|
+
const diagnostics = await waitForDiagnostics(client, uri, 3000, signal, minVersion);
|
|
504
531
|
return { serverName, diagnostics };
|
|
505
532
|
}),
|
|
506
533
|
);
|
|
@@ -675,6 +702,9 @@ export function createLspWritethrough(cwd: string, options?: WritethroughOptions
|
|
|
675
702
|
const getWritePromise = once(() => writeContent(finalContent));
|
|
676
703
|
const useCustomFormatter = enableFormat && customLinterServers.length > 0;
|
|
677
704
|
|
|
705
|
+
// Capture diagnostic versions BEFORE syncing to detect stale diagnostics
|
|
706
|
+
const minVersions = enableDiagnostics ? await captureDiagnosticVersions(cwd, servers) : undefined;
|
|
707
|
+
|
|
678
708
|
let formatter: FileFormatResult | undefined;
|
|
679
709
|
let diagnostics: FileDiagnosticsResult | undefined;
|
|
680
710
|
try {
|
|
@@ -710,9 +740,9 @@ export function createLspWritethrough(cwd: string, options?: WritethroughOptions
|
|
|
710
740
|
// 5. Notify saved to LSP servers
|
|
711
741
|
await notifyFileSaved(dst, cwd, lspServers, operationSignal);
|
|
712
742
|
|
|
713
|
-
// 6. Get diagnostics from all servers
|
|
743
|
+
// 6. Get diagnostics from all servers (wait for fresh results)
|
|
714
744
|
if (enableDiagnostics) {
|
|
715
|
-
diagnostics = await getDiagnosticsForFile(dst, cwd, servers, operationSignal);
|
|
745
|
+
diagnostics = await getDiagnosticsForFile(dst, cwd, servers, operationSignal, minVersions);
|
|
716
746
|
}
|
|
717
747
|
});
|
|
718
748
|
} catch {
|
|
@@ -829,8 +859,9 @@ export function createLspTool(session: ToolSession): AgentTool<typeof lspSchema,
|
|
|
829
859
|
continue;
|
|
830
860
|
}
|
|
831
861
|
const client = await getOrCreateClient(serverConfig, session.cwd);
|
|
862
|
+
const minVersion = client.diagnosticsVersion;
|
|
832
863
|
await refreshFile(client, resolved);
|
|
833
|
-
const diagnostics = await waitForDiagnostics(client, uri);
|
|
864
|
+
const diagnostics = await waitForDiagnostics(client, uri, 3000, undefined, minVersion);
|
|
834
865
|
allDiagnostics.push(...diagnostics);
|
|
835
866
|
} catch {
|
|
836
867
|
// Server failed, continue with others
|
|
@@ -1091,8 +1122,9 @@ export function createLspTool(session: ToolSession): AgentTool<typeof lspSchema,
|
|
|
1091
1122
|
};
|
|
1092
1123
|
}
|
|
1093
1124
|
|
|
1125
|
+
const actionsMinVersion = client.diagnosticsVersion;
|
|
1094
1126
|
await refreshFile(client, targetFile);
|
|
1095
|
-
const diagnostics = await waitForDiagnostics(client, uri);
|
|
1127
|
+
const diagnostics = await waitForDiagnostics(client, uri, 3000, undefined, actionsMinVersion);
|
|
1096
1128
|
const endLine = (end_line ?? line ?? 1) - 1;
|
|
1097
1129
|
const endCharacter = (end_character ?? column ?? 1) - 1;
|
|
1098
1130
|
const range = { start: position, end: { line: endLine, character: endCharacter } };
|