pi-readseek 0.3.21 → 0.3.22

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.3.21",
3
+ "version": "0.3.22",
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": {
@@ -39,7 +39,7 @@
39
39
  "node": ">=20.0.0"
40
40
  },
41
41
  "dependencies": {
42
- "@jarkkojs/readseek": "^0.3.17",
42
+ "@jarkkojs/readseek": "^0.3.20",
43
43
  "diff": "^8.0.3",
44
44
  "ignore": "^7.0.5",
45
45
  "picomatch": "^4.0.4",
@@ -1,5 +1,7 @@
1
1
  import { spawn, type StdioOptions } from "node:child_process";
2
+ import { existsSync, readFileSync, statSync } from "node:fs";
2
3
  import { createRequire } from "node:module";
4
+ import { homedir } from "node:os";
3
5
  import path from "node:path";
4
6
 
5
7
  import { DetailLevel } from "./readseek/enums.js";
@@ -165,6 +167,8 @@ function symbolsFromReadseek(symbols: ReadseekSymbol[]): FileSymbol[] {
165
167
  }
166
168
 
167
169
  const require = createRequire(import.meta.url);
170
+ const READSEEK_REPO_PACKAGE_NAMES = new Set(["@jarkkojs/readseek", "readseek"]);
171
+ let defaultReadseekDirInit: Promise<string | null> | undefined;
168
172
 
169
173
  function readseekPackageDir(): string {
170
174
  return path.dirname(require.resolve("@jarkkojs/readseek/package.json"));
@@ -199,12 +203,39 @@ export function isReadseekAvailable(): boolean {
199
203
  }
200
204
  }
201
205
 
202
- interface RunReadseekOptions {
203
- signal?: AbortSignal;
204
- stdin?: string;
206
+ function directoryExists(dirPath: string): boolean {
207
+ try {
208
+ return statSync(dirPath).isDirectory();
209
+ } catch {
210
+ return false;
211
+ }
205
212
  }
206
213
 
207
- async function runReadseekRaw(args: string[], options: RunReadseekOptions = {}): Promise<string> {
214
+ function isOwnReadseekRepository(cwd = process.cwd()): boolean {
215
+ let dir = path.resolve(cwd);
216
+ while (true) {
217
+ const packageJsonPath = path.join(dir, "package.json");
218
+ if (existsSync(packageJsonPath)) {
219
+ try {
220
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8")) as { name?: unknown };
221
+ if (typeof packageJson.name === "string" && READSEEK_REPO_PACKAGE_NAMES.has(packageJson.name)) return true;
222
+ } catch {
223
+ // Ignore unreadable or invalid package manifests while walking up.
224
+ }
225
+ }
226
+
227
+ const parent = path.dirname(dir);
228
+ if (parent === dir) return false;
229
+ dir = parent;
230
+ }
231
+ }
232
+
233
+ function defaultReadseekDir(): string | null {
234
+ const home = homedir();
235
+ return home ? path.join(home, ".pi", "readseek") : null;
236
+ }
237
+
238
+ async function spawnReadseekRaw(args: string[], options: RunReadseekOptions = {}): Promise<string> {
208
239
  return new Promise<string>((resolve, reject) => {
209
240
  let settled = false;
210
241
  const fail = (error: Error): void => {
@@ -265,6 +296,36 @@ async function runReadseekRaw(args: string[], options: RunReadseekOptions = {}):
265
296
  });
266
297
  }
267
298
 
299
+ async function ensureDefaultReadseekDir(): Promise<string | null> {
300
+ const dir = defaultReadseekDir();
301
+ if (!dir) return null;
302
+ if (directoryExists(dir)) return dir;
303
+
304
+ defaultReadseekDirInit ??= spawnReadseekRaw(["--readseek-dir", dir, "init"])
305
+ .then(() => (directoryExists(dir) ? dir : null))
306
+ .catch(() => null)
307
+ .finally(() => {
308
+ defaultReadseekDirInit = undefined;
309
+ });
310
+ return defaultReadseekDirInit;
311
+ }
312
+
313
+ async function readseekInvocationArgs(args: string[]): Promise<string[]> {
314
+ if (isOwnReadseekRepository()) return args;
315
+
316
+ const readseekDir = await ensureDefaultReadseekDir();
317
+ return readseekDir ? ["--readseek-dir", readseekDir, ...args] : args;
318
+ }
319
+
320
+ interface RunReadseekOptions {
321
+ signal?: AbortSignal;
322
+ stdin?: string;
323
+ }
324
+
325
+ async function runReadseekRaw(args: string[], options: RunReadseekOptions = {}): Promise<string> {
326
+ return spawnReadseekRaw(await readseekInvocationArgs(args), options);
327
+ }
328
+
268
329
  async function runReadseek(args: string[], options: RunReadseekOptions = {}): Promise<unknown> {
269
330
  const stdout = await runReadseekRaw(args, options);
270
331
  return JSON.parse(stdout) as unknown;