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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-readseek",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Pi extension for readseek-backed hash-anchored read/edit/grep, structural code maps, structural search, and file exploration",
5
5
  "type": "module",
6
6
  "exports": {
package/src/edit-diff.ts CHANGED
@@ -14,6 +14,7 @@ export function detectLineEnding(content: string): "\r\n" | "\n" {
14
14
  lf++;
15
15
  }
16
16
  }
17
+ if (lf === 0 && crlf === 0) return "\n";
17
18
  if (lf === 0) return "\r\n";
18
19
  if (crlf === 0) return "\n";
19
20
  return crlf > lf ? "\r\n" : "\n";
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
- if (state.cache.has(absPath)) state.cache.delete(absPath);
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.delete(absPath);
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, readFileSync, writeFileSync } from "node:fs";
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
- function readPreviousTextForDiff(filePath: string): string {
96
+
97
+ async function readPreviousTextForDiff(filePath: string): Promise<string> {
96
98
  try {
97
99
  if (!existsSync(filePath)) return "";
98
- const previous = readFileSync(filePath);
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