magector 2.16.10 → 2.16.11
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 +96 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "magector",
|
|
3
|
-
"version": "2.16.
|
|
3
|
+
"version": "2.16.11",
|
|
4
4
|
"description": "Semantic code search for Magento 2 — index, search, MCP server",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/mcp-server.js",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"ruvector": "^0.1.96"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@magector/cli-darwin-arm64": "2.16.
|
|
37
|
-
"@magector/cli-linux-x64": "2.16.
|
|
38
|
-
"@magector/cli-linux-arm64": "2.16.
|
|
39
|
-
"@magector/cli-win32-x64": "2.16.
|
|
36
|
+
"@magector/cli-darwin-arm64": "2.16.11",
|
|
37
|
+
"@magector/cli-linux-x64": "2.16.11",
|
|
38
|
+
"@magector/cli-linux-arm64": "2.16.11",
|
|
39
|
+
"@magector/cli-win32-x64": "2.16.11"
|
|
40
40
|
},
|
|
41
41
|
"keywords": [
|
|
42
42
|
"magento",
|
package/src/mcp-server.js
CHANGED
|
@@ -492,6 +492,26 @@ let reindexTotalFiles = 0;
|
|
|
492
492
|
let reindexItemsToEmbed = 0;
|
|
493
493
|
let reindexPhase2Start = null;
|
|
494
494
|
|
|
495
|
+
/**
|
|
496
|
+
* Build a short reindex progress message for tool responses.
|
|
497
|
+
* Returns null when not reindexing.
|
|
498
|
+
*/
|
|
499
|
+
function getReindexWarning() {
|
|
500
|
+
if (!reindexInProgress) return null;
|
|
501
|
+
const phases = ['initializing', 'AST analysis', 'embedding generation', 'building HNSW graph'];
|
|
502
|
+
const phase = phases[reindexPhase] || 'in progress';
|
|
503
|
+
const elapsed = reindexStartTime ? Math.round((Date.now() - reindexStartTime) / 1000) : 0;
|
|
504
|
+
let msg = `⚠️ Re-indexing ${phase}`;
|
|
505
|
+
if (elapsed > 0) msg += ` (${elapsed}s elapsed)`;
|
|
506
|
+
if (reindexPhase === 2 && reindexPhase2Start && reindexItemsToEmbed > 0) {
|
|
507
|
+
const p2elapsed = (Date.now() - reindexPhase2Start) / 1000;
|
|
508
|
+
const rate = p2elapsed > 0 ? Math.round(reindexItemsToEmbed * (p2elapsed / reindexItemsToEmbed)) : 0;
|
|
509
|
+
if (rate > 0) msg += ` — ETA ~${Math.round((reindexItemsToEmbed / (p2elapsed > 0 ? reindexItemsToEmbed / p2elapsed : 1)) * (1 - p2elapsed / rate))}s`;
|
|
510
|
+
}
|
|
511
|
+
msg += '. Results may be from previous index or incomplete.';
|
|
512
|
+
return msg;
|
|
513
|
+
}
|
|
514
|
+
|
|
495
515
|
/**
|
|
496
516
|
* Check if the database file is compatible with the current binary.
|
|
497
517
|
* Uses a cached result to avoid running stats (30-60s) on every startup.
|
|
@@ -1978,6 +1998,7 @@ async function traceDependency(className, direction = 'both') {
|
|
|
1978
1998
|
plugins: [],
|
|
1979
1999
|
virtualTypes: [],
|
|
1980
2000
|
argumentOverrides: [],
|
|
2001
|
+
argumentInjections: [],
|
|
1981
2002
|
totalDiFiles: diFiles.length
|
|
1982
2003
|
};
|
|
1983
2004
|
|
|
@@ -2045,6 +2066,54 @@ async function traceDependency(className, direction = 'both') {
|
|
|
2045
2066
|
}
|
|
2046
2067
|
}
|
|
2047
2068
|
}
|
|
2069
|
+
|
|
2070
|
+
// Find argument injections: className used as an argument VALUE in any <type> or <virtualType> block.
|
|
2071
|
+
// Catches cases where an interface is injected via constructor argument, e.g.:
|
|
2072
|
+
// <virtualType name="SomeVT" type="SomeClass">
|
|
2073
|
+
// <argument name="validator" xsi:type="object">My\Interface</argument>
|
|
2074
|
+
// </virtualType>
|
|
2075
|
+
const allBlockRegex = /<(?:type|virtualType)\s+name="([^"]+)"[^>]*(?:type="([^"]+)")?[^>]*>([\s\S]*?)<\/(?:type|virtualType)>/g;
|
|
2076
|
+
let blockMatch;
|
|
2077
|
+
while ((blockMatch = allBlockRegex.exec(content)) !== null) {
|
|
2078
|
+
const blockName = blockMatch[1];
|
|
2079
|
+
const blockType = blockMatch[2] || null;
|
|
2080
|
+
const blockBody = blockMatch[3];
|
|
2081
|
+
// Skip if this block IS the target (already covered above)
|
|
2082
|
+
if (blockName.toLowerCase().includes(classLower)) continue;
|
|
2083
|
+
|
|
2084
|
+
// Search argument values for the className
|
|
2085
|
+
const objArgRegex = /<argument\s+name="([^"]+)"[^>]*xsi:type="object"[^>]*>([^<]*)<\/argument>/g;
|
|
2086
|
+
let oMatch;
|
|
2087
|
+
while ((oMatch = objArgRegex.exec(blockBody)) !== null) {
|
|
2088
|
+
const argValue = oMatch[2].trim();
|
|
2089
|
+
if (argValue.toLowerCase().includes(classLower) || argValue.toLowerCase().includes(classShort)) {
|
|
2090
|
+
result.argumentInjections.push({
|
|
2091
|
+
injectedAs: argValue,
|
|
2092
|
+
intoBlock: blockName,
|
|
2093
|
+
blockType: blockType,
|
|
2094
|
+
argumentName: oMatch[1],
|
|
2095
|
+
file: relativePath
|
|
2096
|
+
});
|
|
2097
|
+
}
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
// Also check <item> values inside array arguments
|
|
2101
|
+
const itemRegex = /<item\s+name="([^"]+)"[^>]*xsi:type="object"[^>]*>([^<]*)<\/item>/g;
|
|
2102
|
+
let iMatch;
|
|
2103
|
+
while ((iMatch = itemRegex.exec(blockBody)) !== null) {
|
|
2104
|
+
const itemValue = iMatch[2].trim();
|
|
2105
|
+
if (itemValue.toLowerCase().includes(classLower) || itemValue.toLowerCase().includes(classShort)) {
|
|
2106
|
+
result.argumentInjections.push({
|
|
2107
|
+
injectedAs: itemValue,
|
|
2108
|
+
intoBlock: blockName,
|
|
2109
|
+
blockType: blockType,
|
|
2110
|
+
argumentName: iMatch[1],
|
|
2111
|
+
isArrayItem: true,
|
|
2112
|
+
file: relativePath
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2116
|
+
}
|
|
2048
2117
|
}
|
|
2049
2118
|
}
|
|
2050
2119
|
|
|
@@ -4968,10 +5037,12 @@ const _callToolHandler = async (request) => {
|
|
|
4968
5037
|
}
|
|
4969
5038
|
// SONA: record search with results for follow-up tracking
|
|
4970
5039
|
sessionTracker.recordToolCall(name, args || {}, arr);
|
|
5040
|
+
const reindexWarn = getReindexWarning();
|
|
5041
|
+
const searchOutput = formatSearchResults(results.slice(0, args.limit || 5));
|
|
4971
5042
|
return {
|
|
4972
5043
|
content: [{
|
|
4973
5044
|
type: 'text',
|
|
4974
|
-
text:
|
|
5045
|
+
text: reindexWarn ? `${reindexWarn}\n\n${searchOutput}` : searchOutput
|
|
4975
5046
|
}]
|
|
4976
5047
|
};
|
|
4977
5048
|
}
|
|
@@ -6024,6 +6095,15 @@ const _callToolHandler = async (request) => {
|
|
|
6024
6095
|
const result = await traceFlow(entryPoint, entryType, depth);
|
|
6025
6096
|
result.summary = buildTraceSummary(result);
|
|
6026
6097
|
|
|
6098
|
+
const reindexWarn = getReindexWarning();
|
|
6099
|
+
if (reindexWarn) result.warning = reindexWarn;
|
|
6100
|
+
|
|
6101
|
+
// Detect empty trace — likely caused by search unavailability
|
|
6102
|
+
const traceKeys = Object.keys(result.trace || {});
|
|
6103
|
+
if (traceKeys.length === 0 && reindexInProgress) {
|
|
6104
|
+
result.warning = '⚠️ Re-indexing in progress — trace returned empty results. Search-dependent tracing will produce accurate results once re-indexing completes.';
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6027
6107
|
return {
|
|
6028
6108
|
content: [{
|
|
6029
6109
|
type: 'text',
|
|
@@ -6070,8 +6150,21 @@ const _callToolHandler = async (request) => {
|
|
|
6070
6150
|
text += '\n';
|
|
6071
6151
|
}
|
|
6072
6152
|
|
|
6073
|
-
if (diResult.
|
|
6074
|
-
|
|
6153
|
+
if (diResult.argumentInjections && diResult.argumentInjections.length > 0) {
|
|
6154
|
+
text += `### Argument Injections (${diResult.argumentInjections.length})\n`;
|
|
6155
|
+
text += `_This class is injected as a constructor argument value in the following blocks:_\n`;
|
|
6156
|
+
for (const a of diResult.argumentInjections) {
|
|
6157
|
+
const blockLabel = a.blockType ? `\`${a.intoBlock}\` (type: \`${a.blockType}\`)` : `\`${a.intoBlock}\``;
|
|
6158
|
+
const itemTag = a.isArrayItem ? ' [array item]' : '';
|
|
6159
|
+
text += `- ${blockLabel} → argument \`${a.argumentName}\`${itemTag} = \`${a.injectedAs}\` (${a.file})\n`;
|
|
6160
|
+
}
|
|
6161
|
+
text += '\n';
|
|
6162
|
+
}
|
|
6163
|
+
|
|
6164
|
+
const totalFound = diResult.preferences.length + diResult.plugins.length +
|
|
6165
|
+
diResult.virtualTypes.length + diResult.argumentOverrides.length +
|
|
6166
|
+
(diResult.argumentInjections?.length || 0);
|
|
6167
|
+
if (totalFound === 0) {
|
|
6075
6168
|
text += '_No DI configuration found for this class. It may use default Magento auto-resolution or be configured under a different name._\n';
|
|
6076
6169
|
}
|
|
6077
6170
|
|