magector 2.1.2 → 2.1.4
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/package.json +5 -5
- package/src/mcp-server.js +65 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magector",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "Semantic code search for Magento 2 — index, search, MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/mcp-server.js",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"ruvector": "^0.1.96"
|
|
40
40
|
},
|
|
41
41
|
"optionalDependencies": {
|
|
42
|
-
"@magector/cli-darwin-arm64": "2.1.
|
|
43
|
-
"@magector/cli-linux-x64": "2.1.
|
|
44
|
-
"@magector/cli-linux-arm64": "2.1.
|
|
45
|
-
"@magector/cli-win32-x64": "2.1.
|
|
42
|
+
"@magector/cli-darwin-arm64": "2.1.4",
|
|
43
|
+
"@magector/cli-linux-x64": "2.1.4",
|
|
44
|
+
"@magector/cli-linux-arm64": "2.1.4",
|
|
45
|
+
"@magector/cli-win32-x64": "2.1.4"
|
|
46
46
|
},
|
|
47
47
|
"keywords": [
|
|
48
48
|
"magento",
|
package/src/mcp-server.js
CHANGED
|
@@ -81,8 +81,8 @@ function logToFile(level, message) {
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
// Initialize log
|
|
85
|
-
try {
|
|
84
|
+
// Initialize log on startup — append to preserve history across MCP restarts
|
|
85
|
+
try { appendFileSync(LOG_PATH, `\n[${new Date().toISOString()}] [INFO] ════ Magector MCP server starting ════\n`); } catch {}
|
|
86
86
|
|
|
87
87
|
// Log resolved configuration so the log file is self-contained for debugging
|
|
88
88
|
logToFile('INFO', `Config: MAGENTO_ROOT=${config.magentoRoot}`);
|
|
@@ -141,6 +141,7 @@ function extractJson(stdout) {
|
|
|
141
141
|
// Track the serve process PID to clean up orphans on restart.
|
|
142
142
|
|
|
143
143
|
const PID_PATH = path.join(config.magentoRoot, '.magector', 'serve.pid');
|
|
144
|
+
const REINDEX_PID_PATH = path.join(config.magentoRoot, '.magector', 'reindex.pid');
|
|
144
145
|
|
|
145
146
|
/**
|
|
146
147
|
* Write the serve process PID to disk so future instances can clean up orphans.
|
|
@@ -153,6 +154,32 @@ function removePidFile() {
|
|
|
153
154
|
try { if (existsSync(PID_PATH)) unlinkSync(PID_PATH); } catch {}
|
|
154
155
|
}
|
|
155
156
|
|
|
157
|
+
function writeReindexPidFile(pid) {
|
|
158
|
+
try { writeFileSync(REINDEX_PID_PATH, String(pid)); } catch {}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function removeReindexPidFile() {
|
|
162
|
+
try { if (existsSync(REINDEX_PID_PATH)) unlinkSync(REINDEX_PID_PATH); } catch {}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Check if another reindex process is already running (from another MCP instance).
|
|
167
|
+
* Returns the PID if alive, null otherwise.
|
|
168
|
+
*/
|
|
169
|
+
function getRunningReindexPid() {
|
|
170
|
+
try {
|
|
171
|
+
if (!existsSync(REINDEX_PID_PATH)) return null;
|
|
172
|
+
const pid = parseInt(readFileSync(REINDEX_PID_PATH, 'utf-8').trim(), 10);
|
|
173
|
+
if (!pid || isNaN(pid)) return null;
|
|
174
|
+
process.kill(pid, 0); // signal 0 = existence check
|
|
175
|
+
return pid;
|
|
176
|
+
} catch {
|
|
177
|
+
// Process doesn't exist or PID file unreadable — clean up
|
|
178
|
+
removeReindexPidFile();
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
156
183
|
/**
|
|
157
184
|
* Kill any stale serve process from a previous MCP server instance.
|
|
158
185
|
* This handles the common case where the MCP server was killed without
|
|
@@ -229,6 +256,27 @@ function checkDbFormat() {
|
|
|
229
256
|
*/
|
|
230
257
|
function startBackgroundReindex() {
|
|
231
258
|
if (reindexInProgress) return;
|
|
259
|
+
|
|
260
|
+
// Check if another MCP instance is already running a reindex
|
|
261
|
+
const existingPid = getRunningReindexPid();
|
|
262
|
+
if (existingPid) {
|
|
263
|
+
logToFile('INFO', `Reindex already running in another process (PID ${existingPid}) — skipping`);
|
|
264
|
+
console.error(`Reindex already running (PID ${existingPid}) — skipping`);
|
|
265
|
+
reindexInProgress = true; // mark locally so tools know
|
|
266
|
+
// Poll the external process and react when it finishes
|
|
267
|
+
const pollInterval = setInterval(() => {
|
|
268
|
+
if (!getRunningReindexPid()) {
|
|
269
|
+
clearInterval(pollInterval);
|
|
270
|
+
reindexInProgress = false;
|
|
271
|
+
logToFile('INFO', 'External reindex finished. Restarting serve process.');
|
|
272
|
+
if (serveProcess) serveProcess.kill();
|
|
273
|
+
searchCache.clear();
|
|
274
|
+
startServeProcess();
|
|
275
|
+
}
|
|
276
|
+
}, 10000);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
|
|
232
280
|
if (!config.magentoRoot || !existsSync(config.magentoRoot)) {
|
|
233
281
|
const msg = 'Cannot auto-reindex: MAGENTO_ROOT not set or not found';
|
|
234
282
|
console.error(msg);
|
|
@@ -269,18 +317,27 @@ function startBackgroundReindex() {
|
|
|
269
317
|
env: rustEnv,
|
|
270
318
|
});
|
|
271
319
|
|
|
272
|
-
|
|
273
|
-
|
|
320
|
+
// Write PID file so other MCP instances know a reindex is running
|
|
321
|
+
writeReindexPidFile(reindexProcess.pid);
|
|
322
|
+
|
|
323
|
+
// Log stdout/stderr line-by-line using readline to avoid buffering issues.
|
|
324
|
+
// Without this, Rust tracing output accumulates in pipe buffers and progress
|
|
325
|
+
// entries arrive in large chunks instead of in real time.
|
|
326
|
+
const indexStdout = createInterface({ input: reindexProcess.stdout });
|
|
327
|
+
const indexStderr = createInterface({ input: reindexProcess.stderr });
|
|
328
|
+
indexStdout.on('line', (line) => {
|
|
329
|
+
const text = line.replace(/\x1b\[[0-9;]*m/g, '').trim();
|
|
274
330
|
if (text) logToFile('INDEX', text);
|
|
275
331
|
});
|
|
276
|
-
|
|
277
|
-
const text =
|
|
332
|
+
indexStderr.on('line', (line) => {
|
|
333
|
+
const text = line.replace(/\x1b\[[0-9;]*m/g, '').trim();
|
|
278
334
|
if (text) logToFile('INDEX', text);
|
|
279
335
|
});
|
|
280
336
|
|
|
281
337
|
reindexProcess.on('exit', (code) => {
|
|
282
338
|
reindexInProgress = false;
|
|
283
339
|
reindexProcess = null;
|
|
340
|
+
removeReindexPidFile();
|
|
284
341
|
if (code === 0) {
|
|
285
342
|
// Atomic swap: old → .bak, new → current
|
|
286
343
|
try {
|
|
@@ -311,6 +368,7 @@ function startBackgroundReindex() {
|
|
|
311
368
|
reindexProcess.on('error', (err) => {
|
|
312
369
|
reindexInProgress = false;
|
|
313
370
|
reindexProcess = null;
|
|
371
|
+
removeReindexPidFile();
|
|
314
372
|
logToFile('ERR', `Background re-index error: ${err.message}`);
|
|
315
373
|
console.error(`Background re-index error: ${err.message}`);
|
|
316
374
|
});
|
|
@@ -3202,6 +3260,7 @@ function cleanup(reason) {
|
|
|
3202
3260
|
reindexProcess = null;
|
|
3203
3261
|
}
|
|
3204
3262
|
removePidFile();
|
|
3263
|
+
removeReindexPidFile();
|
|
3205
3264
|
}
|
|
3206
3265
|
|
|
3207
3266
|
process.on('exit', () => cleanup('process exit'));
|