grepmax 0.6.3 → 0.6.5

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.
@@ -136,7 +136,7 @@ child.unref();
136
136
  `;
137
137
  const stopScript = `
138
138
  const { spawnSync, execSync } = require("child_process");
139
- try { execSync("pkill -f 'gmax serve'"); } catch {}
139
+ try { execSync("gmax serve stop", { stdio: "ignore" }); } catch {}
140
140
  `;
141
141
  writeFileIfChanged(startJsPath, startScript.trim());
142
142
  writeFileIfChanged(stopJsPath, stopScript.trim());
@@ -354,6 +354,9 @@ exports.mcp = new commander_1.Command("mcp")
354
354
  const searchRoot = typeof args.root === "string"
355
355
  ? path.resolve(args.root)
356
356
  : path.resolve(projectRoot);
357
+ if (typeof args.root === "string" && !fs.existsSync(searchRoot)) {
358
+ return err(`Directory not found: ${args.root}`);
359
+ }
357
360
  displayRoot = searchRoot;
358
361
  pathPrefix = searchRoot.endsWith("/")
359
362
  ? searchRoot
@@ -702,6 +705,6 @@ exports.mcp = new commander_1.Command("mcp")
702
705
  }));
703
706
  yield server.connect(transport);
704
707
  // Kick off index readiness check and watcher in background
705
- ensureIndexReady();
708
+ ensureIndexReady().catch((e) => console.error("[MCP] Index readiness check failed:", e));
706
709
  ensureWatcher();
707
710
  }));
@@ -65,7 +65,7 @@ exports.setup = new commander_1.Command("setup")
65
65
  catch (error) {
66
66
  p.cancel("Setup failed");
67
67
  console.error(error);
68
- process.exit(1);
68
+ yield (0, exit_1.gracefulExit)(1);
69
69
  }
70
70
  // Download grammars
71
71
  const grammarSpinner = p.spinner();
@@ -48,6 +48,7 @@ const fs = __importStar(require("node:fs"));
48
48
  const path = __importStar(require("node:path"));
49
49
  const commander_1 = require("commander");
50
50
  const config_1 = require("../config");
51
+ const filter_builder_1 = require("../lib/utils/filter-builder");
51
52
  const syncer_1 = require("../lib/index/syncer");
52
53
  const watcher_1 = require("../lib/index/watcher");
53
54
  const meta_cache_1 = require("../lib/store/meta-cache");
@@ -113,7 +114,7 @@ exports.watch = new commander_1.Command("watch")
113
114
  const indexed = yield table
114
115
  .query()
115
116
  .select(["id"])
116
- .where(`path LIKE '${prefix}%'`)
117
+ .where(`path LIKE '${(0, filter_builder_1.escapeSqlString)(prefix)}%'`)
117
118
  .limit(1)
118
119
  .toArray();
119
120
  if (indexed.length === 0) {
@@ -57,6 +57,7 @@ const config_1 = require("../../config");
57
57
  const logger_1 = require("../utils/logger");
58
58
  const meta_cache_1 = require("../store/meta-cache");
59
59
  const vector_db_1 = require("../store/vector-db");
60
+ const filter_builder_1 = require("../utils/filter-builder");
60
61
  const file_utils_1 = require("../utils/file-utils");
61
62
  const lock_1 = require("../utils/lock");
62
63
  const project_registry_1 = require("../utils/project-registry");
@@ -85,7 +86,7 @@ function generateSummaries(db, pathPrefix, onProgress, maxChunks) {
85
86
  const rows = yield table
86
87
  .query()
87
88
  .select(["id", "path", "content", "defined_symbols"])
88
- .where(`path LIKE '${pathPrefix}%' AND (summary IS NULL OR summary = '')`)
89
+ .where(`path LIKE '${(0, filter_builder_1.escapeSqlString)(pathPrefix)}%' AND (summary IS NULL OR summary = '')`)
89
90
  .limit(queryLimit)
90
91
  .toArray();
91
92
  if (rows.length === 0)
@@ -47,6 +47,7 @@ exports.startWatcher = startWatcher;
47
47
  const fs = __importStar(require("node:fs"));
48
48
  const path = __importStar(require("node:path"));
49
49
  const chokidar_1 = require("chokidar");
50
+ const filter_builder_1 = require("../utils/filter-builder");
50
51
  const file_utils_1 = require("../utils/file-utils");
51
52
  const logger_1 = require("../utils/logger");
52
53
  const lock_1 = require("../utils/lock");
@@ -208,7 +209,7 @@ function startWatcher(opts) {
208
209
  try {
209
210
  const table = yield vectorDb.ensureTable();
210
211
  for (const id of changedIds) {
211
- const escaped = id.replace(/'/g, "''");
212
+ const escaped = (0, filter_builder_1.escapeSqlString)(id);
212
213
  const rows = yield table
213
214
  .query()
214
215
  .select(["id", "path", "content"])
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.getStoredSkeleton = getStoredSkeleton;
13
+ const filter_builder_1 = require("../utils/filter-builder");
13
14
  function getStoredSkeleton(db, filePath) {
14
15
  return __awaiter(this, void 0, void 0, function* () {
15
16
  try {
@@ -17,7 +18,7 @@ function getStoredSkeleton(db, filePath) {
17
18
  // LanceDB query
18
19
  const results = yield table
19
20
  .query()
20
- .where(`path = '${filePath.replace(/'/g, "''")}' AND is_anchor = true`)
21
+ .where(`path = '${(0, filter_builder_1.escapeSqlString)(filePath)}' AND is_anchor = true`)
21
22
  .limit(1)
22
23
  .toArray();
23
24
  if (results.length > 0) {
@@ -47,6 +47,7 @@ const fs = __importStar(require("node:fs"));
47
47
  const lancedb = __importStar(require("@lancedb/lancedb"));
48
48
  const apache_arrow_1 = require("apache-arrow");
49
49
  const config_1 = require("../../config");
50
+ const filter_builder_1 = require("../utils/filter-builder");
50
51
  const logger_1 = require("../utils/logger");
51
52
  const cleanup_1 = require("../utils/cleanup");
52
53
  const TABLE_NAME = "chunks";
@@ -292,7 +293,7 @@ class VectorDB {
292
293
  const rows = yield table
293
294
  .query()
294
295
  .select(["id"])
295
- .where(`path LIKE '${prefix.replace(/'/g, "''")}%'`)
296
+ .where(`path LIKE '${(0, filter_builder_1.escapeSqlString)(prefix)}%'`)
296
297
  .limit(1)
297
298
  .toArray();
298
299
  return rows.length > 0;
@@ -324,7 +325,7 @@ class VectorDB {
324
325
  const batchSize = 500;
325
326
  for (let i = 0; i < unique.length; i += batchSize) {
326
327
  const slice = unique.slice(i, i + batchSize);
327
- const values = slice.map((p) => `'${p.replace(/'/g, "''")}'`).join(",");
328
+ const values = slice.map((p) => `'${(0, filter_builder_1.escapeSqlString)(p)}'`).join(",");
328
329
  yield table.delete(`path IN (${values})`);
329
330
  }
330
331
  });
@@ -336,7 +337,7 @@ class VectorDB {
336
337
  return;
337
338
  const table = yield this.ensureTable();
338
339
  for (let i = 0; i < ids.length; i++) {
339
- const escaped = ids[i].replace(/'/g, "''");
340
+ const escaped = (0, filter_builder_1.escapeSqlString)(ids[i]);
340
341
  yield table.update({
341
342
  where: `id = '${escaped}'`,
342
343
  values: { [field]: (_a = values[i]) !== null && _a !== void 0 ? _a : "" },
@@ -352,12 +353,12 @@ class VectorDB {
352
353
  const unique = Array.from(new Set(paths));
353
354
  const batchSize = 500;
354
355
  const idExclusion = excludeIds.length > 0
355
- ? ` AND id NOT IN (${excludeIds.map((id) => `'${id.replace(/'/g, "''")}'`).join(",")})`
356
+ ? ` AND id NOT IN (${excludeIds.map((id) => `'${(0, filter_builder_1.escapeSqlString)(id)}'`).join(",")})`
356
357
  : "";
357
358
  for (let i = 0; i < unique.length; i += batchSize) {
358
359
  const slice = unique.slice(i, i + batchSize);
359
360
  const values = slice
360
- .map((p) => `'${p.replace(/'/g, "''")}'`)
361
+ .map((p) => `'${(0, filter_builder_1.escapeSqlString)(p)}'`)
361
362
  .join(",");
362
363
  yield table.delete(`path IN (${values})${idExclusion}`);
363
364
  }
@@ -366,8 +367,7 @@ class VectorDB {
366
367
  deletePathsWithPrefix(prefix) {
367
368
  return __awaiter(this, void 0, void 0, function* () {
368
369
  const table = yield this.ensureTable();
369
- const escaped = prefix.replace(/'/g, "''");
370
- yield table.delete(`path LIKE '${escaped}%'`);
370
+ yield table.delete(`path LIKE '${(0, filter_builder_1.escapeSqlString)(prefix)}%'`);
371
371
  });
372
372
  }
373
373
  drop() {
@@ -114,6 +114,7 @@ class WorkerPool {
114
114
  this.nextId = 1;
115
115
  this.destroyed = false;
116
116
  this.destroyPromise = null;
117
+ this.consecutiveRespawns = 0;
117
118
  const resolved = resolveProcessWorker();
118
119
  this.modulePath = resolved.filename;
119
120
  this.execArgv = resolved.execArgv;
@@ -153,6 +154,11 @@ class WorkerPool {
153
154
  (0, logger_1.log)("pool", `Worker PID:${worker.child.pid} exited (code:${code} signal:${signal})`);
154
155
  this.workers = this.workers.filter((w) => w !== worker);
155
156
  if (!this.destroyed) {
157
+ this.consecutiveRespawns++;
158
+ if (this.consecutiveRespawns > WorkerPool.MAX_RESPAWNS) {
159
+ console.error(`[pool] Worker respawn limit reached (${WorkerPool.MAX_RESPAWNS}). Not spawning more workers.`);
160
+ return;
161
+ }
156
162
  this.spawnWorker();
157
163
  this.dispatch();
158
164
  }
@@ -183,6 +189,7 @@ class WorkerPool {
183
189
  task.resolve(result);
184
190
  }
185
191
  this.completeTask(task, worker);
192
+ this.consecutiveRespawns = 0;
186
193
  this.dispatch();
187
194
  };
188
195
  const onExit = (code, signal) => this.handleWorkerExit(worker, code, signal);
@@ -355,6 +362,7 @@ class WorkerPool {
355
362
  }
356
363
  }
357
364
  exports.WorkerPool = WorkerPool;
365
+ WorkerPool.MAX_RESPAWNS = 10;
358
366
  let singleton = null;
359
367
  function getWorkerPool() {
360
368
  if (!singleton) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "author": "Robert Owens <robowens@me.com>",
5
5
  "homepage": "https://github.com/reowens/grepmax",
6
6
  "bugs": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.6.3",
3
+ "version": "0.6.5",
4
4
  "description": "Semantic code search for Claude Code. Automatically indexes your project and provides intelligent search capabilities.",
5
5
  "author": {
6
6
  "name": "Robert Owens",