grepmax 0.14.8 → 0.14.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.
@@ -146,20 +146,77 @@ class Daemon {
146
146
  }
147
147
  throw err;
148
148
  }
149
- // 2. Kill existing per-project watchers
149
+ // 2. Stale socket cleanup + start socket server EARLY.
150
+ // The socket must be listening before the PID file is written so that
151
+ // other daemons checking isDaemonRunning() never see a PID for a process
152
+ // that can't respond to pings. Without this, the slow initialization
153
+ // steps below (LanceDB, MLX, project watchers) create a window where
154
+ // new daemons kill this one as "unresponsive".
155
+ try {
156
+ fs.unlinkSync(config_1.PATHS.daemonSocket);
157
+ }
158
+ catch (_b) { }
159
+ this.server = net.createServer((conn) => {
160
+ (0, logger_1.debug)("daemon", "client connected");
161
+ let buf = "";
162
+ conn.on("data", (chunk) => {
163
+ buf += chunk.toString();
164
+ if (buf.length > 1000000) {
165
+ conn.destroy();
166
+ return;
167
+ }
168
+ const nl = buf.indexOf("\n");
169
+ if (nl === -1)
170
+ return;
171
+ const line = buf.slice(0, nl);
172
+ buf = buf.slice(nl + 1);
173
+ let cmd;
174
+ try {
175
+ cmd = JSON.parse(line);
176
+ }
177
+ catch (_a) {
178
+ conn.write(`${JSON.stringify({ ok: false, error: "invalid JSON" })}\n`);
179
+ conn.end();
180
+ return;
181
+ }
182
+ (0, ipc_handler_1.handleCommand)(this, cmd, conn).then((resp) => {
183
+ // null means the handler is managing the connection (streaming)
184
+ if (resp !== null) {
185
+ conn.write(`${JSON.stringify(resp)}\n`);
186
+ conn.end();
187
+ }
188
+ });
189
+ });
190
+ conn.on("error", () => { });
191
+ });
192
+ yield new Promise((resolve, reject) => {
193
+ this.server.on("error", (err) => {
194
+ const code = err.code;
195
+ if (code === "EADDRINUSE") {
196
+ console.error("[daemon] Socket already in use");
197
+ reject(err);
198
+ }
199
+ else if (code === "EOPNOTSUPP") {
200
+ console.error("[daemon] Filesystem does not support Unix sockets");
201
+ process.exitCode = 2;
202
+ reject(err);
203
+ }
204
+ else {
205
+ reject(err);
206
+ }
207
+ });
208
+ this.server.listen(config_1.PATHS.daemonSocket, () => resolve());
209
+ });
210
+ // 3. Write PID file AFTER socket is listening — ensures any process that
211
+ // reads the PID can immediately ping this daemon and get a response.
212
+ fs.writeFileSync(config_1.PATHS.daemonPidFile, String(process.pid));
213
+ // 4. Kill existing per-project watchers
150
214
  const existing = (0, watcher_store_1.listWatchers)();
151
215
  for (const w of existing) {
152
216
  console.log(`[daemon] Taking over from per-project watcher (PID: ${w.pid}, ${path.basename(w.projectRoot)})`);
153
217
  yield (0, process_1.killProcess)(w.pid);
154
218
  (0, watcher_store_1.unregisterWatcher)(w.pid);
155
219
  }
156
- // 3. Write PID file (informational only — lock is the real guard)
157
- fs.writeFileSync(config_1.PATHS.daemonPidFile, String(process.pid));
158
- // 4. Stale socket cleanup
159
- try {
160
- fs.unlinkSync(config_1.PATHS.daemonSocket);
161
- }
162
- catch (_b) { }
163
220
  // 5. Open shared resources
164
221
  try {
165
222
  fs.mkdirSync(config_1.PATHS.cacheDir, { recursive: true });
@@ -222,58 +279,6 @@ class Daemon {
222
279
  this.shutdown();
223
280
  }
224
281
  }, HEARTBEAT_INTERVAL_MS);
225
- // 11. Socket server
226
- this.server = net.createServer((conn) => {
227
- (0, logger_1.debug)("daemon", "client connected");
228
- let buf = "";
229
- conn.on("data", (chunk) => {
230
- buf += chunk.toString();
231
- if (buf.length > 1000000) {
232
- conn.destroy();
233
- return;
234
- }
235
- const nl = buf.indexOf("\n");
236
- if (nl === -1)
237
- return;
238
- const line = buf.slice(0, nl);
239
- buf = buf.slice(nl + 1);
240
- let cmd;
241
- try {
242
- cmd = JSON.parse(line);
243
- }
244
- catch (_a) {
245
- conn.write(`${JSON.stringify({ ok: false, error: "invalid JSON" })}\n`);
246
- conn.end();
247
- return;
248
- }
249
- (0, ipc_handler_1.handleCommand)(this, cmd, conn).then((resp) => {
250
- // null means the handler is managing the connection (streaming)
251
- if (resp !== null) {
252
- conn.write(`${JSON.stringify(resp)}\n`);
253
- conn.end();
254
- }
255
- });
256
- });
257
- conn.on("error", () => { });
258
- });
259
- yield new Promise((resolve, reject) => {
260
- this.server.on("error", (err) => {
261
- const code = err.code;
262
- if (code === "EADDRINUSE") {
263
- console.error("[daemon] Socket already in use");
264
- reject(err);
265
- }
266
- else if (code === "EOPNOTSUPP") {
267
- console.error("[daemon] Filesystem does not support Unix sockets");
268
- process.exitCode = 2;
269
- reject(err);
270
- }
271
- else {
272
- reject(err);
273
- }
274
- });
275
- this.server.listen(config_1.PATHS.daemonSocket, () => resolve());
276
- });
277
282
  console.log(`[daemon] Started (PID: ${process.pid}, ${this.processors.size} projects)`);
278
283
  });
279
284
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.14.8",
3
+ "version": "0.14.9",
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.14.8",
3
+ "version": "0.14.9",
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",