@launchsecure/launch-kit 0.0.11 → 0.0.12
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/server/cli.js +56 -10
- package/dist/server/graph-mcp-entry.js +56 -10
- package/package.json +1 -1
package/dist/server/cli.js
CHANGED
|
@@ -9159,7 +9159,7 @@ Returns: { pattern, filter, files_searched, total_matches, matches: [{file, line
|
|
|
9159
9159
|
name: "inspect_node",
|
|
9160
9160
|
description: `Get deep AST data for specific graph nodes \u2014 what's INSIDE a component or endpoint. Returns elements (JSX), state hooks, conditions, variables, responses, and request params. Use INSTEAD of Grep/Read when you need to understand component internals without reading source.
|
|
9161
9161
|
|
|
9162
|
-
USE THIS FOR: "what elements does LoginPage have?", "what conditions does the login endpoint check?", "what state does SettingsPage manage?", "what responses can this endpoint return?", "what validation does this API do?", "what props does this component accept?"
|
|
9162
|
+
USE THIS FOR: "what elements does LoginPage have?", "what conditions does the login endpoint check?", "what state does SettingsPage manage?", "what responses can this endpoint return?", "what validation does this API do?", "what props does this component accept?", "which endpoints check for isAdmin?", "find all conditions mentioning rateLimit"
|
|
9163
9163
|
|
|
9164
9164
|
DO NOT USE FOR: structural queries (use read_graph), content search (use grep_nodes).
|
|
9165
9165
|
|
|
@@ -9184,6 +9184,14 @@ Returns deep fields only \u2014 not structural metadata (use read_graph for that
|
|
|
9184
9184
|
type: "array",
|
|
9185
9185
|
items: { type: "string" },
|
|
9186
9186
|
description: "Specific deep fields to return. Options: elements, stateVars, conditions, variables, responses, params. Omit for all."
|
|
9187
|
+
},
|
|
9188
|
+
filter: {
|
|
9189
|
+
type: "string",
|
|
9190
|
+
description: "Regex pattern to search WITHIN deep field values. Only returns nodes where at least one deep field matches. Searches across all string values in the requested fields (condition tests, variable inits, element tags/props, response bodies, etc.). When set, search becomes optional and node limit is raised to 50."
|
|
9191
|
+
},
|
|
9192
|
+
case_insensitive: {
|
|
9193
|
+
type: "boolean",
|
|
9194
|
+
description: "Case-insensitive filter matching. Default true."
|
|
9187
9195
|
}
|
|
9188
9196
|
},
|
|
9189
9197
|
required: ["layer"]
|
|
@@ -9660,8 +9668,10 @@ function handleInspectNode(args) {
|
|
|
9660
9668
|
const nodeId = args.node_id;
|
|
9661
9669
|
const search = args.search;
|
|
9662
9670
|
const fields = args.fields;
|
|
9671
|
+
const filter = args.filter;
|
|
9672
|
+
const caseInsensitive = args.case_insensitive ?? true;
|
|
9663
9673
|
if (!layer) return err("layer is required.");
|
|
9664
|
-
if (!nodeId && !search) return err("Either node_id or
|
|
9674
|
+
if (!nodeId && !search && !filter) return err("Either node_id, search, or filter is required.");
|
|
9665
9675
|
const graph = readGraph(rootDir, layer);
|
|
9666
9676
|
if (!graph) return err(`No graph found for layer "${layer}". Run generate_graph first.`);
|
|
9667
9677
|
let matched;
|
|
@@ -9669,30 +9679,66 @@ function handleInspectNode(args) {
|
|
|
9669
9679
|
const node = graph.nodes.find((n) => n.id === nodeId);
|
|
9670
9680
|
if (!node) return err(`Node "${nodeId}" not found in ${layer} layer.`);
|
|
9671
9681
|
matched = [node];
|
|
9672
|
-
} else {
|
|
9682
|
+
} else if (search) {
|
|
9673
9683
|
const searchLower = search.toLowerCase();
|
|
9674
9684
|
matched = graph.nodes.filter(
|
|
9675
9685
|
(n) => n.id.toLowerCase().includes(searchLower) || n.name.toLowerCase().includes(searchLower) || n.route?.toLowerCase().includes(searchLower)
|
|
9676
9686
|
);
|
|
9677
|
-
}
|
|
9678
|
-
|
|
9679
|
-
if (matched.length > 5) {
|
|
9680
|
-
return err(`${matched.length} nodes match "${search}". Narrow your search (max 5 for inspect_node).`);
|
|
9687
|
+
} else {
|
|
9688
|
+
matched = graph.nodes;
|
|
9681
9689
|
}
|
|
9682
9690
|
const allDeepFields = ["elements", "stateVars", "conditions", "variables", "responses", "params"];
|
|
9683
9691
|
const requestedFields = fields ?? allDeepFields;
|
|
9684
|
-
|
|
9692
|
+
let filterRegex = null;
|
|
9693
|
+
if (filter) {
|
|
9694
|
+
try {
|
|
9695
|
+
filterRegex = new RegExp(filter, caseInsensitive ? "i" : "");
|
|
9696
|
+
} catch {
|
|
9697
|
+
return err(`Invalid regex pattern: "${filter}"`);
|
|
9698
|
+
}
|
|
9699
|
+
}
|
|
9700
|
+
function deepMatch(obj, regex) {
|
|
9701
|
+
if (typeof obj === "string") return regex.test(obj);
|
|
9702
|
+
if (Array.isArray(obj)) return obj.some((item) => deepMatch(item, regex));
|
|
9703
|
+
if (obj && typeof obj === "object") {
|
|
9704
|
+
return Object.values(obj).some((val) => deepMatch(val, regex));
|
|
9705
|
+
}
|
|
9706
|
+
return false;
|
|
9707
|
+
}
|
|
9708
|
+
const results = [];
|
|
9709
|
+
const maxResults = filter ? 50 : 5;
|
|
9710
|
+
for (const node of matched) {
|
|
9685
9711
|
const deep = { id: node.id, name: node.name, type: node.type };
|
|
9712
|
+
let hasData = false;
|
|
9686
9713
|
for (const field of requestedFields) {
|
|
9687
9714
|
if (allDeepFields.includes(field) && node[field] != null) {
|
|
9688
9715
|
deep[field] = node[field];
|
|
9716
|
+
hasData = true;
|
|
9689
9717
|
}
|
|
9690
9718
|
}
|
|
9691
|
-
|
|
9692
|
-
|
|
9719
|
+
if (filterRegex) {
|
|
9720
|
+
let fieldMatches = false;
|
|
9721
|
+
for (const field of requestedFields) {
|
|
9722
|
+
if (node[field] != null && deepMatch(node[field], filterRegex)) {
|
|
9723
|
+
fieldMatches = true;
|
|
9724
|
+
break;
|
|
9725
|
+
}
|
|
9726
|
+
}
|
|
9727
|
+
if (!fieldMatches) continue;
|
|
9728
|
+
}
|
|
9729
|
+
if (hasData || !filter) {
|
|
9730
|
+
results.push(deep);
|
|
9731
|
+
}
|
|
9732
|
+
if (results.length >= maxResults) break;
|
|
9733
|
+
}
|
|
9734
|
+
if (results.length === 0) {
|
|
9735
|
+
const hint = filter ? `No nodes with deep fields matching /${filter}/${caseInsensitive ? "i" : ""} in ${layer} layer.` : `No nodes matching "${search}" in ${layer} layer.`;
|
|
9736
|
+
return err(hint);
|
|
9737
|
+
}
|
|
9693
9738
|
return okJson({
|
|
9694
9739
|
layer,
|
|
9695
9740
|
matched: results.length,
|
|
9741
|
+
...results.length >= maxResults ? { truncated: true, hint: `Showing first ${maxResults} matches. Narrow with search param.` } : {},
|
|
9696
9742
|
nodes: results
|
|
9697
9743
|
});
|
|
9698
9744
|
}
|
|
@@ -3519,8 +3519,10 @@ function handleInspectNode(args) {
|
|
|
3519
3519
|
const nodeId = args.node_id;
|
|
3520
3520
|
const search = args.search;
|
|
3521
3521
|
const fields = args.fields;
|
|
3522
|
+
const filter = args.filter;
|
|
3523
|
+
const caseInsensitive = args.case_insensitive ?? true;
|
|
3522
3524
|
if (!layer) return err("layer is required.");
|
|
3523
|
-
if (!nodeId && !search) return err("Either node_id or
|
|
3525
|
+
if (!nodeId && !search && !filter) return err("Either node_id, search, or filter is required.");
|
|
3524
3526
|
const graph = readGraph(rootDir, layer);
|
|
3525
3527
|
if (!graph) return err(`No graph found for layer "${layer}". Run generate_graph first.`);
|
|
3526
3528
|
let matched;
|
|
@@ -3528,30 +3530,66 @@ function handleInspectNode(args) {
|
|
|
3528
3530
|
const node = graph.nodes.find((n) => n.id === nodeId);
|
|
3529
3531
|
if (!node) return err(`Node "${nodeId}" not found in ${layer} layer.`);
|
|
3530
3532
|
matched = [node];
|
|
3531
|
-
} else {
|
|
3533
|
+
} else if (search) {
|
|
3532
3534
|
const searchLower = search.toLowerCase();
|
|
3533
3535
|
matched = graph.nodes.filter(
|
|
3534
3536
|
(n) => n.id.toLowerCase().includes(searchLower) || n.name.toLowerCase().includes(searchLower) || n.route?.toLowerCase().includes(searchLower)
|
|
3535
3537
|
);
|
|
3536
|
-
}
|
|
3537
|
-
|
|
3538
|
-
if (matched.length > 5) {
|
|
3539
|
-
return err(`${matched.length} nodes match "${search}". Narrow your search (max 5 for inspect_node).`);
|
|
3538
|
+
} else {
|
|
3539
|
+
matched = graph.nodes;
|
|
3540
3540
|
}
|
|
3541
3541
|
const allDeepFields = ["elements", "stateVars", "conditions", "variables", "responses", "params"];
|
|
3542
3542
|
const requestedFields = fields ?? allDeepFields;
|
|
3543
|
-
|
|
3543
|
+
let filterRegex = null;
|
|
3544
|
+
if (filter) {
|
|
3545
|
+
try {
|
|
3546
|
+
filterRegex = new RegExp(filter, caseInsensitive ? "i" : "");
|
|
3547
|
+
} catch {
|
|
3548
|
+
return err(`Invalid regex pattern: "${filter}"`);
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
function deepMatch(obj, regex) {
|
|
3552
|
+
if (typeof obj === "string") return regex.test(obj);
|
|
3553
|
+
if (Array.isArray(obj)) return obj.some((item) => deepMatch(item, regex));
|
|
3554
|
+
if (obj && typeof obj === "object") {
|
|
3555
|
+
return Object.values(obj).some((val) => deepMatch(val, regex));
|
|
3556
|
+
}
|
|
3557
|
+
return false;
|
|
3558
|
+
}
|
|
3559
|
+
const results = [];
|
|
3560
|
+
const maxResults = filter ? 50 : 5;
|
|
3561
|
+
for (const node of matched) {
|
|
3544
3562
|
const deep = { id: node.id, name: node.name, type: node.type };
|
|
3563
|
+
let hasData = false;
|
|
3545
3564
|
for (const field of requestedFields) {
|
|
3546
3565
|
if (allDeepFields.includes(field) && node[field] != null) {
|
|
3547
3566
|
deep[field] = node[field];
|
|
3567
|
+
hasData = true;
|
|
3548
3568
|
}
|
|
3549
3569
|
}
|
|
3550
|
-
|
|
3551
|
-
|
|
3570
|
+
if (filterRegex) {
|
|
3571
|
+
let fieldMatches = false;
|
|
3572
|
+
for (const field of requestedFields) {
|
|
3573
|
+
if (node[field] != null && deepMatch(node[field], filterRegex)) {
|
|
3574
|
+
fieldMatches = true;
|
|
3575
|
+
break;
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
if (!fieldMatches) continue;
|
|
3579
|
+
}
|
|
3580
|
+
if (hasData || !filter) {
|
|
3581
|
+
results.push(deep);
|
|
3582
|
+
}
|
|
3583
|
+
if (results.length >= maxResults) break;
|
|
3584
|
+
}
|
|
3585
|
+
if (results.length === 0) {
|
|
3586
|
+
const hint = filter ? `No nodes with deep fields matching /${filter}/${caseInsensitive ? "i" : ""} in ${layer} layer.` : `No nodes matching "${search}" in ${layer} layer.`;
|
|
3587
|
+
return err(hint);
|
|
3588
|
+
}
|
|
3552
3589
|
return okJson({
|
|
3553
3590
|
layer,
|
|
3554
3591
|
matched: results.length,
|
|
3592
|
+
...results.length >= maxResults ? { truncated: true, hint: `Showing first ${maxResults} matches. Narrow with search param.` } : {},
|
|
3555
3593
|
nodes: results
|
|
3556
3594
|
});
|
|
3557
3595
|
}
|
|
@@ -4074,7 +4112,7 @@ Returns: { pattern, filter, files_searched, total_matches, matches: [{file, line
|
|
|
4074
4112
|
name: "inspect_node",
|
|
4075
4113
|
description: `Get deep AST data for specific graph nodes \u2014 what's INSIDE a component or endpoint. Returns elements (JSX), state hooks, conditions, variables, responses, and request params. Use INSTEAD of Grep/Read when you need to understand component internals without reading source.
|
|
4076
4114
|
|
|
4077
|
-
USE THIS FOR: "what elements does LoginPage have?", "what conditions does the login endpoint check?", "what state does SettingsPage manage?", "what responses can this endpoint return?", "what validation does this API do?", "what props does this component accept?"
|
|
4115
|
+
USE THIS FOR: "what elements does LoginPage have?", "what conditions does the login endpoint check?", "what state does SettingsPage manage?", "what responses can this endpoint return?", "what validation does this API do?", "what props does this component accept?", "which endpoints check for isAdmin?", "find all conditions mentioning rateLimit"
|
|
4078
4116
|
|
|
4079
4117
|
DO NOT USE FOR: structural queries (use read_graph), content search (use grep_nodes).
|
|
4080
4118
|
|
|
@@ -4099,6 +4137,14 @@ Returns deep fields only \u2014 not structural metadata (use read_graph for that
|
|
|
4099
4137
|
type: "array",
|
|
4100
4138
|
items: { type: "string" },
|
|
4101
4139
|
description: "Specific deep fields to return. Options: elements, stateVars, conditions, variables, responses, params. Omit for all."
|
|
4140
|
+
},
|
|
4141
|
+
filter: {
|
|
4142
|
+
type: "string",
|
|
4143
|
+
description: "Regex pattern to search WITHIN deep field values. Only returns nodes where at least one deep field matches. Searches across all string values in the requested fields (condition tests, variable inits, element tags/props, response bodies, etc.). When set, search becomes optional and node limit is raised to 50."
|
|
4144
|
+
},
|
|
4145
|
+
case_insensitive: {
|
|
4146
|
+
type: "boolean",
|
|
4147
|
+
description: "Case-insensitive filter matching. Default true."
|
|
4102
4148
|
}
|
|
4103
4149
|
},
|
|
4104
4150
|
required: ["layer"]
|
package/package.json
CHANGED