pi-readseek 0.4.8 → 0.4.9
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 +1 -1
- package/src/edit-diff.ts +1 -0
- package/src/edit.ts +1 -0
- package/src/grep.ts +18 -0
- package/src/map-cache.ts +7 -4
- package/src/write.ts +6 -4
package/package.json
CHANGED
package/src/edit-diff.ts
CHANGED
package/src/edit.ts
CHANGED
|
@@ -277,6 +277,7 @@ export async function executeEdit(opts: ExecuteEditOptions): Promise<any> {
|
|
|
277
277
|
const replaceSymbolRanges: { start: number; end: number }[] = [];
|
|
278
278
|
const rsProbeResults: { type: "ok"; content: string; replacement: string; warnings: string[]; range: { start: number; end: number } }[] = [];
|
|
279
279
|
for (const rs of replaceSymbolEdits) {
|
|
280
|
+
throwIfAborted(signal);
|
|
280
281
|
const probe = await replaceSymbol({
|
|
281
282
|
filePath: absolutePath,
|
|
282
283
|
content: originalNormalized,
|
package/src/grep.ts
CHANGED
|
@@ -315,6 +315,24 @@ export async function executeGrep(opts: ExecuteGrepOptions): Promise<any> {
|
|
|
315
315
|
let parsedCount = 0;
|
|
316
316
|
let candidateUnparsedCount = 0;
|
|
317
317
|
const candidateLinePattern = /^.+(?::|-)\d+(?::|-)\s/;
|
|
318
|
+
// Pre-read all matched files with bounded concurrency so the processing
|
|
319
|
+
// loop below hits the cache on every getFileLines call instead of
|
|
320
|
+
// serialising disk I/O.
|
|
321
|
+
if (!p.summary) {
|
|
322
|
+
const pathsToRead = new Set<string>();
|
|
323
|
+
for (const line of textBlock.text.split("\n")) {
|
|
324
|
+
throwIfAborted(signal);
|
|
325
|
+
const parsed = parseGrepOutputLine(line);
|
|
326
|
+
if (parsed && Number.isFinite(parsed.lineNumber) && parsed.lineNumber >= 1) {
|
|
327
|
+
pathsToRead.add(toAbsolutePath(parsed.displayPath));
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const CONCURRENCY = 8;
|
|
331
|
+
const pathList = [...pathsToRead];
|
|
332
|
+
for (let i = 0; i < pathList.length; i += CONCURRENCY) {
|
|
333
|
+
await Promise.all(pathList.slice(i, i + CONCURRENCY).map((p) => getFileLines(p)));
|
|
334
|
+
}
|
|
335
|
+
}
|
|
318
336
|
|
|
319
337
|
const addSummaryMatch = (displayPath: string, absolutePath: string) => {
|
|
320
338
|
let group = groupsByPath.get(displayPath);
|
package/src/map-cache.ts
CHANGED
|
@@ -29,11 +29,15 @@ function getMapCacheState(): MapCacheGlobalState {
|
|
|
29
29
|
globalObject[MAP_CACHE_STATE_KEY] = state;
|
|
30
30
|
return state;
|
|
31
31
|
}
|
|
32
|
+
/** Move an existing entry to the most-recently-used position (Map insertion-order tail). */
|
|
33
|
+
function touchMapEntry<K, V>(map: Map<K, V>, key: K, value: V): void {
|
|
34
|
+
map.delete(key);
|
|
35
|
+
map.set(key, value);
|
|
36
|
+
}
|
|
32
37
|
|
|
33
38
|
function rememberInMemory(absPath: string, entry: CacheEntry): void {
|
|
34
39
|
const state = getMapCacheState();
|
|
35
|
-
|
|
36
|
-
state.cache.set(absPath, entry);
|
|
40
|
+
touchMapEntry(state.cache, absPath, entry);
|
|
37
41
|
if (state.cache.size > state.maxSize) {
|
|
38
42
|
const oldestKey = state.cache.keys().next().value;
|
|
39
43
|
if (oldestKey !== undefined) state.cache.delete(oldestKey);
|
|
@@ -55,8 +59,7 @@ export async function getOrGenerateMap(absPath: string): Promise<FileMap | null>
|
|
|
55
59
|
const state = getMapCacheState();
|
|
56
60
|
const cached = state.cache.get(absPath);
|
|
57
61
|
if (cached && cached.mtimeMs === mtimeMs) {
|
|
58
|
-
state.cache
|
|
59
|
-
state.cache.set(absPath, cached);
|
|
62
|
+
touchMapEntry(state.cache, absPath, cached);
|
|
60
63
|
return cached.map;
|
|
61
64
|
}
|
|
62
65
|
const inflight = state.inflight.get(absPath);
|
package/src/write.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { existsSync, mkdirSync,
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { readFile } from "node:fs/promises";
|
|
2
3
|
import { dirname, relative } from "node:path";
|
|
3
4
|
|
|
4
5
|
import { withFileMutationQueue, type ExtensionAPI } from "@earendil-works/pi-coding-agent";
|
|
@@ -92,10 +93,11 @@ export interface WriteResult extends WriteDiffFields {
|
|
|
92
93
|
};
|
|
93
94
|
}
|
|
94
95
|
|
|
95
|
-
|
|
96
|
+
|
|
97
|
+
async function readPreviousTextForDiff(filePath: string): Promise<string> {
|
|
96
98
|
try {
|
|
97
99
|
if (!existsSync(filePath)) return "";
|
|
98
|
-
const previous =
|
|
100
|
+
const previous = await readFile(filePath);
|
|
99
101
|
if (looksLikeBinary(previous)) return "";
|
|
100
102
|
return previous.toString("utf-8");
|
|
101
103
|
} catch {
|
|
@@ -223,7 +225,7 @@ export async function executeWrite(opts: {
|
|
|
223
225
|
},
|
|
224
226
|
};
|
|
225
227
|
}
|
|
226
|
-
const previousContent = readPreviousTextForDiff(filePath);
|
|
228
|
+
const previousContent = await readPreviousTextForDiff(filePath);
|
|
227
229
|
const existedBeforeWrite = existsSync(filePath);
|
|
228
230
|
|
|
229
231
|
// Create parent directories
|