grepmax 0.9.0 → 0.9.1

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.
@@ -100,25 +100,33 @@ class Daemon {
100
100
  console.error("[daemon] Failed to open shared resources:", err);
101
101
  throw err;
102
102
  }
103
- // 4. Create chokidar (empty projects added via watchProject)
104
- const forcePoll = process.env.GMAX_WATCH_POLL === "1";
105
- const usePoll = forcePoll || process.platform !== "darwin";
106
- this.watcher = (0, chokidar_1.watch)([], Object.assign({ ignored: watcher_1.WATCHER_IGNORE_PATTERNS, ignoreInitial: true, persistent: true }, (usePoll
107
- ? { usePolling: true, interval: 5000, binaryInterval: 10000 }
108
- : {})));
103
+ // 4. Register daemon (only after resources are open)
104
+ (0, watcher_store_1.registerDaemon)(process.pid);
105
+ // 5. Load registered projects and create processors
106
+ const projects = (0, project_registry_1.listProjects)().filter((p) => p.status === "indexed");
107
+ const initialRoots = [];
108
+ for (const p of projects) {
109
+ this.addProcessor(p.root);
110
+ initialRoots.push(p.root);
111
+ }
112
+ // 6. Create chokidar with all initial roots
113
+ // Daemon always uses polling — watching multiple large project trees
114
+ // with native fs.watch can exhaust file descriptors even on macOS.
115
+ // Polling at 5s intervals is lightweight and reliable for all platforms.
116
+ this.watcher = (0, chokidar_1.watch)(initialRoots, {
117
+ ignored: watcher_1.WATCHER_IGNORE_PATTERNS,
118
+ ignoreInitial: true,
119
+ persistent: true,
120
+ usePolling: true,
121
+ interval: 5000,
122
+ binaryInterval: 10000,
123
+ });
109
124
  this.watcher.on("add", (p) => this.routeEvent("change", p));
110
125
  this.watcher.on("change", (p) => this.routeEvent("change", p));
111
126
  this.watcher.on("unlink", (p) => this.routeEvent("unlink", p));
112
127
  this.watcher.on("error", (err) => {
113
128
  console.error("[daemon] Watcher error:", err);
114
129
  });
115
- // 5. Register daemon (only after resources are open)
116
- (0, watcher_store_1.registerDaemon)(process.pid);
117
- // 6. Load registered projects
118
- const projects = (0, project_registry_1.listProjects)().filter((p) => p.status === "indexed");
119
- for (const p of projects) {
120
- yield this.watchProject(p.root);
121
- }
122
130
  // 7. Heartbeat
123
131
  this.heartbeatInterval = setInterval(() => {
124
132
  (0, watcher_store_1.heartbeat)(process.pid);
@@ -181,35 +189,42 @@ class Daemon {
181
189
  return __awaiter(this, void 0, void 0, function* () {
182
190
  if (this.processors.has(root) || this.pendingOps.has(root))
183
191
  return;
184
- if (!this.vectorDb || !this.metaCache || !this.watcher)
192
+ if (!this.watcher)
185
193
  return;
186
- this.pendingOps.add(root);
187
- const processor = new batch_processor_1.ProjectBatchProcessor({
188
- projectRoot: root,
189
- vectorDb: this.vectorDb,
190
- metaCache: this.metaCache,
191
- dataDir: config_1.PATHS.globalRoot,
192
- onReindex: (files, ms) => {
193
- console.log(`[daemon:${path.basename(root)}] Reindexed ${files} file${files !== 1 ? "s" : ""} (${(ms / 1000).toFixed(1)}s)`);
194
- },
195
- onActivity: () => {
196
- this.lastActivity = Date.now();
197
- },
198
- });
194
+ this.addProcessor(root);
199
195
  this.watcher.add(root);
200
- this.processors.set(root, processor);
201
- this.rebuildSortedRoots();
202
- (0, watcher_store_1.registerWatcher)({
203
- pid: process.pid,
204
- projectRoot: root,
205
- startTime: Date.now(),
206
- status: "watching",
207
- lastHeartbeat: Date.now(),
208
- });
209
- this.pendingOps.delete(root);
210
196
  console.log(`[daemon] Watching ${root}`);
211
197
  });
212
198
  }
199
+ addProcessor(root) {
200
+ if (this.processors.has(root))
201
+ return;
202
+ if (!this.vectorDb || !this.metaCache)
203
+ return;
204
+ this.pendingOps.add(root);
205
+ const processor = new batch_processor_1.ProjectBatchProcessor({
206
+ projectRoot: root,
207
+ vectorDb: this.vectorDb,
208
+ metaCache: this.metaCache,
209
+ dataDir: config_1.PATHS.globalRoot,
210
+ onReindex: (files, ms) => {
211
+ console.log(`[daemon:${path.basename(root)}] Reindexed ${files} file${files !== 1 ? "s" : ""} (${(ms / 1000).toFixed(1)}s)`);
212
+ },
213
+ onActivity: () => {
214
+ this.lastActivity = Date.now();
215
+ },
216
+ });
217
+ this.processors.set(root, processor);
218
+ this.rebuildSortedRoots();
219
+ (0, watcher_store_1.registerWatcher)({
220
+ pid: process.pid,
221
+ projectRoot: root,
222
+ startTime: Date.now(),
223
+ status: "watching",
224
+ lastHeartbeat: Date.now(),
225
+ });
226
+ this.pendingOps.delete(root);
227
+ }
213
228
  unwatchProject(root) {
214
229
  return __awaiter(this, void 0, void 0, function* () {
215
230
  var _a;
@@ -159,6 +159,8 @@ function listWatchers() {
159
159
  for (const { key, value } of db.getRange()) {
160
160
  if (!value)
161
161
  continue;
162
+ if (String(key) === exports.DAEMON_KEY)
163
+ continue;
162
164
  if (isAlive(value)) {
163
165
  alive.push(value);
164
166
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "grepmax",
3
- "version": "0.9.0",
3
+ "version": "0.9.1",
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.9.0",
3
+ "version": "0.9.1",
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",