grepmax 0.8.1 → 0.8.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.
- package/dist/commands/add.js +4 -1
- package/dist/commands/droid.js +4 -1
- package/dist/commands/index.js +4 -1
- package/dist/commands/mcp.js +5 -11
- package/dist/commands/remove.js +4 -11
- package/dist/commands/search.js +4 -1
- package/dist/commands/serve.js +5 -7
- package/dist/commands/watch.js +13 -25
- package/dist/config.js +1 -0
- package/dist/lib/index/watcher.js +8 -0
- package/dist/lib/utils/log-rotate.js +55 -0
- package/dist/lib/utils/process.js +45 -0
- package/dist/lib/utils/watcher-launcher.js +17 -15
- package/package.json +1 -1
- package/plugins/grepmax/.claude-plugin/plugin.json +1 -1
package/dist/commands/add.js
CHANGED
|
@@ -155,9 +155,12 @@ Examples:
|
|
|
155
155
|
}
|
|
156
156
|
// Start watcher
|
|
157
157
|
const launched = (0, watcher_launcher_1.launchWatcher)(projectRoot);
|
|
158
|
-
if (launched) {
|
|
158
|
+
if (launched.ok) {
|
|
159
159
|
console.log(`Watcher started (PID: ${launched.pid})`);
|
|
160
160
|
}
|
|
161
|
+
else if (launched.reason === "spawn-failed") {
|
|
162
|
+
console.warn(`[add] ${launched.message}`);
|
|
163
|
+
}
|
|
161
164
|
}
|
|
162
165
|
catch (error) {
|
|
163
166
|
const message = error instanceof Error ? error.message : "Unknown error";
|
package/dist/commands/droid.js
CHANGED
|
@@ -130,7 +130,10 @@ function installPlugin() {
|
|
|
130
130
|
const startScript = `
|
|
131
131
|
const { spawn } = require("child_process");
|
|
132
132
|
const fs = require("fs");
|
|
133
|
-
const
|
|
133
|
+
const path = require("path");
|
|
134
|
+
const logDir = path.join(require("os").homedir(), ".gmax", "logs");
|
|
135
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
136
|
+
const out = fs.openSync(path.join(logDir, "gmax.log"), "a");
|
|
134
137
|
const child = spawn("gmax", ["serve"], { detached: true, stdio: ["ignore", out, out] });
|
|
135
138
|
child.unref();
|
|
136
139
|
`;
|
package/dist/commands/index.js
CHANGED
|
@@ -169,9 +169,12 @@ Examples:
|
|
|
169
169
|
// Restart the watcher if we stopped one
|
|
170
170
|
if (restartWatcher) {
|
|
171
171
|
const launched = (0, watcher_launcher_1.launchWatcher)(restartWatcher.projectRoot);
|
|
172
|
-
if (launched) {
|
|
172
|
+
if (launched.ok) {
|
|
173
173
|
console.log(`Restarted watcher for ${path.basename(restartWatcher.projectRoot)} (PID: ${launched.pid})`);
|
|
174
174
|
}
|
|
175
|
+
else if (launched.reason === "spawn-failed") {
|
|
176
|
+
console.warn(`[index] ${launched.message}`);
|
|
177
|
+
}
|
|
175
178
|
}
|
|
176
179
|
}
|
|
177
180
|
}
|
package/dist/commands/mcp.js
CHANGED
|
@@ -77,6 +77,7 @@ const format_helpers_1 = require("../lib/utils/format-helpers");
|
|
|
77
77
|
const import_extractor_1 = require("../lib/utils/import-extractor");
|
|
78
78
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
79
79
|
const project_root_1 = require("../lib/utils/project-root");
|
|
80
|
+
const watcher_launcher_1 = require("../lib/utils/watcher-launcher");
|
|
80
81
|
const watcher_store_1 = require("../lib/utils/watcher-store");
|
|
81
82
|
// ---------------------------------------------------------------------------
|
|
82
83
|
// Tool definitions
|
|
@@ -352,17 +353,10 @@ exports.mcp = new commander_1.Command("mcp")
|
|
|
352
353
|
}
|
|
353
354
|
// --- Background watcher ---
|
|
354
355
|
function ensureWatcher() {
|
|
355
|
-
|
|
356
|
-
if (!
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
return;
|
|
360
|
-
const child = (0, node_child_process_1.spawn)("gmax", ["watch", "-b", "--path", projectRoot], {
|
|
361
|
-
detached: true,
|
|
362
|
-
stdio: "ignore",
|
|
363
|
-
});
|
|
364
|
-
child.unref();
|
|
365
|
-
console.log(`[MCP] Started background watcher for ${projectRoot}`);
|
|
356
|
+
const result = (0, watcher_launcher_1.launchWatcher)(projectRoot);
|
|
357
|
+
if (result.ok && !result.reused) {
|
|
358
|
+
console.log(`[MCP] Started background watcher for ${projectRoot} (PID: ${result.pid})`);
|
|
359
|
+
}
|
|
366
360
|
}
|
|
367
361
|
// --- Tool handlers ---
|
|
368
362
|
function handleSemanticSearch(args_1) {
|
package/dist/commands/remove.js
CHANGED
|
@@ -49,6 +49,7 @@ const commander_1 = require("commander");
|
|
|
49
49
|
const meta_cache_1 = require("../lib/store/meta-cache");
|
|
50
50
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
51
51
|
const exit_1 = require("../lib/utils/exit");
|
|
52
|
+
const process_1 = require("../lib/utils/process");
|
|
52
53
|
const project_marker_1 = require("../lib/utils/project-marker");
|
|
53
54
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
54
55
|
const project_root_1 = require("../lib/utils/project-root");
|
|
@@ -102,15 +103,7 @@ Examples:
|
|
|
102
103
|
const watcher = (0, watcher_store_1.getWatcherForProject)(projectRoot);
|
|
103
104
|
if (watcher) {
|
|
104
105
|
console.log(`Stopping watcher (PID: ${watcher.pid})...`);
|
|
105
|
-
|
|
106
|
-
process.kill(watcher.pid, "SIGTERM");
|
|
107
|
-
}
|
|
108
|
-
catch (_b) { }
|
|
109
|
-
for (let i = 0; i < 50; i++) {
|
|
110
|
-
if (!(0, watcher_store_1.isProcessRunning)(watcher.pid))
|
|
111
|
-
break;
|
|
112
|
-
yield new Promise((r) => setTimeout(r, 100));
|
|
113
|
-
}
|
|
106
|
+
yield (0, process_1.killProcess)(watcher.pid);
|
|
114
107
|
(0, watcher_store_1.unregisterWatcher)(watcher.pid);
|
|
115
108
|
}
|
|
116
109
|
// Delete vectors from LanceDB
|
|
@@ -139,13 +132,13 @@ Examples:
|
|
|
139
132
|
try {
|
|
140
133
|
metaCache.close();
|
|
141
134
|
}
|
|
142
|
-
catch (
|
|
135
|
+
catch (_b) { }
|
|
143
136
|
}
|
|
144
137
|
if (vectorDb) {
|
|
145
138
|
try {
|
|
146
139
|
yield vectorDb.close();
|
|
147
140
|
}
|
|
148
|
-
catch (
|
|
141
|
+
catch (_c) { }
|
|
149
142
|
}
|
|
150
143
|
yield (0, exit_1.gracefulExit)();
|
|
151
144
|
}
|
package/dist/commands/search.js
CHANGED
|
@@ -529,7 +529,10 @@ Examples:
|
|
|
529
529
|
// Ensure a watcher is running for live reindexing
|
|
530
530
|
if (!process.env.VITEST && !((_d = process.env.NODE_ENV) === null || _d === void 0 ? void 0 : _d.includes("test"))) {
|
|
531
531
|
const { launchWatcher } = yield Promise.resolve().then(() => __importStar(require("../lib/utils/watcher-launcher")));
|
|
532
|
-
launchWatcher(projectRoot);
|
|
532
|
+
const launched = launchWatcher(projectRoot);
|
|
533
|
+
if (!launched.ok && launched.reason === "spawn-failed") {
|
|
534
|
+
console.warn(`[search] ${launched.message}`);
|
|
535
|
+
}
|
|
533
536
|
}
|
|
534
537
|
const searcher = new searcher_1.Searcher(vectorDb);
|
|
535
538
|
// Use --root or fall back to project root
|
package/dist/commands/serve.js
CHANGED
|
@@ -59,6 +59,7 @@ const setup_helpers_1 = require("../lib/setup/setup-helpers");
|
|
|
59
59
|
const meta_cache_1 = require("../lib/store/meta-cache");
|
|
60
60
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
61
61
|
const exit_1 = require("../lib/utils/exit");
|
|
62
|
+
const log_rotate_1 = require("../lib/utils/log-rotate");
|
|
62
63
|
const project_root_1 = require("../lib/utils/project-root");
|
|
63
64
|
const server_registry_1 = require("../lib/utils/server-registry");
|
|
64
65
|
function isMlxServerUp() {
|
|
@@ -84,8 +85,7 @@ function startMlxServer(mlxModel) {
|
|
|
84
85
|
const serverDir = candidates.find((d) => fs.existsSync(path.join(d, "server.py")));
|
|
85
86
|
if (!serverDir)
|
|
86
87
|
return null;
|
|
87
|
-
const
|
|
88
|
-
const out = fs.openSync(logPath, "a");
|
|
88
|
+
const out = (0, log_rotate_1.openRotatedLog)(path.join(config_1.PATHS.logsDir, "mlx-embed-server.log"));
|
|
89
89
|
const env = Object.assign({}, process.env);
|
|
90
90
|
if (mlxModel) {
|
|
91
91
|
env.MLX_EMBED_MODEL = mlxModel;
|
|
@@ -121,14 +121,12 @@ exports.serve = new commander_1.Command("serve")
|
|
|
121
121
|
const args = process.argv
|
|
122
122
|
.slice(2)
|
|
123
123
|
.filter((arg) => arg !== "-b" && arg !== "--background");
|
|
124
|
-
const logDir = path.join(config_1.PATHS.globalRoot, "logs");
|
|
125
|
-
fs.mkdirSync(logDir, { recursive: true });
|
|
126
124
|
const safeName = path
|
|
127
125
|
.basename(projectRoot)
|
|
128
126
|
.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
129
|
-
const logFile = path.join(
|
|
130
|
-
const out =
|
|
131
|
-
const err =
|
|
127
|
+
const logFile = path.join(config_1.PATHS.logsDir, `server-${safeName}.log`);
|
|
128
|
+
const out = (0, log_rotate_1.openRotatedLog)(logFile);
|
|
129
|
+
const err = (0, log_rotate_1.openRotatedLog)(logFile);
|
|
132
130
|
const child = (0, node_child_process_1.spawn)(process.argv[0], [process.argv[1], ...args], {
|
|
133
131
|
detached: true,
|
|
134
132
|
stdio: ["ignore", out, err],
|
package/dist/commands/watch.js
CHANGED
|
@@ -44,7 +44,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
44
44
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
45
|
exports.watch = void 0;
|
|
46
46
|
const node_child_process_1 = require("node:child_process");
|
|
47
|
-
const fs = __importStar(require("node:fs"));
|
|
48
47
|
const path = __importStar(require("node:path"));
|
|
49
48
|
const commander_1 = require("commander");
|
|
50
49
|
const config_1 = require("../config");
|
|
@@ -55,12 +54,13 @@ const watcher_1 = require("../lib/index/watcher");
|
|
|
55
54
|
const meta_cache_1 = require("../lib/store/meta-cache");
|
|
56
55
|
const vector_db_1 = require("../lib/store/vector-db");
|
|
57
56
|
const exit_1 = require("../lib/utils/exit");
|
|
57
|
+
const log_rotate_1 = require("../lib/utils/log-rotate");
|
|
58
|
+
const process_1 = require("../lib/utils/process");
|
|
58
59
|
const project_registry_1 = require("../lib/utils/project-registry");
|
|
59
60
|
const project_root_1 = require("../lib/utils/project-root");
|
|
60
61
|
const watcher_store_1 = require("../lib/utils/watcher-store");
|
|
61
62
|
const IDLE_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
|
|
62
63
|
const IDLE_CHECK_INTERVAL_MS = 60 * 1000; // check every minute
|
|
63
|
-
const MAX_LOG_BYTES = 5 * 1024 * 1024; // 5 MB — rotate log when exceeded
|
|
64
64
|
exports.watch = new commander_1.Command("watch")
|
|
65
65
|
.description("Start background file watcher for live reindexing")
|
|
66
66
|
.option("-b, --background", "Run watcher in background and exit")
|
|
@@ -83,20 +83,9 @@ exports.watch = new commander_1.Command("watch")
|
|
|
83
83
|
const args = process.argv
|
|
84
84
|
.slice(2)
|
|
85
85
|
.filter((arg) => arg !== "-b" && arg !== "--background");
|
|
86
|
-
const logDir = path.join(config_1.PATHS.globalRoot, "logs");
|
|
87
|
-
fs.mkdirSync(logDir, { recursive: true });
|
|
88
86
|
const safeName = projectName.replace(/[^a-zA-Z0-9._-]/g, "_");
|
|
89
|
-
const logFile = path.join(
|
|
90
|
-
|
|
91
|
-
try {
|
|
92
|
-
const logStat = fs.statSync(logFile);
|
|
93
|
-
if (logStat.size > MAX_LOG_BYTES) {
|
|
94
|
-
const prev = `${logFile}.prev`;
|
|
95
|
-
fs.renameSync(logFile, prev);
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
catch (_c) { }
|
|
99
|
-
const out = fs.openSync(logFile, "a");
|
|
87
|
+
const logFile = path.join(config_1.PATHS.logsDir, `watch-${safeName}.log`);
|
|
88
|
+
const out = (0, log_rotate_1.openRotatedLog)(logFile);
|
|
100
89
|
const child = (0, node_child_process_1.spawn)(process.argv[0], [process.argv[1], ...args], {
|
|
101
90
|
detached: true,
|
|
102
91
|
stdio: ["ignore", out, out],
|
|
@@ -228,11 +217,11 @@ exports.watch
|
|
|
228
217
|
if (options.all) {
|
|
229
218
|
const watchers = (0, watcher_store_1.listWatchers)();
|
|
230
219
|
for (const w of watchers) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
220
|
+
const killed = yield (0, process_1.killProcess)(w.pid);
|
|
221
|
+
(0, watcher_store_1.unregisterWatcher)(w.pid);
|
|
222
|
+
if (!killed) {
|
|
223
|
+
console.warn(`Warning: PID ${w.pid} did not exit after SIGKILL`);
|
|
234
224
|
}
|
|
235
|
-
catch (_b) { }
|
|
236
225
|
}
|
|
237
226
|
console.log(`Stopped ${watchers.length} watcher(s).`);
|
|
238
227
|
yield (0, exit_1.gracefulExit)();
|
|
@@ -245,14 +234,13 @@ exports.watch
|
|
|
245
234
|
yield (0, exit_1.gracefulExit)();
|
|
246
235
|
return;
|
|
247
236
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
237
|
+
const killed = yield (0, process_1.killProcess)(watcher.pid);
|
|
238
|
+
(0, watcher_store_1.unregisterWatcher)(watcher.pid);
|
|
239
|
+
if (killed) {
|
|
251
240
|
console.log(`Stopped watcher (PID: ${watcher.pid})`);
|
|
252
241
|
}
|
|
253
|
-
|
|
254
|
-
console.
|
|
255
|
-
(0, watcher_store_1.unregisterWatcher)(watcher.pid);
|
|
242
|
+
else {
|
|
243
|
+
console.warn(`Warning: watcher PID ${watcher.pid} did not exit`);
|
|
256
244
|
}
|
|
257
245
|
yield (0, exit_1.gracefulExit)();
|
|
258
246
|
}));
|
package/dist/config.js
CHANGED
|
@@ -93,6 +93,7 @@ exports.PATHS = {
|
|
|
93
93
|
globalRoot: GLOBAL_ROOT,
|
|
94
94
|
models: path.join(GLOBAL_ROOT, "models"),
|
|
95
95
|
grammars: path.join(GLOBAL_ROOT, "grammars"),
|
|
96
|
+
logsDir: path.join(GLOBAL_ROOT, "logs"),
|
|
96
97
|
// Centralized index storage — one database for all indexed directories
|
|
97
98
|
lancedbDir: path.join(GLOBAL_ROOT, "lancedb"),
|
|
98
99
|
cacheDir: path.join(GLOBAL_ROOT, "cache"),
|
|
@@ -136,9 +136,11 @@ function startWatcher(opts) {
|
|
|
136
136
|
const vectors = [];
|
|
137
137
|
const metaUpdates = new Map();
|
|
138
138
|
const metaDeletes = [];
|
|
139
|
+
const attempted = new Set();
|
|
139
140
|
for (const [absPath, event] of batch) {
|
|
140
141
|
if (batchAc.signal.aborted)
|
|
141
142
|
break;
|
|
143
|
+
attempted.add(absPath);
|
|
142
144
|
if (event === "unlink") {
|
|
143
145
|
deletes.push(absPath);
|
|
144
146
|
metaDeletes.push(absPath);
|
|
@@ -200,6 +202,12 @@ function startWatcher(opts) {
|
|
|
200
202
|
}
|
|
201
203
|
}
|
|
202
204
|
}
|
|
205
|
+
// Requeue files that weren't attempted (aborted or pool unhealthy)
|
|
206
|
+
for (const [absPath, event] of batch) {
|
|
207
|
+
if (!attempted.has(absPath) && !pending.has(absPath)) {
|
|
208
|
+
pending.set(absPath, event);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
203
211
|
// Flush to VectorDB: insert first, then delete old (preserving new)
|
|
204
212
|
const newIds = vectors.map((v) => v.id);
|
|
205
213
|
if (vectors.length > 0) {
|
|
@@ -0,0 +1,55 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.openRotatedLog = openRotatedLog;
|
|
37
|
+
const fs = __importStar(require("node:fs"));
|
|
38
|
+
const path = __importStar(require("node:path"));
|
|
39
|
+
const MAX_LOG_BYTES = 5 * 1024 * 1024; // 5 MB
|
|
40
|
+
/**
|
|
41
|
+
* Open a log file with rotation. Creates parent directories if needed.
|
|
42
|
+
* Rotates {name}.log -> {name}.log.prev when size exceeds maxBytes.
|
|
43
|
+
* Returns an fd suitable for stdio redirection.
|
|
44
|
+
*/
|
|
45
|
+
function openRotatedLog(logPath, maxBytes = MAX_LOG_BYTES) {
|
|
46
|
+
fs.mkdirSync(path.dirname(logPath), { recursive: true });
|
|
47
|
+
try {
|
|
48
|
+
const stat = fs.statSync(logPath);
|
|
49
|
+
if (stat.size > maxBytes) {
|
|
50
|
+
fs.renameSync(logPath, `${logPath}.prev`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (_a) { }
|
|
54
|
+
return fs.openSync(logPath, "a");
|
|
55
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.killProcess = killProcess;
|
|
13
|
+
const watcher_store_1 = require("./watcher-store");
|
|
14
|
+
/**
|
|
15
|
+
* Send SIGTERM, wait up to 3s, then SIGKILL if still alive.
|
|
16
|
+
* Returns true if process is confirmed dead.
|
|
17
|
+
*/
|
|
18
|
+
function killProcess(pid) {
|
|
19
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
+
try {
|
|
21
|
+
process.kill(pid, "SIGTERM");
|
|
22
|
+
}
|
|
23
|
+
catch (_a) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
// Poll up to 3s for graceful exit
|
|
27
|
+
for (let i = 0; i < 30; i++) {
|
|
28
|
+
if (!(0, watcher_store_1.isProcessRunning)(pid))
|
|
29
|
+
return true;
|
|
30
|
+
yield new Promise((r) => setTimeout(r, 100));
|
|
31
|
+
}
|
|
32
|
+
// Force kill
|
|
33
|
+
try {
|
|
34
|
+
process.kill(pid, "SIGKILL");
|
|
35
|
+
}
|
|
36
|
+
catch (_b) { }
|
|
37
|
+
// Give SIGKILL a moment
|
|
38
|
+
for (let i = 0; i < 10; i++) {
|
|
39
|
+
if (!(0, watcher_store_1.isProcessRunning)(pid))
|
|
40
|
+
return true;
|
|
41
|
+
yield new Promise((r) => setTimeout(r, 100));
|
|
42
|
+
}
|
|
43
|
+
return !(0, watcher_store_1.isProcessRunning)(pid);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -8,39 +8,41 @@ exports.launchWatcher = launchWatcher;
|
|
|
8
8
|
const node_child_process_1 = require("node:child_process");
|
|
9
9
|
const project_registry_1 = require("./project-registry");
|
|
10
10
|
const watcher_store_1 = require("./watcher-store");
|
|
11
|
-
/**
|
|
12
|
-
* Launch a background watcher for a project.
|
|
13
|
-
*
|
|
14
|
-
* Returns { pid } on success, null if:
|
|
15
|
-
* - Project is not registered
|
|
16
|
-
* - Watcher is already running
|
|
17
|
-
* - Spawn fails
|
|
18
|
-
*/
|
|
19
11
|
function launchWatcher(projectRoot) {
|
|
20
12
|
var _a;
|
|
21
13
|
// 1. Project must be registered
|
|
22
14
|
const project = (0, project_registry_1.getProject)(projectRoot);
|
|
23
15
|
if (!project) {
|
|
24
|
-
return
|
|
16
|
+
return {
|
|
17
|
+
ok: false,
|
|
18
|
+
reason: "not-registered",
|
|
19
|
+
message: `Project not registered. Run: gmax add ${projectRoot}`,
|
|
20
|
+
};
|
|
25
21
|
}
|
|
26
22
|
// 2. Check if watcher already running
|
|
27
23
|
const existing = (_a = (0, watcher_store_1.getWatcherForProject)(projectRoot)) !== null && _a !== void 0 ? _a : (0, watcher_store_1.getWatcherCoveringPath)(projectRoot);
|
|
28
24
|
if (existing && (0, watcher_store_1.isProcessRunning)(existing.pid)) {
|
|
29
|
-
return { pid: existing.pid };
|
|
25
|
+
return { ok: true, pid: existing.pid, reused: true };
|
|
30
26
|
}
|
|
31
27
|
// 3. Spawn
|
|
32
28
|
try {
|
|
33
29
|
const child = (0, node_child_process_1.spawn)(process.argv[0], [process.argv[1], "watch", "--path", projectRoot, "-b"], { detached: true, stdio: "ignore" });
|
|
34
30
|
child.unref();
|
|
35
31
|
if (child.pid) {
|
|
36
|
-
return { pid: child.pid };
|
|
32
|
+
return { ok: true, pid: child.pid, reused: false };
|
|
37
33
|
}
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
return {
|
|
35
|
+
ok: false,
|
|
36
|
+
reason: "spawn-failed",
|
|
37
|
+
message: `Spawn returned no PID for ${projectRoot}`,
|
|
38
|
+
};
|
|
40
39
|
}
|
|
41
40
|
catch (err) {
|
|
42
41
|
const msg = err instanceof Error ? err.message : String(err);
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
reason: "spawn-failed",
|
|
45
|
+
message: `Failed to start watcher for ${projectRoot}: ${msg}`,
|
|
46
|
+
};
|
|
45
47
|
}
|
|
46
48
|
}
|
package/package.json
CHANGED