grepmax 0.24.0 → 0.25.0

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.
Files changed (75) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/README.md +11 -6
  3. package/dist/commands/add.js +38 -31
  4. package/dist/commands/config.js +16 -15
  5. package/dist/commands/context.js +38 -13
  6. package/dist/commands/doctor.js +76 -83
  7. package/dist/commands/extract.js +12 -1
  8. package/dist/commands/index.js +23 -24
  9. package/dist/commands/list.js +23 -14
  10. package/dist/commands/mcp.js +278 -143
  11. package/dist/commands/peek.js +16 -5
  12. package/dist/commands/repair.js +54 -120
  13. package/dist/commands/search-output.js +30 -9
  14. package/dist/commands/search-run.js +75 -47
  15. package/dist/commands/search-skeletons.js +28 -18
  16. package/dist/commands/search.js +45 -49
  17. package/dist/commands/serve.js +415 -373
  18. package/dist/commands/setup.js +2 -2
  19. package/dist/commands/similar.js +5 -5
  20. package/dist/commands/skeleton.js +67 -41
  21. package/dist/commands/status.js +5 -2
  22. package/dist/commands/summarize.js +6 -0
  23. package/dist/commands/watch.js +102 -38
  24. package/dist/config.js +3 -0
  25. package/dist/lib/daemon/daemon.js +1101 -379
  26. package/dist/lib/daemon/ipc-handler.js +122 -13
  27. package/dist/lib/daemon/mlx-server-manager.js +268 -125
  28. package/dist/lib/daemon/process-manager.js +7 -4
  29. package/dist/lib/daemon/search-handler.js +23 -9
  30. package/dist/lib/daemon/watcher-manager.js +353 -110
  31. package/dist/lib/index/batch-processor.js +231 -67
  32. package/dist/lib/index/embedding-generation.js +109 -0
  33. package/dist/lib/index/embedding-status.js +23 -0
  34. package/dist/lib/index/file-policy.js +273 -0
  35. package/dist/lib/index/ignore-patterns.js +4 -0
  36. package/dist/lib/index/index-config.js +18 -4
  37. package/dist/lib/index/syncer.js +256 -79
  38. package/dist/lib/index/walker.js +66 -86
  39. package/dist/lib/index/watcher-batch.js +9 -0
  40. package/dist/lib/index/watcher.js +129 -3
  41. package/dist/lib/llm/server.js +6 -0
  42. package/dist/lib/search/searcher.js +30 -19
  43. package/dist/lib/store/store-lease.js +473 -0
  44. package/dist/lib/store/vector-db.js +302 -57
  45. package/dist/lib/utils/blocked-roots.js +63 -0
  46. package/dist/lib/utils/cross-project.js +7 -3
  47. package/dist/lib/utils/daemon-client.js +24 -1
  48. package/dist/lib/utils/daemon-launcher.js +38 -13
  49. package/dist/lib/utils/doctor-status.js +76 -0
  50. package/dist/lib/utils/file-utils.js +74 -4
  51. package/dist/lib/utils/keyed-mutex.js +101 -0
  52. package/dist/lib/utils/logger.js +57 -1
  53. package/dist/lib/utils/mlx-hf-cache.js +114 -0
  54. package/dist/lib/utils/operation-coordinator.js +146 -0
  55. package/dist/lib/utils/path-containment.js +106 -0
  56. package/dist/lib/utils/process.js +44 -0
  57. package/dist/lib/utils/project-registry.js +351 -3
  58. package/dist/lib/utils/scope-filter.js +3 -9
  59. package/dist/lib/utils/stale-hint.js +12 -19
  60. package/dist/lib/utils/watcher-launcher.js +5 -1
  61. package/dist/lib/utils/watcher-store.js +2 -2
  62. package/dist/lib/workers/colbert-math.js +15 -12
  63. package/dist/lib/workers/embeddings/colbert.js +3 -2
  64. package/dist/lib/workers/embeddings/granite.js +4 -3
  65. package/dist/lib/workers/embeddings/mlx-client.js +59 -16
  66. package/dist/lib/workers/orchestrator.js +39 -8
  67. package/dist/lib/workers/pool.js +146 -82
  68. package/dist/lib/workers/process-child.js +11 -2
  69. package/dist/lib/workers/serialized-handler.js +10 -0
  70. package/dist/lib/workers/worker.js +13 -4
  71. package/mlx-embed-server/server.py +21 -3
  72. package/mlx-embed-server/summarizer.py +8 -0
  73. package/package.json +4 -3
  74. package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
  75. package/plugins/grepmax/hooks/start.js +3 -170
@@ -0,0 +1,473 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.StoreLease = exports.StoreLeaseTimeoutError = void 0;
49
+ exports.storeLeasePaths = storeLeasePaths;
50
+ exports.hasStoreExclusiveIntent = hasStoreExclusiveIntent;
51
+ const node_child_process_1 = require("node:child_process");
52
+ const node_crypto_1 = require("node:crypto");
53
+ const fs = __importStar(require("node:fs"));
54
+ const path = __importStar(require("node:path"));
55
+ const proper_lockfile_1 = __importDefault(require("proper-lockfile"));
56
+ function storeLeasePaths(storeDir) {
57
+ const root = `${path.resolve(storeDir)}.lease`;
58
+ const intentDir = path.join(root, "exclusive-intent");
59
+ return {
60
+ root,
61
+ readersDir: path.join(root, "readers"),
62
+ intentDir,
63
+ intentOwnerFile: path.join(intentDir, "owner.json"),
64
+ };
65
+ }
66
+ class StoreLeaseTimeoutError extends Error {
67
+ constructor(message, blockers) {
68
+ super(message);
69
+ this.blockers = blockers;
70
+ this.name = "StoreLeaseTimeoutError";
71
+ }
72
+ }
73
+ exports.StoreLeaseTimeoutError = StoreLeaseTimeoutError;
74
+ function abortError() {
75
+ const error = new Error("Aborted");
76
+ error.name = "AbortError";
77
+ return error;
78
+ }
79
+ let cachedCurrentProcessStart = null;
80
+ function currentProcessStart(pid) {
81
+ if (pid === process.pid && cachedCurrentProcessStart) {
82
+ return cachedCurrentProcessStart;
83
+ }
84
+ try {
85
+ const start = (0, node_child_process_1.execFileSync)("ps", ["-p", String(pid), "-o", "lstart="], {
86
+ encoding: "utf8",
87
+ timeout: 1000,
88
+ }).trim();
89
+ if (pid === process.pid)
90
+ cachedCurrentProcessStart = start;
91
+ return start;
92
+ }
93
+ catch (_a) {
94
+ const fallback = `pid:${pid}:started:${Math.trunc(Date.now() - process.uptime() * 1000)}`;
95
+ if (pid === process.pid)
96
+ cachedCurrentProcessStart = fallback;
97
+ return fallback;
98
+ }
99
+ }
100
+ function defaultProbeOwner(owner) {
101
+ try {
102
+ process.kill(owner.pid, 0);
103
+ }
104
+ catch (error) {
105
+ return error.code === "ESRCH"
106
+ ? "dead"
107
+ : "unknown";
108
+ }
109
+ if (owner.processStart.startsWith(`pid:${owner.pid}:started:`))
110
+ return "same";
111
+ try {
112
+ const start = (0, node_child_process_1.execFileSync)("ps", ["-p", String(owner.pid), "-o", "lstart="], { encoding: "utf8", timeout: 1000 }).trim();
113
+ if (!start)
114
+ return "unknown";
115
+ return start === owner.processStart ? "same" : "reused";
116
+ }
117
+ catch (_a) {
118
+ return "unknown";
119
+ }
120
+ }
121
+ function readOwner(filePath) {
122
+ try {
123
+ const parsed = JSON.parse(fs.readFileSync(filePath, "utf8"));
124
+ if (!parsed || typeof parsed !== "object")
125
+ return null;
126
+ const owner = parsed;
127
+ return typeof owner.pid === "number" &&
128
+ typeof owner.processStart === "string" &&
129
+ typeof owner.nonce === "string" &&
130
+ typeof owner.role === "string" &&
131
+ typeof owner.acquiredAt === "number"
132
+ ? owner
133
+ : null;
134
+ }
135
+ catch (_a) {
136
+ return null;
137
+ }
138
+ }
139
+ function writeOwnerAtomic(filePath, owner) {
140
+ const temp = `${filePath}.${owner.nonce}.tmp`;
141
+ fs.writeFileSync(temp, `${JSON.stringify(owner)}\n`, { flag: "wx" });
142
+ fs.renameSync(temp, filePath);
143
+ }
144
+ function delay(ms, signal) {
145
+ return __awaiter(this, void 0, void 0, function* () {
146
+ if (signal === null || signal === void 0 ? void 0 : signal.aborted)
147
+ throw abortError();
148
+ yield new Promise((resolve, reject) => {
149
+ const finish = () => {
150
+ signal === null || signal === void 0 ? void 0 : signal.removeEventListener("abort", onAbort);
151
+ resolve();
152
+ };
153
+ const timer = setTimeout(finish, ms);
154
+ const onAbort = () => {
155
+ clearTimeout(timer);
156
+ signal === null || signal === void 0 ? void 0 : signal.removeEventListener("abort", onAbort);
157
+ reject(abortError());
158
+ };
159
+ signal === null || signal === void 0 ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
160
+ timer.unref();
161
+ });
162
+ });
163
+ }
164
+ class StoreLease {
165
+ constructor(mode, owner, markerPath, paths, storeDir) {
166
+ this.mode = mode;
167
+ this.owner = owner;
168
+ this.markerPath = markerPath;
169
+ this.paths = paths;
170
+ this.storeDir = storeDir;
171
+ this.released = false;
172
+ this.claimedBy = null;
173
+ }
174
+ static acquireShared(options) {
175
+ return __awaiter(this, void 0, void 0, function* () {
176
+ var _a;
177
+ const context = StoreLease.context(options);
178
+ fs.mkdirSync(context.paths.readersDir, { recursive: true });
179
+ const markerPath = path.join(context.paths.readersDir, `${context.owner.nonce}.json`);
180
+ while (Date.now() <= context.deadline) {
181
+ if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted)
182
+ throw abortError();
183
+ StoreLease.withIntentLock(context, () => StoreLease.removeStaleIntent(context));
184
+ if (!fs.existsSync(context.paths.intentDir)) {
185
+ writeOwnerAtomic(markerPath, context.owner);
186
+ if (!fs.existsSync(context.paths.intentDir)) {
187
+ return new StoreLease("shared", context.owner, markerPath, context.paths, options.storeDir);
188
+ }
189
+ fs.rmSync(markerPath, { force: true });
190
+ }
191
+ yield delay(context.pollMs, options.signal);
192
+ }
193
+ throw new StoreLeaseTimeoutError("Timed out waiting for exclusive store intent to clear", StoreLease.intentBlockers(context.paths));
194
+ });
195
+ }
196
+ static acquireExclusive(options) {
197
+ return __awaiter(this, void 0, void 0, function* () {
198
+ var _a, _b;
199
+ const context = StoreLease.context(options);
200
+ fs.mkdirSync(context.paths.readersDir, { recursive: true });
201
+ let ownsIntent = false;
202
+ try {
203
+ while (Date.now() <= context.deadline) {
204
+ if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted)
205
+ throw abortError();
206
+ StoreLease.withIntentLock(context, () => {
207
+ StoreLease.removeStaleIntent(context);
208
+ if (fs.existsSync(context.paths.intentDir))
209
+ return;
210
+ const tempIntent = `${context.paths.intentDir}.${context.owner.nonce}.tmp`;
211
+ try {
212
+ fs.mkdirSync(tempIntent);
213
+ writeOwnerAtomic(path.join(tempIntent, "owner.json"), context.owner);
214
+ fs.renameSync(tempIntent, context.paths.intentDir);
215
+ ownsIntent = true;
216
+ }
217
+ finally {
218
+ fs.rmSync(tempIntent, { recursive: true, force: true });
219
+ }
220
+ });
221
+ if (ownsIntent)
222
+ break;
223
+ yield delay(context.pollMs, options.signal);
224
+ }
225
+ if (!ownsIntent) {
226
+ throw new StoreLeaseTimeoutError("Timed out waiting to acquire exclusive store intent", StoreLease.intentBlockers(context.paths));
227
+ }
228
+ while (Date.now() <= context.deadline) {
229
+ if ((_b = options.signal) === null || _b === void 0 ? void 0 : _b.aborted)
230
+ throw abortError();
231
+ const blockers = StoreLease.liveReaders(context);
232
+ if (blockers.length === 0) {
233
+ const current = readOwner(context.paths.intentOwnerFile);
234
+ if ((current === null || current === void 0 ? void 0 : current.nonce) !== context.owner.nonce) {
235
+ throw new Error("Exclusive store lease ownership was lost");
236
+ }
237
+ return new StoreLease("exclusive", context.owner, context.paths.intentDir, context.paths, options.storeDir);
238
+ }
239
+ yield delay(context.pollMs, options.signal);
240
+ }
241
+ throw new StoreLeaseTimeoutError("Timed out waiting for shared store owners to close", StoreLease.liveReaders(context));
242
+ }
243
+ catch (error) {
244
+ if (ownsIntent) {
245
+ yield StoreLease.releaseIntentWithRetry(context.paths, context.owner, 1000, context.pollMs);
246
+ }
247
+ throw error;
248
+ }
249
+ });
250
+ }
251
+ release() {
252
+ return __awaiter(this, arguments, void 0, function* (options = {}) {
253
+ if (this.released)
254
+ return;
255
+ if (this.mode === "shared") {
256
+ const current = readOwner(this.markerPath);
257
+ if ((current === null || current === void 0 ? void 0 : current.nonce) === this.owner.nonce) {
258
+ fs.rmSync(this.markerPath, { force: true });
259
+ }
260
+ this.released = true;
261
+ this.claimedBy = null;
262
+ return;
263
+ }
264
+ yield StoreLease.releaseIntentWithRetry(this.paths, this.owner, options.timeoutMs, options.pollMs);
265
+ this.released = true;
266
+ this.claimedBy = null;
267
+ });
268
+ }
269
+ claim(holder, storeDir) {
270
+ if (path.resolve(storeDir) !== path.resolve(this.storeDir)) {
271
+ throw new Error("Store lease belongs to a different store");
272
+ }
273
+ if (this.released)
274
+ throw new Error("Store lease has already been released");
275
+ if (this.claimedBy && this.claimedBy !== holder) {
276
+ throw new Error("Store lease is already attached to another owner");
277
+ }
278
+ const current = this.mode === "shared"
279
+ ? readOwner(this.markerPath)
280
+ : readOwner(this.paths.intentOwnerFile);
281
+ if ((current === null || current === void 0 ? void 0 : current.nonce) !== this.owner.nonce) {
282
+ throw new Error("Store lease ownership could not be verified");
283
+ }
284
+ this.claimedBy = holder;
285
+ }
286
+ relinquish(holder) {
287
+ if (this.claimedBy === holder)
288
+ this.claimedBy = null;
289
+ }
290
+ /** Atomically replace this shared lease with an exclusive lease. */
291
+ upgrade() {
292
+ return __awaiter(this, arguments, void 0, function* (options = {}) {
293
+ if (this.mode !== "shared") {
294
+ throw new Error("Only a shared store lease can be upgraded");
295
+ }
296
+ if (this.released)
297
+ throw new Error("Store lease has already been released");
298
+ const exclusive = yield StoreLease.acquireExclusive(Object.assign(Object.assign({}, options), { storeDir: this.storeDir, pid: this.owner.pid, processStart: this.owner.processStart, ignoreNonces: new Set([this.owner.nonce]) }));
299
+ try {
300
+ yield this.release();
301
+ return exclusive;
302
+ }
303
+ catch (error) {
304
+ yield exclusive.release();
305
+ throw error;
306
+ }
307
+ });
308
+ }
309
+ /** Replace this exclusive lease with a shared lease without an ownership gap. */
310
+ downgrade() {
311
+ return __awaiter(this, arguments, void 0, function* (options = {}) {
312
+ if (this.mode !== "exclusive") {
313
+ throw new Error("Only an exclusive store lease can be downgraded");
314
+ }
315
+ if (this.released)
316
+ throw new Error("Store lease has already been released");
317
+ const current = readOwner(this.paths.intentOwnerFile);
318
+ if ((current === null || current === void 0 ? void 0 : current.nonce) !== this.owner.nonce) {
319
+ throw new Error("Exclusive store lease ownership could not be verified");
320
+ }
321
+ const context = StoreLease.context(Object.assign(Object.assign({}, options), { storeDir: this.storeDir, pid: this.owner.pid, processStart: this.owner.processStart }));
322
+ fs.mkdirSync(context.paths.readersDir, { recursive: true });
323
+ const markerPath = path.join(context.paths.readersDir, `${context.owner.nonce}.json`);
324
+ writeOwnerAtomic(markerPath, context.owner);
325
+ try {
326
+ const stillCurrent = readOwner(this.paths.intentOwnerFile);
327
+ if ((stillCurrent === null || stillCurrent === void 0 ? void 0 : stillCurrent.nonce) !== this.owner.nonce) {
328
+ throw new Error("Exclusive store lease ownership changed during downgrade");
329
+ }
330
+ while (!StoreLease.withIntentLock(context, () => StoreLease.releaseIntent(this.paths, this.owner, true))) {
331
+ if (Date.now() > context.deadline) {
332
+ throw new Error("Timed out waiting to release exclusive store intent during downgrade");
333
+ }
334
+ yield delay(context.pollMs, options.signal);
335
+ }
336
+ this.released = true;
337
+ this.claimedBy = null;
338
+ return new StoreLease("shared", context.owner, markerPath, context.paths, this.storeDir);
339
+ }
340
+ catch (error) {
341
+ fs.rmSync(markerPath, { force: true });
342
+ throw error;
343
+ }
344
+ });
345
+ }
346
+ static context(options) {
347
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
348
+ const pid = (_a = options.pid) !== null && _a !== void 0 ? _a : process.pid;
349
+ const nonce = (_b = options.nonce) !== null && _b !== void 0 ? _b : (0, node_crypto_1.randomUUID)();
350
+ if (!/^[A-Za-z0-9._-]+$/.test(nonce)) {
351
+ throw new Error("Store lease nonce contains invalid characters");
352
+ }
353
+ const owner = {
354
+ pid,
355
+ processStart: (_c = options.processStart) !== null && _c !== void 0 ? _c : currentProcessStart(pid),
356
+ nonce,
357
+ role: (_e = (_d = options.role) !== null && _d !== void 0 ? _d : process.title) !== null && _e !== void 0 ? _e : "gmax",
358
+ acquiredAt: Date.now(),
359
+ };
360
+ return {
361
+ owner,
362
+ paths: storeLeasePaths(options.storeDir),
363
+ deadline: Date.now() + ((_f = options.timeoutMs) !== null && _f !== void 0 ? _f : 10000),
364
+ pollMs: (_g = options.pollMs) !== null && _g !== void 0 ? _g : 50,
365
+ ignoreNonces: (_h = options.ignoreNonces) !== null && _h !== void 0 ? _h : new Set(),
366
+ probeOwner: (_j = options.probeOwner) !== null && _j !== void 0 ? _j : defaultProbeOwner,
367
+ };
368
+ }
369
+ static removeStaleIntent(context) {
370
+ if (!fs.existsSync(context.paths.intentDir))
371
+ return;
372
+ const owner = readOwner(context.paths.intentOwnerFile);
373
+ if (!owner)
374
+ return;
375
+ const status = context.probeOwner(owner);
376
+ if (status === "dead" || status === "reused") {
377
+ StoreLease.releaseIntent(context.paths, owner, true);
378
+ }
379
+ }
380
+ static withIntentLock(context, fn) {
381
+ return StoreLease.withIntentPathsLock(context.paths, fn);
382
+ }
383
+ static withIntentPathsLock(paths, fn) {
384
+ fs.mkdirSync(paths.root, { recursive: true });
385
+ let release;
386
+ try {
387
+ release = proper_lockfile_1.default.lockSync(paths.root, {
388
+ realpath: false,
389
+ retries: 0,
390
+ stale: 10000,
391
+ });
392
+ fn();
393
+ return true;
394
+ }
395
+ catch (error) {
396
+ if (error.code !== "ELOCKED")
397
+ throw error;
398
+ return false;
399
+ }
400
+ finally {
401
+ release === null || release === void 0 ? void 0 : release();
402
+ }
403
+ }
404
+ static releaseIntentWithRetry(paths_1, owner_1) {
405
+ return __awaiter(this, arguments, void 0, function* (paths, owner, timeoutMs = 1000, pollMs = 10) {
406
+ const deadline = Date.now() + timeoutMs;
407
+ while (!StoreLease.releaseIntent(paths, owner)) {
408
+ if (Date.now() > deadline) {
409
+ throw new Error("Timed out waiting to release exclusive store intent");
410
+ }
411
+ yield delay(pollMs);
412
+ }
413
+ });
414
+ }
415
+ static releaseIntent(paths, owner, lockHeld = false) {
416
+ const remove = () => {
417
+ const current = readOwner(paths.intentOwnerFile);
418
+ if ((current === null || current === void 0 ? void 0 : current.nonce) === owner.nonce) {
419
+ fs.rmSync(paths.intentDir, { recursive: true, force: true });
420
+ }
421
+ };
422
+ if (lockHeld) {
423
+ remove();
424
+ return true;
425
+ }
426
+ return StoreLease.withIntentPathsLock(paths, remove);
427
+ }
428
+ static intentBlockers(paths) {
429
+ const owner = readOwner(paths.intentOwnerFile);
430
+ return owner ? [owner] : [];
431
+ }
432
+ static liveReaders(context) {
433
+ let names;
434
+ try {
435
+ names = fs.readdirSync(context.paths.readersDir);
436
+ }
437
+ catch (_a) {
438
+ return [];
439
+ }
440
+ const blockers = [];
441
+ for (const name of names) {
442
+ const markerPath = path.join(context.paths.readersDir, name);
443
+ const owner = readOwner(markerPath);
444
+ if (!owner) {
445
+ blockers.push({
446
+ pid: -1,
447
+ processStart: "unknown",
448
+ nonce: name,
449
+ role: "invalid-marker",
450
+ acquiredAt: 0,
451
+ });
452
+ continue;
453
+ }
454
+ if (context.ignoreNonces.has(owner.nonce) &&
455
+ owner.pid === context.owner.pid &&
456
+ owner.processStart === context.owner.processStart) {
457
+ continue;
458
+ }
459
+ const status = context.probeOwner(owner);
460
+ if (status === "dead" || status === "reused") {
461
+ fs.rmSync(markerPath, { force: true });
462
+ }
463
+ else {
464
+ blockers.push(owner);
465
+ }
466
+ }
467
+ return blockers;
468
+ }
469
+ }
470
+ exports.StoreLease = StoreLease;
471
+ function hasStoreExclusiveIntent(storeDir) {
472
+ return fs.existsSync(storeLeasePaths(storeDir).intentDir);
473
+ }