grepmax 0.15.1 → 0.15.2

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.
@@ -361,12 +361,13 @@ exports.doctor = new commander_1.Command("doctor")
361
361
  }
362
362
  yield db.close();
363
363
  }
364
- catch (_g) {
364
+ catch (err) {
365
+ const msg = err instanceof Error ? err.message : String(err);
365
366
  if (opts.agent) {
366
- console.log("index_health\terror=could_not_check");
367
+ console.log(`index_health\terror=${msg.replace(/\t/g, " ")}`);
367
368
  }
368
369
  else {
369
- console.log("\nWARN Could not check index health");
370
+ console.log(`\nWARN Could not check index health: ${msg}`);
370
371
  }
371
372
  }
372
373
  if (!opts.agent) {
@@ -86,7 +86,9 @@ class LlmServer {
86
86
  if (runningModel) {
87
87
  const configBasename = path.basename(this.config.model);
88
88
  if (runningModel !== configBasename && !configBasename.includes(runningModel) && !runningModel.includes(configBasename)) {
89
- console.log(`[llm] Model mismatch: running "${runningModel}" but config expects "${configBasename}"`);
89
+ console.log(`[llm] Model mismatch: running "${runningModel}" but config expects "${configBasename}" — will restart`);
90
+ resolve(false);
91
+ return;
90
92
  }
91
93
  }
92
94
  }
@@ -120,6 +122,12 @@ class LlmServer {
120
122
  this.startIdleWatchdog();
121
123
  return;
122
124
  }
125
+ // Kill stale/mismatched server before spawning a new one
126
+ const existingPid = this.readPid();
127
+ if (existingPid && this.isAlive(existingPid)) {
128
+ console.log(`[llm] Stopping existing server (PID: ${existingPid}) before restart`);
129
+ yield this.stop();
130
+ }
123
131
  // Validate binary
124
132
  const binary = this.config.binary;
125
133
  try {
@@ -38,6 +38,9 @@ var __importStar = (this && this.__importStar) || (function () {
38
38
  return result;
39
39
  };
40
40
  })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
41
44
  Object.defineProperty(exports, "__esModule", { value: true });
42
45
  exports.registerProject = registerProject;
43
46
  exports.listProjects = listProjects;
@@ -47,6 +50,7 @@ exports.getParentProject = getParentProject;
47
50
  exports.getChildProjects = getChildProjects;
48
51
  const fs = __importStar(require("node:fs"));
49
52
  const path = __importStar(require("node:path"));
53
+ const proper_lockfile_1 = __importDefault(require("proper-lockfile"));
50
54
  const config_1 = require("../../config");
51
55
  const REGISTRY_PATH = path.join(config_1.PATHS.globalRoot, "projects.json");
52
56
  function loadRegistry() {
@@ -64,16 +68,37 @@ function saveRegistry(entries) {
64
68
  fs.writeFileSync(tmp, `${JSON.stringify(entries, null, 2)}\n`);
65
69
  fs.renameSync(tmp, REGISTRY_PATH);
66
70
  }
67
- function registerProject(entry) {
68
- const entries = loadRegistry();
69
- const idx = entries.findIndex((e) => e.root === entry.root);
70
- if (idx >= 0) {
71
- entries[idx] = entry;
71
+ function withRegistryLock(fn) {
72
+ // Ensure the directory exists for the lock target
73
+ fs.mkdirSync(path.dirname(REGISTRY_PATH), { recursive: true });
74
+ // Ensure the file exists (lockSync needs it)
75
+ if (!fs.existsSync(REGISTRY_PATH)) {
76
+ fs.writeFileSync(REGISTRY_PATH, "[]\n");
77
+ }
78
+ let release;
79
+ try {
80
+ release = proper_lockfile_1.default.lockSync(REGISTRY_PATH, { stale: 10000, retries: { retries: 3, minTimeout: 100 } });
81
+ return fn();
72
82
  }
73
- else {
74
- entries.push(entry);
83
+ finally {
84
+ try {
85
+ release === null || release === void 0 ? void 0 : release();
86
+ }
87
+ catch (_a) { }
75
88
  }
76
- saveRegistry(entries);
89
+ }
90
+ function registerProject(entry) {
91
+ withRegistryLock(() => {
92
+ const entries = loadRegistry();
93
+ const idx = entries.findIndex((e) => e.root === entry.root);
94
+ if (idx >= 0) {
95
+ entries[idx] = entry;
96
+ }
97
+ else {
98
+ entries.push(entry);
99
+ }
100
+ saveRegistry(entries);
101
+ });
77
102
  }
78
103
  function listProjects() {
79
104
  return loadRegistry();
@@ -82,8 +107,10 @@ function getProject(root) {
82
107
  return loadRegistry().find((e) => e.root === root);
83
108
  }
84
109
  function removeProject(root) {
85
- const entries = loadRegistry().filter((e) => e.root !== root);
86
- saveRegistry(entries);
110
+ withRegistryLock(() => {
111
+ const entries = loadRegistry().filter((e) => e.root !== root);
112
+ saveRegistry(entries);
113
+ });
87
114
  }
88
115
  /**
89
116
  * Find a registered parent that covers this path, if any.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "author": "Robert Owens <78518764+reowens@users.noreply.github.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.15.1",
3
+ "version": "0.15.2",
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",