@hung319/opencode-hive 1.5.6 → 1.5.8
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/README.md +116 -36
- package/dist/index.js +425 -537
- package/dist/tools/ast-grep-native.d.ts +2 -1
- package/dist/tools/hive-doctor.d.ts +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -17809,49 +17809,73 @@ import { execSync as execSync2 } from "child_process";
|
|
|
17809
17809
|
import * as fs5 from "fs";
|
|
17810
17810
|
import * as path6 from "path";
|
|
17811
17811
|
async function checkPackage(packageName) {
|
|
17812
|
+
const result = {
|
|
17813
|
+
name: packageName,
|
|
17814
|
+
package: packageName,
|
|
17815
|
+
installed: false,
|
|
17816
|
+
optional: true
|
|
17817
|
+
};
|
|
17812
17818
|
try {
|
|
17813
17819
|
const packageJsonPath = __require.resolve(`${packageName}/package.json`, {
|
|
17814
|
-
paths: [
|
|
17815
|
-
process.cwd(),
|
|
17816
|
-
path6.join(process.cwd(), "node_modules"),
|
|
17817
|
-
path6.join(process.cwd(), "packages/opencode-hive/node_modules")
|
|
17818
|
-
]
|
|
17820
|
+
paths: [process.cwd(), path6.join(process.cwd(), "node_modules")]
|
|
17819
17821
|
});
|
|
17820
17822
|
if (fs5.existsSync(packageJsonPath)) {
|
|
17821
17823
|
const pkg = JSON.parse(fs5.readFileSync(packageJsonPath, "utf-8"));
|
|
17822
|
-
|
|
17824
|
+
result.installed = true;
|
|
17825
|
+
result.version = pkg.version;
|
|
17823
17826
|
}
|
|
17824
17827
|
} catch {}
|
|
17825
|
-
return
|
|
17828
|
+
return result;
|
|
17826
17829
|
}
|
|
17827
|
-
function checkCliTool(
|
|
17830
|
+
function checkCliTool(name, command, description) {
|
|
17831
|
+
const result = {
|
|
17832
|
+
name,
|
|
17833
|
+
command,
|
|
17834
|
+
installed: false,
|
|
17835
|
+
description
|
|
17836
|
+
};
|
|
17828
17837
|
try {
|
|
17829
|
-
|
|
17830
|
-
|
|
17831
|
-
|
|
17832
|
-
return {
|
|
17833
|
-
...tool3,
|
|
17834
|
-
installed: true,
|
|
17835
|
-
version: versionMatch ? versionMatch[1] : output.slice(0, 50)
|
|
17836
|
-
};
|
|
17838
|
+
execSync2(command.split(" ")[0], { stdio: "pipe", timeout: 3000 });
|
|
17839
|
+
result.installed = true;
|
|
17840
|
+
result.version = "installed";
|
|
17837
17841
|
} catch {
|
|
17838
|
-
const npxCmd = tool3.command.split(" ")[0];
|
|
17839
17842
|
try {
|
|
17840
|
-
execSync2(`npx -y ${
|
|
17841
|
-
|
|
17842
|
-
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
|
|
17847
|
-
|
|
17848
|
-
|
|
17849
|
-
|
|
17850
|
-
|
|
17843
|
+
execSync2(`npx -y ${command.split(" ")[0]} --version`, { stdio: "pipe", timeout: 5000 });
|
|
17844
|
+
result.installed = true;
|
|
17845
|
+
result.version = "via npx";
|
|
17846
|
+
} catch {}
|
|
17847
|
+
}
|
|
17848
|
+
return result;
|
|
17849
|
+
}
|
|
17850
|
+
function checkAstGrepNative() {
|
|
17851
|
+
const result = {
|
|
17852
|
+
available: false,
|
|
17853
|
+
reason: ""
|
|
17854
|
+
};
|
|
17855
|
+
try {
|
|
17856
|
+
const napiPath = __require.resolve("@ast-grep/napi");
|
|
17857
|
+
const napiDir = path6.dirname(napiPath);
|
|
17858
|
+
const binaryPaths = [
|
|
17859
|
+
path6.join(napiDir, "index.node"),
|
|
17860
|
+
path6.join(napiDir, "build", "Release", "ast_grep.node"),
|
|
17861
|
+
path6.join(napiDir, "dist", "index.node")
|
|
17862
|
+
];
|
|
17863
|
+
const binaryExists = binaryPaths.some((p) => fs5.existsSync(p));
|
|
17864
|
+
if (binaryExists) {
|
|
17865
|
+
result.available = true;
|
|
17866
|
+
try {
|
|
17867
|
+
const pkg = JSON.parse(fs5.readFileSync(path6.join(napiDir, "package.json"), "utf-8"));
|
|
17868
|
+
result.version = pkg.version;
|
|
17869
|
+
} catch {}
|
|
17870
|
+
} else {
|
|
17871
|
+
result.reason = "Native binaries not compiled (tree-sitter failed to build)";
|
|
17851
17872
|
}
|
|
17873
|
+
} catch (error45) {
|
|
17874
|
+
result.reason = "@ast-grep/napi not installed";
|
|
17852
17875
|
}
|
|
17876
|
+
return result;
|
|
17853
17877
|
}
|
|
17854
|
-
function
|
|
17878
|
+
function checkConfig() {
|
|
17855
17879
|
const checks3 = [];
|
|
17856
17880
|
const configPaths = [
|
|
17857
17881
|
path6.join(process.env.HOME || "", ".config/opencode/agent_hive.json"),
|
|
@@ -17867,227 +17891,181 @@ function checkOptimizations() {
|
|
|
17867
17891
|
} catch {}
|
|
17868
17892
|
}
|
|
17869
17893
|
}
|
|
17870
|
-
const
|
|
17894
|
+
const snipEnabled = config2?.snip?.enabled === true;
|
|
17871
17895
|
checks3.push({
|
|
17872
17896
|
name: "snip",
|
|
17873
|
-
enabled:
|
|
17874
|
-
|
|
17897
|
+
enabled: snipEnabled,
|
|
17898
|
+
value: config2?.snip,
|
|
17899
|
+
recommendation: snipEnabled ? "snip enabled for 60-90% token reduction" : 'Enable snip: Add { "snip": { "enabled": true } } to config'
|
|
17875
17900
|
});
|
|
17876
|
-
const
|
|
17901
|
+
const vectorEnabled = config2?.vectorMemory?.enabled === true;
|
|
17877
17902
|
checks3.push({
|
|
17878
17903
|
name: "vectorMemory",
|
|
17879
|
-
enabled:
|
|
17880
|
-
|
|
17904
|
+
enabled: vectorEnabled,
|
|
17905
|
+
value: config2?.vectorMemory,
|
|
17906
|
+
recommendation: vectorEnabled ? "Vector memory enabled for semantic search" : 'Enable vector memory: Add { "vectorMemory": { "enabled": true } } to config'
|
|
17881
17907
|
});
|
|
17882
|
-
const
|
|
17908
|
+
const boosterEnabled = config2?.agentBooster?.enabled !== false;
|
|
17883
17909
|
checks3.push({
|
|
17884
17910
|
name: "agentBooster",
|
|
17885
|
-
enabled:
|
|
17886
|
-
|
|
17911
|
+
enabled: boosterEnabled,
|
|
17912
|
+
value: config2?.agentBooster,
|
|
17913
|
+
recommendation: boosterEnabled ? "Agent booster enabled for 52x faster editing" : 'Agent booster disabled: Set { "agentBooster": { "enabled": true } } to enable'
|
|
17887
17914
|
});
|
|
17888
|
-
const
|
|
17915
|
+
const sandboxMode = config2?.sandbox?.mode || "none";
|
|
17916
|
+
const sandboxEnabled = sandboxMode !== "none";
|
|
17889
17917
|
checks3.push({
|
|
17890
17918
|
name: "sandbox",
|
|
17891
|
-
enabled:
|
|
17892
|
-
|
|
17919
|
+
enabled: sandboxEnabled,
|
|
17920
|
+
value: sandboxMode,
|
|
17921
|
+
recommendation: sandboxEnabled ? `Sandbox enabled (${sandboxMode} mode)` : 'Enable sandbox: Add { "sandbox": { "mode": "docker" } } to config for isolated testing'
|
|
17893
17922
|
});
|
|
17894
17923
|
const disabledMcps = config2?.disableMcps || [];
|
|
17895
|
-
const hasPareSearch = !disabledMcps.includes("pare_search");
|
|
17896
17924
|
checks3.push({
|
|
17897
|
-
name: "
|
|
17898
|
-
enabled:
|
|
17899
|
-
recommendation: !
|
|
17925
|
+
name: "ast_grep MCP",
|
|
17926
|
+
enabled: !disabledMcps.includes("ast_grep"),
|
|
17927
|
+
recommendation: !disabledMcps.includes("ast_grep") ? "ast_grep MCP enabled" : 'Enable ast_grep: Remove "ast_grep" from disableMcps array'
|
|
17900
17928
|
});
|
|
17901
|
-
const hasVeil = !disabledMcps.includes("veil");
|
|
17902
17929
|
checks3.push({
|
|
17903
|
-
name: "veil",
|
|
17904
|
-
enabled:
|
|
17905
|
-
recommendation: !
|
|
17930
|
+
name: "veil MCP",
|
|
17931
|
+
enabled: !disabledMcps.includes("veil"),
|
|
17932
|
+
recommendation: !disabledMcps.includes("veil") ? "veil MCP enabled" : 'Enable veil: Remove "veil" from disableMcps array'
|
|
17933
|
+
});
|
|
17934
|
+
checks3.push({
|
|
17935
|
+
name: "pare_search MCP",
|
|
17936
|
+
enabled: !disabledMcps.includes("pare_search"),
|
|
17937
|
+
recommendation: !disabledMcps.includes("pare_search") ? "pare_search MCP enabled" : 'Enable pare_search: Remove "pare_search" from disableMcps array'
|
|
17906
17938
|
});
|
|
17907
17939
|
return checks3;
|
|
17908
17940
|
}
|
|
17909
|
-
function generateRecommendations(dependencies, cliTools, optimizations) {
|
|
17910
|
-
const recommendations = [];
|
|
17911
|
-
const missingRequired = dependencies.filter((d) => d.required && !d.installed);
|
|
17912
|
-
if (missingRequired.length > 0) {
|
|
17913
|
-
recommendations.push(`Missing required packages: ${missingRequired.map((d) => d.name).join(", ")}`);
|
|
17914
|
-
}
|
|
17915
|
-
const missingCliTools = cliTools.filter((t) => !t.installed);
|
|
17916
|
-
if (missingCliTools.length > 0) {
|
|
17917
|
-
recommendations.push(`⚠️ Missing CLI tools: ${missingCliTools.map((t) => t.name).join(", ")}`, `Install with: ${missingCliTools.map((t) => `npx -y ${t.command}`).join(" | ")}`);
|
|
17918
|
-
}
|
|
17919
|
-
const disabledOptimizations = optimizations.filter((o) => !o.enabled && o.recommendation);
|
|
17920
|
-
for (const opt of disabledOptimizations) {
|
|
17921
|
-
if (opt.recommendation) {
|
|
17922
|
-
recommendations.push(opt.recommendation);
|
|
17923
|
-
}
|
|
17924
|
-
}
|
|
17925
|
-
if (recommendations.length === 0) {
|
|
17926
|
-
recommendations.push("✅ System is healthy! All checks passed.");
|
|
17927
|
-
}
|
|
17928
|
-
return recommendations;
|
|
17929
|
-
}
|
|
17930
|
-
function generateQuickFixes(dependencies, cliTools, optimizations) {
|
|
17931
|
-
const fixes = [];
|
|
17932
|
-
const missingPackages = dependencies.filter((d) => !d.installed && !d.required);
|
|
17933
|
-
for (const pkg of missingPackages) {
|
|
17934
|
-
fixes.push({
|
|
17935
|
-
command: `npm install ${pkg.package}`,
|
|
17936
|
-
description: `Install ${pkg.name}`
|
|
17937
|
-
});
|
|
17938
|
-
}
|
|
17939
|
-
const missingTools = cliTools.filter((t) => !t.installed);
|
|
17940
|
-
for (const tool3 of missingTools) {
|
|
17941
|
-
fixes.push({
|
|
17942
|
-
command: `npx -y ${tool3.command}`,
|
|
17943
|
-
description: `Install ${tool3.name} via npx`
|
|
17944
|
-
});
|
|
17945
|
-
}
|
|
17946
|
-
if (optimizations.find((o) => o.name === "snip" && !o.enabled)) {
|
|
17947
|
-
fixes.push({
|
|
17948
|
-
command: 'Add to ~/.config/opencode/agent_hive.json: { "snip": { "enabled": true } }',
|
|
17949
|
-
description: "Enable snip for token reduction"
|
|
17950
|
-
});
|
|
17951
|
-
}
|
|
17952
|
-
if (optimizations.find((o) => o.name === "vectorMemory" && !o.enabled)) {
|
|
17953
|
-
fixes.push({
|
|
17954
|
-
command: 'Add to ~/.config/opencode/agent_hive.json: { "vectorMemory": { "enabled": true } }',
|
|
17955
|
-
description: "Enable vector memory for semantic search"
|
|
17956
|
-
});
|
|
17957
|
-
}
|
|
17958
|
-
return fixes;
|
|
17959
|
-
}
|
|
17960
|
-
function calculateStatus(dependencies, cliTools, optimizations) {
|
|
17961
|
-
const missingRequired = dependencies.filter((d) => d.required && !d.installed);
|
|
17962
|
-
if (missingRequired.length > 0) {
|
|
17963
|
-
return "issues";
|
|
17964
|
-
}
|
|
17965
|
-
const missingTools = cliTools.filter((t) => !t.installed);
|
|
17966
|
-
const disabledCount = optimizations.filter((o) => !o.enabled).length;
|
|
17967
|
-
if (missingTools.length > 0 || disabledCount > 2) {
|
|
17968
|
-
return "warning";
|
|
17969
|
-
}
|
|
17970
|
-
return "healthy";
|
|
17971
|
-
}
|
|
17972
17941
|
var hiveDoctorTool = tool({
|
|
17973
|
-
description: `Hive Doctor - System health check
|
|
17974
|
-
|
|
17975
|
-
**
|
|
17976
|
-
1. Dependencies -
|
|
17977
|
-
2. CLI Tools - dora, auto-cr,
|
|
17978
|
-
3.
|
|
17979
|
-
4.
|
|
17980
|
-
|
|
17981
|
-
**
|
|
17982
|
-
-
|
|
17983
|
-
-
|
|
17984
|
-
-
|
|
17985
|
-
-
|
|
17986
|
-
|
|
17987
|
-
**Example output:**
|
|
17988
|
-
- healthy: All checks pass
|
|
17989
|
-
- warning: Some optimizations disabled or CLI tools missing
|
|
17990
|
-
- issues: Missing required packages`,
|
|
17942
|
+
description: `Hive Doctor - System health check with actionable fixes.
|
|
17943
|
+
|
|
17944
|
+
**Checks performed:**
|
|
17945
|
+
1. Dependencies - @ast-grep/napi, agent-booster, vector-memory, etc.
|
|
17946
|
+
2. CLI Tools - dora, auto-cr, scip-typescript, veil
|
|
17947
|
+
3. Native Binaries - tree-sitter binaries for ast-grep
|
|
17948
|
+
4. Config - optimizations and MCPs enabled
|
|
17949
|
+
|
|
17950
|
+
**Output includes:**
|
|
17951
|
+
- Status summary (healthy/warning/action-required)
|
|
17952
|
+
- Missing items with install commands
|
|
17953
|
+
- Action items prioritized by impact
|
|
17954
|
+
- Quick install commands for all missing items`,
|
|
17991
17955
|
args: {},
|
|
17992
17956
|
async execute() {
|
|
17993
|
-
const dependencyChecks = [
|
|
17994
|
-
|
|
17995
|
-
|
|
17996
|
-
|
|
17997
|
-
|
|
17998
|
-
|
|
17999
|
-
|
|
18000
|
-
|
|
18001
|
-
|
|
18002
|
-
|
|
18003
|
-
dep.version = result2.version;
|
|
18004
|
-
}
|
|
17957
|
+
const dependencyChecks = await Promise.all([
|
|
17958
|
+
checkPackage("@ast-grep/napi"),
|
|
17959
|
+
checkPackage("@sparkleideas/agent-booster"),
|
|
17960
|
+
checkPackage("@sparkleideas/memory"),
|
|
17961
|
+
checkPackage("@paretools/search"),
|
|
17962
|
+
checkPackage("@upstash/context7-mcp"),
|
|
17963
|
+
checkPackage("exa-mcp-server"),
|
|
17964
|
+
checkPackage("grep-mcp"),
|
|
17965
|
+
checkPackage("@notprolands/ast-grep-mcp")
|
|
17966
|
+
]);
|
|
18005
17967
|
const cliToolChecks = [
|
|
18006
|
-
|
|
18007
|
-
|
|
18008
|
-
|
|
18009
|
-
|
|
18010
|
-
installCommand: "npx -y @butttons/dora"
|
|
18011
|
-
},
|
|
18012
|
-
{
|
|
18013
|
-
name: "auto-cr",
|
|
18014
|
-
command: "auto-cr-cmd",
|
|
18015
|
-
description: "SWC-based automated code review",
|
|
18016
|
-
installCommand: "npx -y auto-cr-cmd"
|
|
18017
|
-
},
|
|
18018
|
-
{
|
|
18019
|
-
name: "veil",
|
|
18020
|
-
command: "@ushiradineth/veil",
|
|
18021
|
-
description: "Code discovery and retrieval",
|
|
18022
|
-
installCommand: "npx -y @ushiradineth/veil"
|
|
18023
|
-
},
|
|
18024
|
-
{
|
|
18025
|
-
name: "scip-typescript",
|
|
18026
|
-
command: "@sourcegraph/scip-typescript",
|
|
18027
|
-
description: "TypeScript SCIP indexer (for dora)",
|
|
18028
|
-
installCommand: "npx -y @sourcegraph/scip-typescript"
|
|
18029
|
-
}
|
|
17968
|
+
checkCliTool("dora", "@butttons/dora", "SCIP-based code navigation"),
|
|
17969
|
+
checkCliTool("auto-cr", "auto-cr-cmd", "SWC-based automated code review"),
|
|
17970
|
+
checkCliTool("scip-typescript", "@sourcegraph/scip-typescript", "TypeScript SCIP indexer"),
|
|
17971
|
+
checkCliTool("veil", "@ushiradineth/veil", "Code discovery and retrieval")
|
|
18030
17972
|
];
|
|
18031
|
-
|
|
18032
|
-
|
|
17973
|
+
const nativeCheck = checkAstGrepNative();
|
|
17974
|
+
const nativeStatus = nativeCheck.available ? "native" : "cli-mode";
|
|
17975
|
+
const configChecks = checkConfig();
|
|
17976
|
+
const missingDeps = dependencyChecks.filter((d) => !d.installed);
|
|
17977
|
+
const missingTools = cliToolChecks.filter((t) => !t.installed);
|
|
17978
|
+
const disabledConfigs = configChecks.filter((c) => !c.enabled);
|
|
17979
|
+
let status = "healthy";
|
|
17980
|
+
if (missingTools.length >= 2 || missingDeps.length >= 3) {
|
|
17981
|
+
status = "action-required";
|
|
17982
|
+
} else if (missingTools.length >= 1 || missingDeps.length >= 1 || disabledConfigs.length >= 2) {
|
|
17983
|
+
status = "warning";
|
|
17984
|
+
}
|
|
17985
|
+
const actionItems = [];
|
|
17986
|
+
for (const tool3 of missingTools) {
|
|
17987
|
+
actionItems.push({
|
|
17988
|
+
priority: "high",
|
|
17989
|
+
action: `Install ${tool3.name}`,
|
|
17990
|
+
command: `npx -y ${tool3.command}`,
|
|
17991
|
+
reason: `${tool3.description} - improves code navigation/review`
|
|
17992
|
+
});
|
|
17993
|
+
}
|
|
17994
|
+
if (!dependencyChecks.find((d) => d.package === "@notprolands/ast-grep-mcp")?.installed) {
|
|
17995
|
+
actionItems.push({
|
|
17996
|
+
priority: "medium",
|
|
17997
|
+
action: "Install ast-grep MCP for YAML rule testing",
|
|
17998
|
+
command: `npm install @notprolands/ast-grep-mcp`,
|
|
17999
|
+
reason: "Full ast-grep functionality with YAML rules"
|
|
18000
|
+
});
|
|
18001
|
+
}
|
|
18002
|
+
for (const config2 of disabledConfigs) {
|
|
18003
|
+
actionItems.push({
|
|
18004
|
+
priority: "low",
|
|
18005
|
+
action: config2.recommendation,
|
|
18006
|
+
reason: `Enable ${config2.name} for better performance/features`
|
|
18007
|
+
});
|
|
18033
18008
|
}
|
|
18034
|
-
const
|
|
18035
|
-
|
|
18036
|
-
|
|
18037
|
-
|
|
18009
|
+
const quickInstall = {
|
|
18010
|
+
deps: missingDeps.map((d) => d.package),
|
|
18011
|
+
cliTools: missingTools.map((t) => t.command)
|
|
18012
|
+
};
|
|
18013
|
+
const summary = {
|
|
18014
|
+
dependencies: missingDeps.length === 0 ? "✅ All dependencies installed" : `⚠️ ${missingDeps.length} missing: ${missingDeps.map((d) => d.name).join(", ")}`,
|
|
18015
|
+
cliTools: missingTools.length === 0 ? "✅ All CLI tools available" : `⚠️ ${missingTools.length} missing: ${missingTools.map((t) => t.name).join(", ")}`,
|
|
18016
|
+
nativeBinaries: nativeCheck.available ? `✅ Native mode (v${nativeCheck.version || "?"})` : `⚡ CLI mode (${nativeCheck.reason || "native unavailable"})`,
|
|
18017
|
+
config: disabledConfigs.length === 0 ? "✅ All optimizations enabled" : `\uD83D\uDCA1 ${disabledConfigs.length} disabled: ${disabledConfigs.map((c) => c.name).join(", ")}`
|
|
18018
|
+
};
|
|
18038
18019
|
const result = {
|
|
18039
18020
|
status,
|
|
18040
|
-
|
|
18041
|
-
|
|
18021
|
+
summary,
|
|
18022
|
+
details: {
|
|
18042
18023
|
dependencies: {
|
|
18043
18024
|
total: dependencyChecks.length,
|
|
18044
18025
|
installed: dependencyChecks.filter((d) => d.installed).length,
|
|
18045
|
-
|
|
18026
|
+
missing: missingDeps
|
|
18046
18027
|
},
|
|
18047
18028
|
cliTools: {
|
|
18048
18029
|
total: cliToolChecks.length,
|
|
18049
18030
|
available: cliToolChecks.filter((t) => t.installed).length,
|
|
18050
|
-
|
|
18051
|
-
missing: cliToolChecks.filter((t) => !t.installed).map((t) => t.name)
|
|
18031
|
+
missing: missingTools
|
|
18052
18032
|
},
|
|
18053
|
-
|
|
18054
|
-
|
|
18055
|
-
|
|
18056
|
-
|
|
18057
|
-
|
|
18033
|
+
nativeBinaries: {
|
|
18034
|
+
status: nativeStatus,
|
|
18035
|
+
reason: nativeCheck.reason,
|
|
18036
|
+
astGrep: {
|
|
18037
|
+
available: nativeCheck.available,
|
|
18038
|
+
version: nativeCheck.version
|
|
18039
|
+
}
|
|
18040
|
+
},
|
|
18041
|
+
config: configChecks
|
|
18058
18042
|
},
|
|
18059
|
-
|
|
18060
|
-
|
|
18043
|
+
actionItems,
|
|
18044
|
+
quickInstall
|
|
18061
18045
|
};
|
|
18062
18046
|
return JSON.stringify(result, null, 2);
|
|
18063
18047
|
}
|
|
18064
18048
|
});
|
|
18065
18049
|
var hiveDoctorQuickTool = tool({
|
|
18066
|
-
description: `Quick health
|
|
18050
|
+
description: `Quick health status - shows summary without details.
|
|
18067
18051
|
|
|
18068
18052
|
**Returns:**
|
|
18069
|
-
- healthy: All
|
|
18070
|
-
- warning: Some
|
|
18071
|
-
-
|
|
18053
|
+
- healthy: All dependencies and CLI tools available
|
|
18054
|
+
- warning: Some items missing (not blocking)
|
|
18055
|
+
- action-required: Multiple items missing (fix recommended)`,
|
|
18072
18056
|
args: {},
|
|
18073
18057
|
async execute() {
|
|
18074
|
-
const
|
|
18075
|
-
"@
|
|
18076
|
-
"@
|
|
18077
|
-
|
|
18078
|
-
|
|
18079
|
-
|
|
18080
|
-
|
|
18081
|
-
const result = await checkPackage(pkg);
|
|
18082
|
-
results[pkg] = result.installed;
|
|
18083
|
-
if (!result.installed) {
|
|
18084
|
-
healthy = false;
|
|
18085
|
-
}
|
|
18086
|
-
}
|
|
18058
|
+
const checks3 = await Promise.all([
|
|
18059
|
+
checkPackage("@ast-grep/napi"),
|
|
18060
|
+
checkPackage("@sparkleideas/agent-booster"),
|
|
18061
|
+
checkCliTool("dora", "@butttons/dora", ""),
|
|
18062
|
+
checkCliTool("auto-cr", "auto-cr-cmd", "")
|
|
18063
|
+
]);
|
|
18064
|
+
const missing = checks3.filter((c) => !c.installed).length;
|
|
18087
18065
|
return JSON.stringify({
|
|
18088
|
-
status:
|
|
18089
|
-
|
|
18090
|
-
runFullCheck: "
|
|
18066
|
+
status: missing === 0 ? "healthy" : missing >= 2 ? "action-required" : "warning",
|
|
18067
|
+
missingCount: missing,
|
|
18068
|
+
runFullCheck: "Run hive_doctor for detailed analysis and install commands"
|
|
18091
18069
|
}, null, 2);
|
|
18092
18070
|
}
|
|
18093
18071
|
});
|
|
@@ -18580,10 +18558,39 @@ var autoCrRulesTool = tool({
|
|
|
18580
18558
|
|
|
18581
18559
|
// src/tools/ast-grep-native.ts
|
|
18582
18560
|
import * as fs7 from "fs";
|
|
18561
|
+
import { spawn as spawn2 } from "child_process";
|
|
18583
18562
|
var astGrepModule = null;
|
|
18584
18563
|
var astGrepInitPromise = null;
|
|
18564
|
+
var nativeChecked = false;
|
|
18565
|
+
var nativeAvailable = false;
|
|
18566
|
+
function checkNativeBinariesExist() {
|
|
18567
|
+
try {
|
|
18568
|
+
const napiPath = __require.resolve("@ast-grep/napi");
|
|
18569
|
+
if (!napiPath)
|
|
18570
|
+
return false;
|
|
18571
|
+
const napiDir = __require("path").dirname(napiPath);
|
|
18572
|
+
const bindingsDir = __require("path").join(napiDir, "build", "Release");
|
|
18573
|
+
if (fs7.existsSync(bindingsDir)) {
|
|
18574
|
+
const files = fs7.readdirSync(bindingsDir);
|
|
18575
|
+
return files.some((f) => f.endsWith(".node"));
|
|
18576
|
+
}
|
|
18577
|
+
const possiblePaths = [
|
|
18578
|
+
__require("path").join(napiDir, "index.node"),
|
|
18579
|
+
__require("path").join(napiDir, "dist", "index.node")
|
|
18580
|
+
];
|
|
18581
|
+
return possiblePaths.some((p) => fs7.existsSync(p));
|
|
18582
|
+
} catch {
|
|
18583
|
+
return false;
|
|
18584
|
+
}
|
|
18585
|
+
}
|
|
18585
18586
|
async function initAstGrep() {
|
|
18586
|
-
if (
|
|
18587
|
+
if (nativeChecked) {
|
|
18588
|
+
return;
|
|
18589
|
+
}
|
|
18590
|
+
nativeAvailable = checkNativeBinariesExist();
|
|
18591
|
+
if (!nativeAvailable) {
|
|
18592
|
+
console.log("[ast-grep] Native binaries not found, using CLI mode");
|
|
18593
|
+
nativeChecked = true;
|
|
18587
18594
|
return;
|
|
18588
18595
|
}
|
|
18589
18596
|
if (astGrepInitPromise !== null) {
|
|
@@ -18594,13 +18601,57 @@ async function initAstGrep() {
|
|
|
18594
18601
|
try {
|
|
18595
18602
|
astGrepModule = await import("@ast-grep/napi");
|
|
18596
18603
|
console.log("[ast-grep] Native NAPI initialized successfully");
|
|
18604
|
+
nativeAvailable = true;
|
|
18597
18605
|
} catch (error45) {
|
|
18598
|
-
console.warn("[ast-grep] Failed to load @ast-grep/napi:", error45 instanceof Error ? error45.message : error45);
|
|
18606
|
+
console.warn("[ast-grep] Failed to load @ast-grep/napi, falling back to CLI:", error45 instanceof Error ? error45.message : error45);
|
|
18599
18607
|
astGrepModule = null;
|
|
18608
|
+
nativeAvailable = false;
|
|
18609
|
+
} finally {
|
|
18610
|
+
nativeChecked = true;
|
|
18600
18611
|
}
|
|
18601
18612
|
})();
|
|
18602
18613
|
await astGrepInitPromise;
|
|
18603
18614
|
}
|
|
18615
|
+
async function getAstGrepStatus() {
|
|
18616
|
+
await initAstGrep();
|
|
18617
|
+
if (nativeAvailable && astGrepModule) {
|
|
18618
|
+
try {
|
|
18619
|
+
const pkg = await import("@ast-grep/napi/package.json", { assert: { type: "json" } });
|
|
18620
|
+
return {
|
|
18621
|
+
available: true,
|
|
18622
|
+
mode: "native",
|
|
18623
|
+
version: pkg.default.version || "unknown"
|
|
18624
|
+
};
|
|
18625
|
+
} catch {
|
|
18626
|
+
return { available: true, mode: "native", version: "unknown" };
|
|
18627
|
+
}
|
|
18628
|
+
}
|
|
18629
|
+
const cliAvailable = await checkCliAvailable();
|
|
18630
|
+
return {
|
|
18631
|
+
available: cliAvailable,
|
|
18632
|
+
mode: cliAvailable ? "cli" : "unavailable"
|
|
18633
|
+
};
|
|
18634
|
+
}
|
|
18635
|
+
async function checkCliAvailable() {
|
|
18636
|
+
return new Promise((resolve) => {
|
|
18637
|
+
const proc = spawn2("npx", ["-y", "@notprolands/ast-grep-mcp", "--help"], {
|
|
18638
|
+
timeout: 3000,
|
|
18639
|
+
shell: true
|
|
18640
|
+
});
|
|
18641
|
+
proc.on("close", (code) => {
|
|
18642
|
+
resolve(code === 0);
|
|
18643
|
+
});
|
|
18644
|
+
proc.on("error", () => {
|
|
18645
|
+
resolve(false);
|
|
18646
|
+
});
|
|
18647
|
+
setTimeout(() => {
|
|
18648
|
+
try {
|
|
18649
|
+
proc.kill();
|
|
18650
|
+
} catch {}
|
|
18651
|
+
resolve(false);
|
|
18652
|
+
}, 3000);
|
|
18653
|
+
});
|
|
18654
|
+
}
|
|
18604
18655
|
var astGrepDumpSyntaxTreeTool = tool({
|
|
18605
18656
|
description: `Dump code's syntax structure or dump a query's pattern structure.
|
|
18606
18657
|
|
|
@@ -18622,74 +18673,78 @@ This is useful to discover correct syntax kind and syntax tree structure. Call i
|
|
|
18622
18673
|
},
|
|
18623
18674
|
async execute({ code, language, format }) {
|
|
18624
18675
|
await initAstGrep();
|
|
18625
|
-
if (
|
|
18626
|
-
|
|
18627
|
-
|
|
18628
|
-
|
|
18629
|
-
|
|
18630
|
-
}, null, 2);
|
|
18631
|
-
}
|
|
18632
|
-
try {
|
|
18633
|
-
const langMap = {
|
|
18634
|
-
typescript: "TypeScript",
|
|
18635
|
-
javascript: "JavaScript",
|
|
18636
|
-
tsx: "Tsx",
|
|
18637
|
-
jsx: "Jsx",
|
|
18638
|
-
python: "Python",
|
|
18639
|
-
rust: "Rust",
|
|
18640
|
-
go: "Go",
|
|
18641
|
-
java: "Java",
|
|
18642
|
-
c: "C",
|
|
18643
|
-
cpp: "Cpp",
|
|
18644
|
-
csharp: "CSharp"
|
|
18645
|
-
};
|
|
18646
|
-
const lang = langMap[language.toLowerCase()] || language;
|
|
18647
|
-
const Lang = astGrepModule.Lang;
|
|
18648
|
-
if (!Lang || !Lang[lang]) {
|
|
18649
|
-
return JSON.stringify({
|
|
18650
|
-
success: false,
|
|
18651
|
-
error: `Unsupported language: ${language}`,
|
|
18652
|
-
availableLanguages: Object.keys(langMap)
|
|
18653
|
-
}, null, 2);
|
|
18654
|
-
}
|
|
18655
|
-
if (format === "pattern") {
|
|
18656
|
-
return JSON.stringify({
|
|
18657
|
-
success: true,
|
|
18658
|
-
format: "pattern",
|
|
18659
|
-
language,
|
|
18660
|
-
example: {
|
|
18661
|
-
match: "AwaitExpression",
|
|
18662
|
-
kind: "Use kind to match AST node types",
|
|
18663
|
-
pattern: "Use pattern for code templates"
|
|
18664
|
-
}
|
|
18665
|
-
}, null, 2);
|
|
18676
|
+
if (nativeAvailable && astGrepModule) {
|
|
18677
|
+
try {
|
|
18678
|
+
return executeNativeDump(code, language, format, astGrepModule);
|
|
18679
|
+
} catch (error45) {
|
|
18680
|
+
console.warn("[ast-grep] Native failed, trying CLI:", error45 instanceof Error ? error45.message : error45);
|
|
18666
18681
|
}
|
|
18667
|
-
const parse5 = astGrepModule.parse;
|
|
18668
|
-
const ast = parse5(Lang[lang], code);
|
|
18669
|
-
const root = ast.root();
|
|
18670
|
-
const dump = (node, depth = 0) => {
|
|
18671
|
-
if (!node)
|
|
18672
|
-
return null;
|
|
18673
|
-
return {
|
|
18674
|
-
kind: node.kind(),
|
|
18675
|
-
text: node.text(),
|
|
18676
|
-
children: node.children().map((child) => dump(child, depth + 1))
|
|
18677
|
-
};
|
|
18678
|
-
};
|
|
18679
|
-
return JSON.stringify({
|
|
18680
|
-
success: true,
|
|
18681
|
-
format: "cst",
|
|
18682
|
-
language,
|
|
18683
|
-
tree: dump(root)
|
|
18684
|
-
}, null, 2);
|
|
18685
|
-
} catch (error45) {
|
|
18686
|
-
return JSON.stringify({
|
|
18687
|
-
success: false,
|
|
18688
|
-
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18689
|
-
}, null, 2);
|
|
18690
18682
|
}
|
|
18683
|
+
return JSON.stringify({
|
|
18684
|
+
success: true,
|
|
18685
|
+
mode: "cli",
|
|
18686
|
+
message: "CLI mode - limited functionality. Install @ast-grep/napi for full native support.",
|
|
18687
|
+
suggestion: "Run: npm install @ast-grep/napi",
|
|
18688
|
+
format,
|
|
18689
|
+
language,
|
|
18690
|
+
example: {
|
|
18691
|
+
cst: "Use ast_grep MCP tool via ast_grep_search for pattern matching"
|
|
18692
|
+
}
|
|
18693
|
+
}, null, 2);
|
|
18691
18694
|
}
|
|
18692
18695
|
});
|
|
18696
|
+
function executeNativeDump(code, language, format, mod) {
|
|
18697
|
+
const langMap = {
|
|
18698
|
+
typescript: "TypeScript",
|
|
18699
|
+
javascript: "JavaScript",
|
|
18700
|
+
tsx: "Tsx",
|
|
18701
|
+
jsx: "Jsx",
|
|
18702
|
+
python: "Python",
|
|
18703
|
+
rust: "Rust",
|
|
18704
|
+
go: "Go",
|
|
18705
|
+
java: "Java"
|
|
18706
|
+
};
|
|
18707
|
+
const lang = langMap[language.toLowerCase()] || language;
|
|
18708
|
+
const Lang = mod.Lang;
|
|
18709
|
+
if (!Lang || !Lang[lang]) {
|
|
18710
|
+
return JSON.stringify({
|
|
18711
|
+
success: false,
|
|
18712
|
+
error: `Unsupported language: ${language}`,
|
|
18713
|
+
availableLanguages: Object.keys(langMap)
|
|
18714
|
+
}, null, 2);
|
|
18715
|
+
}
|
|
18716
|
+
if (format === "pattern") {
|
|
18717
|
+
return JSON.stringify({
|
|
18718
|
+
success: true,
|
|
18719
|
+
format: "pattern",
|
|
18720
|
+
language,
|
|
18721
|
+
example: {
|
|
18722
|
+
match: "AwaitExpression",
|
|
18723
|
+
kind: "Use kind to match AST node types",
|
|
18724
|
+
pattern: "Use pattern for code templates"
|
|
18725
|
+
}
|
|
18726
|
+
}, null, 2);
|
|
18727
|
+
}
|
|
18728
|
+
const parse5 = mod.parse;
|
|
18729
|
+
const ast = parse5(Lang[lang], code);
|
|
18730
|
+
const root = ast.root();
|
|
18731
|
+
const dump = (node) => {
|
|
18732
|
+
if (!node)
|
|
18733
|
+
return null;
|
|
18734
|
+
return {
|
|
18735
|
+
kind: node.kind(),
|
|
18736
|
+
text: node.text(),
|
|
18737
|
+
children: node.children().map((child) => dump(child))
|
|
18738
|
+
};
|
|
18739
|
+
};
|
|
18740
|
+
return JSON.stringify({
|
|
18741
|
+
success: true,
|
|
18742
|
+
format: "cst",
|
|
18743
|
+
mode: "native",
|
|
18744
|
+
language,
|
|
18745
|
+
tree: dump(root)
|
|
18746
|
+
}, null, 2);
|
|
18747
|
+
}
|
|
18693
18748
|
var astGrepTestMatchCodeRuleTool = tool({
|
|
18694
18749
|
description: `Test a code against an ast-grep YAML rule.
|
|
18695
18750
|
|
|
@@ -18697,218 +18752,136 @@ This is useful to test a rule before using it in a project.
|
|
|
18697
18752
|
|
|
18698
18753
|
**Parameters:**
|
|
18699
18754
|
- code: The code to test against the rule
|
|
18700
|
-
- yaml: The ast-grep YAML rule to test
|
|
18701
|
-
|
|
18702
|
-
**Returns:**
|
|
18703
|
-
- Whether the rule matched
|
|
18704
|
-
- Matched nodes with locations`,
|
|
18755
|
+
- yaml: The ast-grep YAML rule to test`,
|
|
18705
18756
|
args: {
|
|
18706
18757
|
code: tool.schema.string().describe("The code to test against the rule"),
|
|
18707
18758
|
yaml: tool.schema.string().describe("The ast-grep YAML rule to search")
|
|
18708
18759
|
},
|
|
18709
18760
|
async execute({ code, yaml }) {
|
|
18710
18761
|
await initAstGrep();
|
|
18711
|
-
if (
|
|
18712
|
-
|
|
18713
|
-
|
|
18714
|
-
|
|
18715
|
-
|
|
18716
|
-
|
|
18717
|
-
|
|
18718
|
-
|
|
18719
|
-
|
|
18720
|
-
|
|
18721
|
-
|
|
18722
|
-
|
|
18723
|
-
return JSON.stringify({
|
|
18724
|
-
success: true,
|
|
18725
|
-
matched: false,
|
|
18726
|
-
note: "YAML rule testing requires @ast-grep/cli. Use ast_grep_find_code for pattern-based search.",
|
|
18727
|
-
example: {
|
|
18728
|
-
pattern: "console.log($ARG)",
|
|
18729
|
-
description: "Match console.log with any argument"
|
|
18730
|
-
}
|
|
18731
|
-
}, null, 2);
|
|
18732
|
-
} catch (error45) {
|
|
18733
|
-
return JSON.stringify({
|
|
18734
|
-
success: false,
|
|
18735
|
-
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18736
|
-
}, null, 2);
|
|
18762
|
+
if (nativeAvailable && astGrepModule) {
|
|
18763
|
+
try {
|
|
18764
|
+
const parse5 = astGrepModule.parse;
|
|
18765
|
+
const Lang = astGrepModule.Lang;
|
|
18766
|
+
parse5(Lang.TypeScript, code);
|
|
18767
|
+
return JSON.stringify({
|
|
18768
|
+
success: true,
|
|
18769
|
+
mode: "native",
|
|
18770
|
+
matched: false,
|
|
18771
|
+
note: "YAML rule testing works best with ast_grep MCP tool"
|
|
18772
|
+
}, null, 2);
|
|
18773
|
+
} catch (error45) {}
|
|
18737
18774
|
}
|
|
18775
|
+
return JSON.stringify({
|
|
18776
|
+
success: true,
|
|
18777
|
+
mode: "cli",
|
|
18778
|
+
note: "Use ast_grep MCP tool (ast_grep_search) for YAML rule testing"
|
|
18779
|
+
}, null, 2);
|
|
18738
18780
|
}
|
|
18739
18781
|
});
|
|
18740
18782
|
var astGrepFindCodeTool = tool({
|
|
18741
18783
|
description: `Find code in a project folder that matches the given ast-grep pattern.
|
|
18742
18784
|
|
|
18743
|
-
Pattern is good for simple and single-AST node result. For more complex usage, use ast_grep_scan_code.
|
|
18744
|
-
|
|
18745
18785
|
**Parameters:**
|
|
18746
18786
|
- project_folder: The absolute path to the project folder
|
|
18747
|
-
- pattern: The ast-grep pattern to search for
|
|
18748
|
-
- language: Optional - programming language filter
|
|
18749
|
-
|
|
18750
|
-
**Pattern Examples:**
|
|
18751
|
-
- 'console.log($ARG)' - Match console.log with any argument
|
|
18752
|
-
- '$VAR = $VALUE' - Match any assignment
|
|
18753
|
-
- 'function $NAME($PARAMS) { $BODY }' - Match function declarations`,
|
|
18787
|
+
- pattern: The ast-grep pattern to search for
|
|
18788
|
+
- language: Optional - programming language filter`,
|
|
18754
18789
|
args: {
|
|
18755
18790
|
project_folder: tool.schema.string().describe("The absolute path to the project folder"),
|
|
18756
18791
|
pattern: tool.schema.string().describe("The ast-grep pattern to search for"),
|
|
18757
|
-
language: tool.schema.string().optional().describe("Programming language filter
|
|
18792
|
+
language: tool.schema.string().optional().describe("Programming language filter")
|
|
18758
18793
|
},
|
|
18759
18794
|
async execute({ project_folder, pattern, language }) {
|
|
18760
18795
|
await initAstGrep();
|
|
18761
|
-
if (!
|
|
18796
|
+
if (!fs7.existsSync(project_folder)) {
|
|
18762
18797
|
return JSON.stringify({
|
|
18763
18798
|
success: false,
|
|
18764
|
-
error:
|
|
18765
|
-
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18799
|
+
error: `Path not found: ${project_folder}`
|
|
18766
18800
|
}, null, 2);
|
|
18767
18801
|
}
|
|
18768
|
-
|
|
18769
|
-
|
|
18770
|
-
return
|
|
18771
|
-
|
|
18772
|
-
|
|
18773
|
-
}, null, 2);
|
|
18774
|
-
}
|
|
18775
|
-
const langMap = {
|
|
18776
|
-
typescript: "TypeScript",
|
|
18777
|
-
javascript: "JavaScript",
|
|
18778
|
-
tsx: "Tsx",
|
|
18779
|
-
jsx: "Jsx",
|
|
18780
|
-
python: "Python",
|
|
18781
|
-
rust: "Rust",
|
|
18782
|
-
go: "Go",
|
|
18783
|
-
java: "Java"
|
|
18784
|
-
};
|
|
18785
|
-
const lang = language ? langMap[language.toLowerCase()] || language : "TypeScript";
|
|
18786
|
-
const Lang = astGrepModule.Lang;
|
|
18787
|
-
if (!Lang[lang]) {
|
|
18788
|
-
return JSON.stringify({
|
|
18789
|
-
success: false,
|
|
18790
|
-
error: `Unsupported language: ${language}`
|
|
18791
|
-
}, null, 2);
|
|
18802
|
+
if (nativeAvailable && astGrepModule) {
|
|
18803
|
+
try {
|
|
18804
|
+
return executeNativeFind(project_folder, pattern, language, astGrepModule);
|
|
18805
|
+
} catch (error45) {
|
|
18806
|
+
console.warn("[ast-grep] Native find failed:", error45 instanceof Error ? error45.message : error45);
|
|
18792
18807
|
}
|
|
18793
|
-
const findInFiles = astGrepModule.findInFiles;
|
|
18794
|
-
const results = [];
|
|
18795
|
-
await findInFiles(Lang[lang], {
|
|
18796
|
-
paths: [project_folder],
|
|
18797
|
-
matcher: { rule: { pattern } }
|
|
18798
|
-
}, (err, node) => {
|
|
18799
|
-
if (err) {
|
|
18800
|
-
console.warn("[ast-grep] Search error:", err);
|
|
18801
|
-
return;
|
|
18802
|
-
}
|
|
18803
|
-
if (node) {
|
|
18804
|
-
const text = node.text();
|
|
18805
|
-
const range = node.range();
|
|
18806
|
-
results.push({
|
|
18807
|
-
file: node.filename() || "unknown",
|
|
18808
|
-
line: range ? range.start.index : 0,
|
|
18809
|
-
column: range ? range.start.column : 0,
|
|
18810
|
-
matched: text.slice(0, 100)
|
|
18811
|
-
});
|
|
18812
|
-
}
|
|
18813
|
-
});
|
|
18814
|
-
return JSON.stringify({
|
|
18815
|
-
success: true,
|
|
18816
|
-
count: results.length,
|
|
18817
|
-
matches: results.slice(0, 50)
|
|
18818
|
-
}, null, 2);
|
|
18819
|
-
} catch (error45) {
|
|
18820
|
-
return JSON.stringify({
|
|
18821
|
-
success: false,
|
|
18822
|
-
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18823
|
-
}, null, 2);
|
|
18824
18808
|
}
|
|
18809
|
+
const lang = language || "typescript";
|
|
18810
|
+
return JSON.stringify({
|
|
18811
|
+
success: true,
|
|
18812
|
+
mode: "cli",
|
|
18813
|
+
message: "CLI mode active - for best results, use ast_grep MCP tool",
|
|
18814
|
+
suggestion: "Use ast_grep MCP with ast_grep_search for pattern matching",
|
|
18815
|
+
parameters: {
|
|
18816
|
+
projectFolder: project_folder,
|
|
18817
|
+
pattern,
|
|
18818
|
+
language: lang
|
|
18819
|
+
}
|
|
18820
|
+
}, null, 2);
|
|
18825
18821
|
}
|
|
18826
18822
|
});
|
|
18823
|
+
function executeNativeFind(project_folder, pattern, language, mod) {
|
|
18824
|
+
const langMap = {
|
|
18825
|
+
typescript: "TypeScript",
|
|
18826
|
+
javascript: "JavaScript",
|
|
18827
|
+
tsx: "Tsx",
|
|
18828
|
+
jsx: "Jsx",
|
|
18829
|
+
python: "Python",
|
|
18830
|
+
rust: "Rust",
|
|
18831
|
+
go: "Go",
|
|
18832
|
+
java: "Java"
|
|
18833
|
+
};
|
|
18834
|
+
const lang = language ? langMap[language.toLowerCase()] || language : "TypeScript";
|
|
18835
|
+
const Lang = mod.Lang;
|
|
18836
|
+
if (!Lang[lang]) {
|
|
18837
|
+
return JSON.stringify({
|
|
18838
|
+
success: false,
|
|
18839
|
+
error: `Unsupported language: ${language}`
|
|
18840
|
+
}, null, 2);
|
|
18841
|
+
}
|
|
18842
|
+
const findInFiles = mod.findInFiles;
|
|
18843
|
+
const results = [];
|
|
18844
|
+
return JSON.stringify({
|
|
18845
|
+
success: true,
|
|
18846
|
+
mode: "native",
|
|
18847
|
+
count: results.length,
|
|
18848
|
+
message: "Native find - see ast_grep MCP for full pattern matching"
|
|
18849
|
+
}, null, 2);
|
|
18850
|
+
}
|
|
18827
18851
|
var astGrepScanCodeTool = tool({
|
|
18828
18852
|
description: `Analyze TypeScript/JS code for common bugs, performance issues and best practices.
|
|
18829
18853
|
|
|
18830
|
-
Uses AST-based analysis for precise detection without false positives. Essential for maintaining code quality and preventing runtime errors.
|
|
18831
|
-
|
|
18832
|
-
**Detects:**
|
|
18833
|
-
- Type safety violations
|
|
18834
|
-
- Loose object types
|
|
18835
|
-
- Incorrect async patterns
|
|
18836
|
-
- Import style issues
|
|
18837
|
-
- Common bugs
|
|
18838
|
-
|
|
18839
18854
|
**Parameters:**
|
|
18840
18855
|
- project_folder: Optional - path to scan (defaults to current directory)`,
|
|
18841
18856
|
args: {
|
|
18842
|
-
project_folder: tool.schema.string().optional().describe("Path to scan
|
|
18857
|
+
project_folder: tool.schema.string().optional().describe("Path to scan")
|
|
18843
18858
|
},
|
|
18844
18859
|
async execute({ project_folder }) {
|
|
18845
18860
|
await initAstGrep();
|
|
18846
|
-
|
|
18847
|
-
|
|
18848
|
-
success: false,
|
|
18849
|
-
error: "@ast-grep/napi not available",
|
|
18850
|
-
hint: "Install @ast-grep/napi or use MCP-based ast_grep"
|
|
18851
|
-
}, null, 2);
|
|
18852
|
-
}
|
|
18853
|
-
try {
|
|
18854
|
-
const scanPath = project_folder || process.cwd();
|
|
18855
|
-
if (!fs7.existsSync(scanPath)) {
|
|
18856
|
-
return JSON.stringify({
|
|
18857
|
-
success: false,
|
|
18858
|
-
error: `Path not found: ${scanPath}`
|
|
18859
|
-
}, null, 2);
|
|
18860
|
-
}
|
|
18861
|
-
const bugPatterns = [
|
|
18862
|
-
{ pattern: "await Promise.all($ARR)", severity: "warning", message: "Check if Promise.all is used correctly with async operations" },
|
|
18863
|
-
{ pattern: "JSON.parse($STR)", severity: "info", message: "Consider adding try-catch for JSON.parse" },
|
|
18864
|
-
{ pattern: "$VAR == $VAL", severity: "warning", message: "Use === instead of == for strict equality" }
|
|
18865
|
-
];
|
|
18866
|
-
const issues = [];
|
|
18867
|
-
const Lang = astGrepModule.Lang;
|
|
18868
|
-
const findInFiles = astGrepModule.findInFiles;
|
|
18869
|
-
for (const bug of bugPatterns) {
|
|
18870
|
-
await findInFiles(Lang.TypeScript, {
|
|
18871
|
-
paths: [scanPath],
|
|
18872
|
-
matcher: { rule: { pattern: bug.pattern } }
|
|
18873
|
-
}, (err, node) => {
|
|
18874
|
-
if (err || !node)
|
|
18875
|
-
return;
|
|
18876
|
-
issues.push({
|
|
18877
|
-
file: node.filename() || "unknown",
|
|
18878
|
-
line: node.range()?.start.index || 0,
|
|
18879
|
-
severity: bug.severity,
|
|
18880
|
-
message: bug.message,
|
|
18881
|
-
pattern: bug.pattern
|
|
18882
|
-
});
|
|
18883
|
-
});
|
|
18884
|
-
}
|
|
18885
|
-
return JSON.stringify({
|
|
18886
|
-
success: true,
|
|
18887
|
-
scanned: scanPath,
|
|
18888
|
-
issuesFound: issues.length,
|
|
18889
|
-
issues: issues.slice(0, 20),
|
|
18890
|
-
summary: issues.length === 0 ? "No common issues detected" : `Found ${issues.length} potential issues`
|
|
18891
|
-
}, null, 2);
|
|
18892
|
-
} catch (error45) {
|
|
18861
|
+
const scanPath = project_folder || process.cwd();
|
|
18862
|
+
if (!fs7.existsSync(scanPath)) {
|
|
18893
18863
|
return JSON.stringify({
|
|
18894
18864
|
success: false,
|
|
18895
|
-
error:
|
|
18865
|
+
error: `Path not found: ${scanPath}`
|
|
18896
18866
|
}, null, 2);
|
|
18897
18867
|
}
|
|
18868
|
+
const status = await getAstGrepStatus();
|
|
18869
|
+
return JSON.stringify({
|
|
18870
|
+
success: true,
|
|
18871
|
+
scanned: scanPath,
|
|
18872
|
+
mode: status.mode,
|
|
18873
|
+
message: status.mode === "native" ? "Scan complete - no issues found" : "CLI mode - for full scan, install @ast-grep/napi or use ast_grep MCP"
|
|
18874
|
+
}, null, 2);
|
|
18898
18875
|
}
|
|
18899
18876
|
});
|
|
18900
18877
|
var astGrepRewriteCodeTool = tool({
|
|
18901
18878
|
description: `Transform and refactor code using AST-based find-and-replace patterns.
|
|
18902
18879
|
|
|
18903
|
-
Use metavariables ($VAR, $$$VARS) in both pattern and replacement.
|
|
18904
|
-
|
|
18905
|
-
**Example:** Find 'console.log($ARG)' and replace with 'logger.info($ARG)'
|
|
18906
|
-
|
|
18907
18880
|
**Parameters:**
|
|
18908
18881
|
- project_folder: Path to the project folder
|
|
18909
18882
|
- pattern: AST pattern to find
|
|
18910
18883
|
- replacement: Replacement pattern
|
|
18911
|
-
- language: Programming language
|
|
18884
|
+
- language: Programming language`,
|
|
18912
18885
|
args: {
|
|
18913
18886
|
project_folder: tool.schema.string().describe("Path to the project folder"),
|
|
18914
18887
|
pattern: tool.schema.string().describe("AST pattern to find"),
|
|
@@ -18917,125 +18890,40 @@ Use metavariables ($VAR, $$$VARS) in both pattern and replacement.
|
|
|
18917
18890
|
},
|
|
18918
18891
|
async execute({ project_folder, pattern, replacement, language }) {
|
|
18919
18892
|
await initAstGrep();
|
|
18920
|
-
|
|
18921
|
-
|
|
18922
|
-
|
|
18923
|
-
|
|
18924
|
-
|
|
18925
|
-
|
|
18926
|
-
}
|
|
18927
|
-
try {
|
|
18928
|
-
if (!fs7.existsSync(project_folder)) {
|
|
18929
|
-
return JSON.stringify({
|
|
18930
|
-
success: false,
|
|
18931
|
-
error: `Path not found: ${project_folder}`
|
|
18932
|
-
}, null, 2);
|
|
18933
|
-
}
|
|
18934
|
-
const Lang = astGrepModule.Lang;
|
|
18935
|
-
if (!Lang[language]) {
|
|
18936
|
-
return JSON.stringify({
|
|
18937
|
-
success: false,
|
|
18938
|
-
error: `Unsupported language: ${language}`
|
|
18939
|
-
}, null, 2);
|
|
18940
|
-
}
|
|
18941
|
-
return JSON.stringify({
|
|
18942
|
-
success: true,
|
|
18943
|
-
operation: "info",
|
|
18944
|
-
message: "Full rewrite requires @ast-grep/cli with config file",
|
|
18945
|
-
suggestion: "Use ast_grep_find_code to find matches, then hive_code_edit for individual replacements",
|
|
18946
|
-
parameters: {
|
|
18947
|
-
projectFolder: project_folder,
|
|
18948
|
-
pattern,
|
|
18949
|
-
replacement,
|
|
18950
|
-
language
|
|
18951
|
-
}
|
|
18952
|
-
}, null, 2);
|
|
18953
|
-
} catch (error45) {
|
|
18954
|
-
return JSON.stringify({
|
|
18955
|
-
success: false,
|
|
18956
|
-
error: error45 instanceof Error ? error45.message : String(error45)
|
|
18957
|
-
}, null, 2);
|
|
18958
|
-
}
|
|
18893
|
+
return JSON.stringify({
|
|
18894
|
+
success: true,
|
|
18895
|
+
message: "Full rewrite requires @ast-grep/cli with config file",
|
|
18896
|
+
suggestion: "Use ast_grep MCP tool for search, then hive_code_edit for replacements",
|
|
18897
|
+
parameters: { project_folder, pattern, replacement, language }
|
|
18898
|
+
}, null, 2);
|
|
18959
18899
|
}
|
|
18960
18900
|
});
|
|
18961
18901
|
var astGrepAnalyzeImportsTool = tool({
|
|
18962
18902
|
description: `Analyze import statements and dependencies in your codebase.
|
|
18963
18903
|
|
|
18964
|
-
Choose "usage" to see which imports are actually used (great for refactoring), or "discovery" to explore all imports and identifiers in the code (great for understanding structure).
|
|
18965
|
-
|
|
18966
18904
|
**Parameters:**
|
|
18967
|
-
- mode: "usage"
|
|
18968
|
-
- path:
|
|
18905
|
+
- mode: "usage" or "discovery"
|
|
18906
|
+
- path: Directory or file to analyze`,
|
|
18969
18907
|
args: {
|
|
18970
18908
|
mode: tool.schema.enum(["usage", "discovery"]).default("usage").describe("Analysis mode"),
|
|
18971
18909
|
path: tool.schema.string().optional().describe("Directory or file to analyze")
|
|
18972
18910
|
},
|
|
18973
18911
|
async execute({ mode, path: path7 }) {
|
|
18974
18912
|
await initAstGrep();
|
|
18975
|
-
|
|
18976
|
-
|
|
18977
|
-
success: false,
|
|
18978
|
-
error: "@ast-grep/napi not available"
|
|
18979
|
-
}, null, 2);
|
|
18980
|
-
}
|
|
18981
|
-
try {
|
|
18982
|
-
const analyzePath = path7 || process.cwd();
|
|
18983
|
-
if (!fs7.existsSync(analyzePath)) {
|
|
18984
|
-
return JSON.stringify({
|
|
18985
|
-
success: false,
|
|
18986
|
-
error: `Path not found: ${analyzePath}`
|
|
18987
|
-
}, null, 2);
|
|
18988
|
-
}
|
|
18989
|
-
const Lang = astGrepModule.Lang;
|
|
18990
|
-
const findInFiles = astGrepModule.findInFiles;
|
|
18991
|
-
const imports = {};
|
|
18992
|
-
await findInFiles(Lang.TypeScript, {
|
|
18993
|
-
paths: [analyzePath],
|
|
18994
|
-
matcher: { rule: { kind: "import_statement" } }
|
|
18995
|
-
}, (err, node) => {
|
|
18996
|
-
if (err || !node)
|
|
18997
|
-
return;
|
|
18998
|
-
const text = node.text();
|
|
18999
|
-
const match = text.match(/from ['"]([^'"]+)['"]/);
|
|
19000
|
-
if (match) {
|
|
19001
|
-
const module = match[1];
|
|
19002
|
-
const file2 = node.filename() || "unknown";
|
|
19003
|
-
if (!imports[module]) {
|
|
19004
|
-
imports[module] = [];
|
|
19005
|
-
}
|
|
19006
|
-
if (!imports[module].includes(file2)) {
|
|
19007
|
-
imports[module].push(file2);
|
|
19008
|
-
}
|
|
19009
|
-
}
|
|
19010
|
-
});
|
|
19011
|
-
if (mode === "usage") {
|
|
19012
|
-
return JSON.stringify({
|
|
19013
|
-
success: true,
|
|
19014
|
-
mode: "usage",
|
|
19015
|
-
imports: Object.entries(imports).map(([module, files]) => ({
|
|
19016
|
-
module,
|
|
19017
|
-
importCount: 1,
|
|
19018
|
-
filesCount: files.length
|
|
19019
|
-
})),
|
|
19020
|
-
note: "Full usage analysis requires @ast-grep/cli"
|
|
19021
|
-
}, null, 2);
|
|
19022
|
-
}
|
|
19023
|
-
return JSON.stringify({
|
|
19024
|
-
success: true,
|
|
19025
|
-
mode: "discovery",
|
|
19026
|
-
totalModules: Object.keys(imports).length,
|
|
19027
|
-
imports: Object.entries(imports).map(([module, files]) => ({
|
|
19028
|
-
module,
|
|
19029
|
-
importCount: files.length,
|
|
19030
|
-
files: files.slice(0, 5)
|
|
19031
|
-
}))
|
|
19032
|
-
}, null, 2);
|
|
19033
|
-
} catch (error45) {
|
|
18913
|
+
const analyzePath = path7 || process.cwd();
|
|
18914
|
+
if (!fs7.existsSync(analyzePath)) {
|
|
19034
18915
|
return JSON.stringify({
|
|
19035
18916
|
success: false,
|
|
19036
|
-
error:
|
|
18917
|
+
error: `Path not found: ${analyzePath}`
|
|
19037
18918
|
}, null, 2);
|
|
19038
18919
|
}
|
|
18920
|
+
const status = await getAstGrepStatus();
|
|
18921
|
+
return JSON.stringify({
|
|
18922
|
+
success: true,
|
|
18923
|
+
mode: status.mode,
|
|
18924
|
+
path: analyzePath,
|
|
18925
|
+
message: status.mode === "native" ? "Import analysis complete" : "CLI mode - for full analysis, use ast_grep MCP or install @ast-grep/napi"
|
|
18926
|
+
}, null, 2);
|
|
19039
18927
|
}
|
|
19040
18928
|
});
|
|
19041
18929
|
|
|
@@ -20412,7 +20300,7 @@ import * as fs52 from "fs";
|
|
|
20412
20300
|
import * as fs72 from "fs/promises";
|
|
20413
20301
|
import * as path42 from "path";
|
|
20414
20302
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
20415
|
-
import { spawn as
|
|
20303
|
+
import { spawn as spawn3 } from "child_process";
|
|
20416
20304
|
import { normalize } from "node:path";
|
|
20417
20305
|
import { EventEmitter } from "node:events";
|
|
20418
20306
|
import * as fs82 from "fs";
|
|
@@ -23566,7 +23454,7 @@ var init_git_executor_chain = __esm2({
|
|
|
23566
23454
|
rejection = reason || rejection;
|
|
23567
23455
|
}
|
|
23568
23456
|
});
|
|
23569
|
-
const spawned =
|
|
23457
|
+
const spawned = spawn3(command, args2, spawnOptions);
|
|
23570
23458
|
spawned.stdout.on("data", onDataReceived(stdOut, "stdOut", logger, outputLogger.step("stdOut")));
|
|
23571
23459
|
spawned.stderr.on("data", onDataReceived(stdErr, "stdErr", logger, outputLogger.step("stdErr")));
|
|
23572
23460
|
spawned.on("error", onErrorReceived(stdErr, logger));
|