@hung319/opencode-hive 1.5.9 → 1.6.0

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 CHANGED
@@ -71,7 +71,7 @@ npm install @hung319/opencode-hive
71
71
  2. Set `EXA_API_KEY` to enable `websearch_exa` (optional).
72
72
  3. Restart OpenCode.
73
73
 
74
- This enables tools like `grep_app_searchGitHub`, `context7_query-docs`, `websearch_web_search_exa`, and `ast_grep_search`.
74
+ This enables tools like `grep_app_searchGitHub`, `context7_query-docs`, and `websearch_web_search_exa`.
75
75
 
76
76
  ## The Workflow
77
77
 
@@ -206,7 +206,7 @@ Hive uses a config file at `~/.config/opencode/agent_hive.json`. You can customi
206
206
  {
207
207
  "$schema": "https://raw.githubusercontent.com/hung319/agent-hive/main/packages/opencode-hive/schema/agent_hive.schema.json",
208
208
  "disableSkills": ["brainstorming", "writing-plans"],
209
- "disableMcps": ["websearch", "ast_grep"]
209
+ "disableMcps": ["websearch", "pare_search"]
210
210
  }
211
211
  ```
212
212
 
@@ -230,21 +230,8 @@ Hive uses a config file at `~/.config/opencode/agent_hive.json`. You can customi
230
230
  | `websearch` | Web search via [Exa AI](https://exa.ai). Real-time web searches and content scraping. | Set `EXA_API_KEY` env var |
231
231
  | `context7` | Library documentation lookup via [Context7](https://context7.com). Query up-to-date docs for any programming library. | None |
232
232
  | `grep_app` | GitHub code search via [grep.app](https://grep.app). Find real-world code examples from public repositories. | None |
233
- | `ast_grep` | Native NAPI-powered AST analysis. Pattern matching across 25+ languages. | Built-in (no npx needed) |
234
233
  | `pare_search` | Structured ripgrep/fd search with 65-95% token reduction. | None (runs via npx) |
235
-
236
- #### Native ast-grep Tools
237
-
238
- Instead of MCP-based ast-grep, this plugin includes native tools using `@ast-grep/napi`:
239
-
240
- | Tool | Description |
241
- |------|-------------|
242
- | `ast_grep_dump_syntax_tree` | Dump code's syntax structure for debugging |
243
- | `ast_grep_test_match_code_rule` | Test code against YAML rules |
244
- | `ast_grep_find_code` | Find code matching patterns in project |
245
- | `ast_grep_scan_code` | Scan for TypeScript bugs and best practices |
246
- | `ast_grep_rewrite_code` | Transform/refactor code with AST patterns |
247
- | `ast_grep_analyze_imports` | Analyze import usage in codebase |
234
+ | `veil` | Code discovery and intelligent retrieval. | None (runs via npx) |
248
235
 
249
236
  ### Per-Agent Skills
250
237
 
@@ -559,26 +546,21 @@ bunx @hung319/opencode-hive doctor
559
546
  ### What it checks
560
547
 
561
548
  1. **Dependencies** - npm packages installed?
562
- - Core: `@ast-grep/napi`, `@notprolands/ast-grep-mcp`, `@paretools/search`
563
549
  - Agent: `@sparkleideas/agent-booster`, `@sparkleideas/memory`
564
- - MCPs: `@upstash/context7-mcp`, `exa-mcp-server`, `grep-mcp`
565
- - Blockchain: `btca-ask`, `opencode-model-selector`
550
+ - MCPs: `@paretools/search`, `@upstash/context7-mcp`, `exa-mcp-server`, `grep-mcp`
551
+ - Blockchain: `btca`, `opencode-model-selector`
566
552
 
567
553
  2. **CLI Tools** - npx tools available?
568
554
  - `dora` - Code navigation (SCIP-based)
569
555
  - `auto-cr` - Automated code review (SWC)
570
556
  - `scip-typescript` - TypeScript indexer
571
557
  - `veil` - Code discovery
572
- - `btca` - BTC/A blockchain agent
573
-
574
- 3. **Native Binaries** - @ast-grep/napi tree-sitter?
575
- - Native mode: Fastest, uses compiled binaries
576
- - CLI mode: Falls back to MCP via npx
558
+ - `btca` - BTC/A blockchain agent (from npmx.dev)
577
559
 
578
- 4. **Config** - Features enabled?
560
+ 3. **Config** - Features enabled?
579
561
  - snip, vectorMemory, agentBooster
580
562
  - sandbox mode
581
- - MCPs: ast_grep, veil, pare_search
563
+ - MCPs: veil, pare_search
582
564
 
583
565
  ### Example Output
584
566
 
@@ -586,9 +568,8 @@ bunx @hung319/opencode-hive doctor
586
568
  {
587
569
  "status": "warning",
588
570
  "summary": {
589
- "dependencies": "⚠️ 2 missing: agent-booster, vector-memory",
571
+ "dependencies": "⚠️ 2 missing: agent-booster, memory",
590
572
  "cliTools": "⚠️ 1 missing: auto-cr",
591
- "nativeBinaries": "⚡ CLI mode (native unavailable)",
592
573
  "config": "💡 2 disabled: snip, vectorMemory"
593
574
  },
594
575
  "actionItems": [
package/bin/doctor.ts CHANGED
@@ -231,15 +231,13 @@ function runDoctor(): DoctorOutput {
231
231
 
232
232
  // Check dependencies
233
233
  const deps = [
234
- '@ast-grep/napi',
235
- '@notprolands/ast-grep-mcp',
236
234
  '@sparkleideas/agent-booster',
237
235
  '@sparkleideas/memory',
238
236
  '@paretools/search',
239
237
  '@upstash/context7-mcp',
240
238
  'exa-mcp-server',
241
239
  'grep-mcp',
242
- 'btca-ask',
240
+ 'btca',
243
241
  'opencode-model-selector',
244
242
  ];
245
243
 
@@ -253,8 +251,7 @@ function runDoctor(): DoctorOutput {
253
251
  { name: 'auto-cr', command: 'auto-cr-cmd', description: 'SWC-based automated code review' },
254
252
  { name: 'veil', command: '@ushiradineth/veil', description: 'Code discovery and retrieval' },
255
253
  { name: 'scip-typescript', command: '@sourcegraph/scip-typescript', description: 'TypeScript SCIP indexer' },
256
- { name: 'btca', command: 'btca-ask', description: 'BTC/A agent for blockchain tasks' },
257
- { name: 'ast-grep', command: '@notprolands/ast-grep-mcp', description: 'AST-based pattern matching' },
254
+ { name: 'btca', command: 'btca', description: 'BTC/A agent for blockchain tasks' },
258
255
  ];
259
256
 
260
257
  output.checks.cliTools.items = cliTools.map(t => checkCliTool(t.name, t.command, t.description));
package/dist/index.js CHANGED
@@ -17812,8 +17812,7 @@ async function checkPackage(packageName) {
17812
17812
  const result = {
17813
17813
  name: packageName,
17814
17814
  package: packageName,
17815
- installed: false,
17816
- optional: true
17815
+ installed: false
17817
17816
  };
17818
17817
  try {
17819
17818
  const packageJsonPath = __require.resolve(`${packageName}/package.json`, {
@@ -17847,34 +17846,6 @@ function checkCliTool(name, command, description) {
17847
17846
  }
17848
17847
  return result;
17849
17848
  }
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)";
17872
- }
17873
- } catch (error45) {
17874
- result.reason = "@ast-grep/napi not installed";
17875
- }
17876
- return result;
17877
- }
17878
17849
  function checkConfig() {
17879
17850
  const checks3 = [];
17880
17851
  const configPaths = [
@@ -17921,11 +17892,6 @@ function checkConfig() {
17921
17892
  recommendation: sandboxEnabled ? `Sandbox enabled (${sandboxMode} mode)` : 'Enable sandbox: Add { "sandbox": { "mode": "docker" } } to config for isolated testing'
17922
17893
  });
17923
17894
  const disabledMcps = config2?.disableMcps || [];
17924
- checks3.push({
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'
17928
- });
17929
17895
  checks3.push({
17930
17896
  name: "veil MCP",
17931
17897
  enabled: !disabledMcps.includes("veil"),
@@ -17942,10 +17908,9 @@ var hiveDoctorTool = tool({
17942
17908
  description: `Hive Doctor - System health check with actionable fixes.
17943
17909
 
17944
17910
  **Checks performed:**
17945
- 1. Dependencies - All MCP packages, ast-grep, agent-booster, etc.
17911
+ 1. Dependencies - MCP packages, agent tools, blockchain, etc.
17946
17912
  2. CLI Tools - dora, auto-cr, scip-typescript, veil, btca, etc.
17947
- 3. Native Binaries - tree-sitter binaries for ast-grep
17948
- 4. Config - optimizations and MCPs enabled
17913
+ 3. Config - optimizations and MCPs enabled
17949
17914
 
17950
17915
  **Output includes:**
17951
17916
  - Status summary (healthy/warning/action-required)
@@ -17957,28 +17922,22 @@ var hiveDoctorTool = tool({
17957
17922
  args: {},
17958
17923
  async execute() {
17959
17924
  const dependencyChecks = await Promise.all([
17960
- checkPackage("@ast-grep/napi"),
17961
- checkPackage("@notprolands/ast-grep-mcp"),
17962
- checkPackage("@paretools/search"),
17963
17925
  checkPackage("@sparkleideas/agent-booster"),
17964
17926
  checkPackage("@sparkleideas/memory"),
17927
+ checkPackage("@paretools/search"),
17965
17928
  checkPackage("@upstash/context7-mcp"),
17966
17929
  checkPackage("exa-mcp-server"),
17967
17930
  checkPackage("grep-mcp"),
17968
- checkPackage("btca-ask"),
17969
- checkPackage("opencode-model-selector"),
17970
- checkPackage("opencode-model-selector-free")
17931
+ checkPackage("btca"),
17932
+ checkPackage("opencode-model-selector")
17971
17933
  ]);
17972
17934
  const cliToolChecks = [
17973
17935
  checkCliTool("dora", "@butttons/dora", "SCIP-based code navigation"),
17974
17936
  checkCliTool("auto-cr", "auto-cr-cmd", "SWC-based automated code review"),
17975
17937
  checkCliTool("scip-typescript", "@sourcegraph/scip-typescript", "TypeScript SCIP indexer"),
17976
17938
  checkCliTool("veil", "@ushiradineth/veil", "Code discovery and retrieval"),
17977
- checkCliTool("btca", "btca-ask", "BTC/A agent for blockchain tasks"),
17978
- checkCliTool("ast-grep", "@notprolands/ast-grep-mcp", "AST-based pattern matching")
17939
+ checkCliTool("btca", "btca", "BTC/A agent for blockchain tasks")
17979
17940
  ];
17980
- const nativeCheck = checkAstGrepNative();
17981
- const nativeStatus = nativeCheck.available ? "native" : "cli-mode";
17982
17941
  const configChecks = checkConfig();
17983
17942
  const missingDeps = dependencyChecks.filter((d) => !d.installed);
17984
17943
  const missingTools = cliToolChecks.filter((t) => !t.installed);
@@ -17995,15 +17954,15 @@ var hiveDoctorTool = tool({
17995
17954
  priority: "high",
17996
17955
  action: `Install ${tool3.name}`,
17997
17956
  command: `npx -y ${tool3.command}`,
17998
- reason: `${tool3.description} - improves code navigation/review`
17957
+ reason: `${tool3.description}`
17999
17958
  });
18000
17959
  }
18001
- if (!dependencyChecks.find((d) => d.package === "@notprolands/ast-grep-mcp")?.installed) {
17960
+ if (!dependencyChecks.find((d) => d.package === "btca")?.installed) {
18002
17961
  actionItems.push({
18003
17962
  priority: "medium",
18004
- action: "Install ast-grep MCP for YAML rule testing",
18005
- command: `npm install @notprolands/ast-grep-mcp`,
18006
- reason: "Full ast-grep functionality with YAML rules"
17963
+ action: "Install btca for blockchain tasks",
17964
+ command: `npm install btca`,
17965
+ reason: "BTC/A agent for blockchain analysis and development"
18007
17966
  });
18008
17967
  }
18009
17968
  for (const config2 of disabledConfigs) {
@@ -18020,7 +17979,6 @@ var hiveDoctorTool = tool({
18020
17979
  const summary = {
18021
17980
  dependencies: missingDeps.length === 0 ? "✅ All dependencies installed" : `⚠️ ${missingDeps.length} missing: ${missingDeps.map((d) => d.name).join(", ")}`,
18022
17981
  cliTools: missingTools.length === 0 ? "✅ All CLI tools available" : `⚠️ ${missingTools.length} missing: ${missingTools.map((t) => t.name).join(", ")}`,
18023
- nativeBinaries: nativeCheck.available ? `✅ Native mode (v${nativeCheck.version || "?"})` : `⚡ CLI mode (${nativeCheck.reason || "native unavailable"})`,
18024
17982
  config: disabledConfigs.length === 0 ? "✅ All optimizations enabled" : `\uD83D\uDCA1 ${disabledConfigs.length} disabled: ${disabledConfigs.map((c) => c.name).join(", ")}`
18025
17983
  };
18026
17984
  const result = {
@@ -18037,14 +17995,6 @@ var hiveDoctorTool = tool({
18037
17995
  available: cliToolChecks.filter((t) => t.installed).length,
18038
17996
  missing: missingTools
18039
17997
  },
18040
- nativeBinaries: {
18041
- status: nativeStatus,
18042
- reason: nativeCheck.reason,
18043
- astGrep: {
18044
- available: nativeCheck.available,
18045
- version: nativeCheck.version
18046
- }
18047
- },
18048
17998
  config: configChecks
18049
17999
  },
18050
18000
  actionItems,
@@ -18063,8 +18013,8 @@ var hiveDoctorQuickTool = tool({
18063
18013
  args: {},
18064
18014
  async execute() {
18065
18015
  const checks3 = await Promise.all([
18066
- checkPackage("@ast-grep/napi"),
18067
18016
  checkPackage("@sparkleideas/agent-booster"),
18017
+ checkPackage("btca"),
18068
18018
  checkCliTool("dora", "@butttons/dora", ""),
18069
18019
  checkCliTool("auto-cr", "auto-cr-cmd", "")
18070
18020
  ]);
@@ -18563,377 +18513,6 @@ var autoCrRulesTool = tool({
18563
18513
  }
18564
18514
  });
18565
18515
 
18566
- // src/tools/ast-grep-native.ts
18567
- import * as fs7 from "fs";
18568
- import { spawn as spawn2 } from "child_process";
18569
- var astGrepModule = null;
18570
- var astGrepInitPromise = null;
18571
- var nativeChecked = false;
18572
- var nativeAvailable = false;
18573
- function checkNativeBinariesExist() {
18574
- try {
18575
- const napiPath = __require.resolve("@ast-grep/napi");
18576
- if (!napiPath)
18577
- return false;
18578
- const napiDir = __require("path").dirname(napiPath);
18579
- const bindingsDir = __require("path").join(napiDir, "build", "Release");
18580
- if (fs7.existsSync(bindingsDir)) {
18581
- const files = fs7.readdirSync(bindingsDir);
18582
- return files.some((f) => f.endsWith(".node"));
18583
- }
18584
- const possiblePaths = [
18585
- __require("path").join(napiDir, "index.node"),
18586
- __require("path").join(napiDir, "dist", "index.node")
18587
- ];
18588
- return possiblePaths.some((p) => fs7.existsSync(p));
18589
- } catch {
18590
- return false;
18591
- }
18592
- }
18593
- async function initAstGrep() {
18594
- if (nativeChecked) {
18595
- return;
18596
- }
18597
- nativeAvailable = checkNativeBinariesExist();
18598
- if (!nativeAvailable) {
18599
- console.log("[ast-grep] Native binaries not found, using CLI mode");
18600
- nativeChecked = true;
18601
- return;
18602
- }
18603
- if (astGrepInitPromise !== null) {
18604
- await astGrepInitPromise;
18605
- return;
18606
- }
18607
- astGrepInitPromise = (async () => {
18608
- try {
18609
- astGrepModule = await import("@ast-grep/napi");
18610
- console.log("[ast-grep] Native NAPI initialized successfully");
18611
- nativeAvailable = true;
18612
- } catch (error45) {
18613
- console.warn("[ast-grep] Failed to load @ast-grep/napi, falling back to CLI:", error45 instanceof Error ? error45.message : error45);
18614
- astGrepModule = null;
18615
- nativeAvailable = false;
18616
- } finally {
18617
- nativeChecked = true;
18618
- }
18619
- })();
18620
- await astGrepInitPromise;
18621
- }
18622
- async function getAstGrepStatus() {
18623
- await initAstGrep();
18624
- if (nativeAvailable && astGrepModule) {
18625
- try {
18626
- const pkg = await import("@ast-grep/napi/package.json", { assert: { type: "json" } });
18627
- return {
18628
- available: true,
18629
- mode: "native",
18630
- version: pkg.default.version || "unknown"
18631
- };
18632
- } catch {
18633
- return { available: true, mode: "native", version: "unknown" };
18634
- }
18635
- }
18636
- const cliAvailable = await checkCliAvailable();
18637
- return {
18638
- available: cliAvailable,
18639
- mode: cliAvailable ? "cli" : "unavailable"
18640
- };
18641
- }
18642
- async function checkCliAvailable() {
18643
- return new Promise((resolve) => {
18644
- const proc = spawn2("npx", ["-y", "@notprolands/ast-grep-mcp", "--help"], {
18645
- timeout: 3000,
18646
- shell: true
18647
- });
18648
- proc.on("close", (code) => {
18649
- resolve(code === 0);
18650
- });
18651
- proc.on("error", () => {
18652
- resolve(false);
18653
- });
18654
- setTimeout(() => {
18655
- try {
18656
- proc.kill();
18657
- } catch {}
18658
- resolve(false);
18659
- }, 3000);
18660
- });
18661
- }
18662
- var astGrepDumpSyntaxTreeTool = tool({
18663
- description: `Dump code's syntax structure or dump a query's pattern structure.
18664
-
18665
- This is useful to discover correct syntax kind and syntax tree structure. Call it when debugging a rule.
18666
-
18667
- **Parameters:**
18668
- - code: The code you need
18669
- - language: Programming language (typescript, javascript, python, rust, go, java, etc.)
18670
- - format: Output format - 'cst' (concrete syntax tree) or 'pattern' (to inspect rule patterns)
18671
-
18672
- **Use when:**
18673
- - Debugging AST patterns
18674
- - Finding correct syntax kind names
18675
- - Understanding code structure`,
18676
- args: {
18677
- code: tool.schema.string().describe("The code to analyze"),
18678
- language: tool.schema.string().describe("Programming language (typescript, javascript, python, rust, go, java, etc.)"),
18679
- format: tool.schema.enum(["cst", "pattern"]).default("cst").describe("Output format")
18680
- },
18681
- async execute({ code, language, format }) {
18682
- await initAstGrep();
18683
- if (nativeAvailable && astGrepModule) {
18684
- try {
18685
- return executeNativeDump(code, language, format, astGrepModule);
18686
- } catch (error45) {
18687
- console.warn("[ast-grep] Native failed, trying CLI:", error45 instanceof Error ? error45.message : error45);
18688
- }
18689
- }
18690
- return JSON.stringify({
18691
- success: true,
18692
- mode: "cli",
18693
- message: "CLI mode - limited functionality. Install @ast-grep/napi for full native support.",
18694
- suggestion: "Run: npm install @ast-grep/napi",
18695
- format,
18696
- language,
18697
- example: {
18698
- cst: "Use ast_grep MCP tool via ast_grep_search for pattern matching"
18699
- }
18700
- }, null, 2);
18701
- }
18702
- });
18703
- function executeNativeDump(code, language, format, mod) {
18704
- const langMap = {
18705
- typescript: "TypeScript",
18706
- javascript: "JavaScript",
18707
- tsx: "Tsx",
18708
- jsx: "Jsx",
18709
- python: "Python",
18710
- rust: "Rust",
18711
- go: "Go",
18712
- java: "Java"
18713
- };
18714
- const lang = langMap[language.toLowerCase()] || language;
18715
- const Lang = mod.Lang;
18716
- if (!Lang || !Lang[lang]) {
18717
- return JSON.stringify({
18718
- success: false,
18719
- error: `Unsupported language: ${language}`,
18720
- availableLanguages: Object.keys(langMap)
18721
- }, null, 2);
18722
- }
18723
- if (format === "pattern") {
18724
- return JSON.stringify({
18725
- success: true,
18726
- format: "pattern",
18727
- language,
18728
- example: {
18729
- match: "AwaitExpression",
18730
- kind: "Use kind to match AST node types",
18731
- pattern: "Use pattern for code templates"
18732
- }
18733
- }, null, 2);
18734
- }
18735
- const parse5 = mod.parse;
18736
- const ast = parse5(Lang[lang], code);
18737
- const root = ast.root();
18738
- const dump = (node) => {
18739
- if (!node)
18740
- return null;
18741
- return {
18742
- kind: node.kind(),
18743
- text: node.text(),
18744
- children: node.children().map((child) => dump(child))
18745
- };
18746
- };
18747
- return JSON.stringify({
18748
- success: true,
18749
- format: "cst",
18750
- mode: "native",
18751
- language,
18752
- tree: dump(root)
18753
- }, null, 2);
18754
- }
18755
- var astGrepTestMatchCodeRuleTool = tool({
18756
- description: `Test a code against an ast-grep YAML rule.
18757
-
18758
- This is useful to test a rule before using it in a project.
18759
-
18760
- **Parameters:**
18761
- - code: The code to test against the rule
18762
- - yaml: The ast-grep YAML rule to test`,
18763
- args: {
18764
- code: tool.schema.string().describe("The code to test against the rule"),
18765
- yaml: tool.schema.string().describe("The ast-grep YAML rule to search")
18766
- },
18767
- async execute({ code, yaml }) {
18768
- await initAstGrep();
18769
- if (nativeAvailable && astGrepModule) {
18770
- try {
18771
- const parse5 = astGrepModule.parse;
18772
- const Lang = astGrepModule.Lang;
18773
- parse5(Lang.TypeScript, code);
18774
- return JSON.stringify({
18775
- success: true,
18776
- mode: "native",
18777
- matched: false,
18778
- note: "YAML rule testing works best with ast_grep MCP tool"
18779
- }, null, 2);
18780
- } catch (error45) {}
18781
- }
18782
- return JSON.stringify({
18783
- success: true,
18784
- mode: "cli",
18785
- note: "Use ast_grep MCP tool (ast_grep_search) for YAML rule testing"
18786
- }, null, 2);
18787
- }
18788
- });
18789
- var astGrepFindCodeTool = tool({
18790
- description: `Find code in a project folder that matches the given ast-grep pattern.
18791
-
18792
- **Parameters:**
18793
- - project_folder: The absolute path to the project folder
18794
- - pattern: The ast-grep pattern to search for
18795
- - language: Optional - programming language filter`,
18796
- args: {
18797
- project_folder: tool.schema.string().describe("The absolute path to the project folder"),
18798
- pattern: tool.schema.string().describe("The ast-grep pattern to search for"),
18799
- language: tool.schema.string().optional().describe("Programming language filter")
18800
- },
18801
- async execute({ project_folder, pattern, language }) {
18802
- await initAstGrep();
18803
- if (!fs7.existsSync(project_folder)) {
18804
- return JSON.stringify({
18805
- success: false,
18806
- error: `Path not found: ${project_folder}`
18807
- }, null, 2);
18808
- }
18809
- if (nativeAvailable && astGrepModule) {
18810
- try {
18811
- return executeNativeFind(project_folder, pattern, language, astGrepModule);
18812
- } catch (error45) {
18813
- console.warn("[ast-grep] Native find failed:", error45 instanceof Error ? error45.message : error45);
18814
- }
18815
- }
18816
- const lang = language || "typescript";
18817
- return JSON.stringify({
18818
- success: true,
18819
- mode: "cli",
18820
- message: "CLI mode active - for best results, use ast_grep MCP tool",
18821
- suggestion: "Use ast_grep MCP with ast_grep_search for pattern matching",
18822
- parameters: {
18823
- projectFolder: project_folder,
18824
- pattern,
18825
- language: lang
18826
- }
18827
- }, null, 2);
18828
- }
18829
- });
18830
- function executeNativeFind(project_folder, pattern, language, mod) {
18831
- const langMap = {
18832
- typescript: "TypeScript",
18833
- javascript: "JavaScript",
18834
- tsx: "Tsx",
18835
- jsx: "Jsx",
18836
- python: "Python",
18837
- rust: "Rust",
18838
- go: "Go",
18839
- java: "Java"
18840
- };
18841
- const lang = language ? langMap[language.toLowerCase()] || language : "TypeScript";
18842
- const Lang = mod.Lang;
18843
- if (!Lang[lang]) {
18844
- return JSON.stringify({
18845
- success: false,
18846
- error: `Unsupported language: ${language}`
18847
- }, null, 2);
18848
- }
18849
- const findInFiles = mod.findInFiles;
18850
- const results = [];
18851
- return JSON.stringify({
18852
- success: true,
18853
- mode: "native",
18854
- count: results.length,
18855
- message: "Native find - see ast_grep MCP for full pattern matching"
18856
- }, null, 2);
18857
- }
18858
- var astGrepScanCodeTool = tool({
18859
- description: `Analyze TypeScript/JS code for common bugs, performance issues and best practices.
18860
-
18861
- **Parameters:**
18862
- - project_folder: Optional - path to scan (defaults to current directory)`,
18863
- args: {
18864
- project_folder: tool.schema.string().optional().describe("Path to scan")
18865
- },
18866
- async execute({ project_folder }) {
18867
- await initAstGrep();
18868
- const scanPath = project_folder || process.cwd();
18869
- if (!fs7.existsSync(scanPath)) {
18870
- return JSON.stringify({
18871
- success: false,
18872
- error: `Path not found: ${scanPath}`
18873
- }, null, 2);
18874
- }
18875
- const status = await getAstGrepStatus();
18876
- return JSON.stringify({
18877
- success: true,
18878
- scanned: scanPath,
18879
- mode: status.mode,
18880
- message: status.mode === "native" ? "Scan complete - no issues found" : "CLI mode - for full scan, install @ast-grep/napi or use ast_grep MCP"
18881
- }, null, 2);
18882
- }
18883
- });
18884
- var astGrepRewriteCodeTool = tool({
18885
- description: `Transform and refactor code using AST-based find-and-replace patterns.
18886
-
18887
- **Parameters:**
18888
- - project_folder: Path to the project folder
18889
- - pattern: AST pattern to find
18890
- - replacement: Replacement pattern
18891
- - language: Programming language`,
18892
- args: {
18893
- project_folder: tool.schema.string().describe("Path to the project folder"),
18894
- pattern: tool.schema.string().describe("AST pattern to find"),
18895
- replacement: tool.schema.string().describe("Replacement pattern"),
18896
- language: tool.schema.string().optional().default("TypeScript").describe("Programming language")
18897
- },
18898
- async execute({ project_folder, pattern, replacement, language }) {
18899
- await initAstGrep();
18900
- return JSON.stringify({
18901
- success: true,
18902
- message: "Full rewrite requires @ast-grep/cli with config file",
18903
- suggestion: "Use ast_grep MCP tool for search, then hive_code_edit for replacements",
18904
- parameters: { project_folder, pattern, replacement, language }
18905
- }, null, 2);
18906
- }
18907
- });
18908
- var astGrepAnalyzeImportsTool = tool({
18909
- description: `Analyze import statements and dependencies in your codebase.
18910
-
18911
- **Parameters:**
18912
- - mode: "usage" or "discovery"
18913
- - path: Directory or file to analyze`,
18914
- args: {
18915
- mode: tool.schema.enum(["usage", "discovery"]).default("usage").describe("Analysis mode"),
18916
- path: tool.schema.string().optional().describe("Directory or file to analyze")
18917
- },
18918
- async execute({ mode, path: path7 }) {
18919
- await initAstGrep();
18920
- const analyzePath = path7 || process.cwd();
18921
- if (!fs7.existsSync(analyzePath)) {
18922
- return JSON.stringify({
18923
- success: false,
18924
- error: `Path not found: ${analyzePath}`
18925
- }, null, 2);
18926
- }
18927
- const status = await getAstGrepStatus();
18928
- return JSON.stringify({
18929
- success: true,
18930
- mode: status.mode,
18931
- path: analyzePath,
18932
- message: status.mode === "native" ? "Import analysis complete" : "CLI mode - for full analysis, use ast_grep MCP or install @ast-grep/napi"
18933
- }, null, 2);
18934
- }
18935
- });
18936
-
18937
18516
  // src/agents/hive.ts
18938
18517
  var QUEEN_BEE_PROMPT = `# Zetta (Hybrid)
18939
18518
 
@@ -20273,20 +19852,13 @@ var veilMcp = {
20273
19852
  command: ["npx", "-y", "@ushiradineth/veil@latest", "mcp", "server"]
20274
19853
  };
20275
19854
 
20276
- // src/mcp/ast-grep.ts
20277
- var astGrepMcp = {
20278
- type: "local",
20279
- command: ["npx", "-y", "@notprolands/ast-grep-mcp"]
20280
- };
20281
-
20282
19855
  // src/mcp/index.ts
20283
19856
  var allBuiltinMcps = {
20284
19857
  websearch: websearchMcp,
20285
19858
  context7: context7Mcp,
20286
19859
  grep_app: grepAppMcp,
20287
19860
  pare_search: pareSearchMcp,
20288
- veil: veilMcp,
20289
- ast_grep: astGrepMcp
19861
+ veil: veilMcp
20290
19862
  };
20291
19863
  var createBuiltinMcps = (disabledMcps = []) => {
20292
19864
  const disabled = new Set(disabledMcps);
@@ -20298,7 +19870,7 @@ import { createRequire as createRequire2 } from "node:module";
20298
19870
  import * as path7 from "path";
20299
19871
  import * as os3 from "os";
20300
19872
  import * as path22 from "path";
20301
- import * as fs8 from "fs";
19873
+ import * as fs7 from "fs";
20302
19874
  import * as path32 from "path";
20303
19875
  import * as fs22 from "fs";
20304
19876
  import * as fs32 from "fs";
@@ -20307,10 +19879,10 @@ import * as fs52 from "fs";
20307
19879
  import * as fs72 from "fs/promises";
20308
19880
  import * as path42 from "path";
20309
19881
  import { Buffer as Buffer2 } from "node:buffer";
20310
- import { spawn as spawn3 } from "child_process";
19882
+ import { spawn as spawn2 } from "child_process";
20311
19883
  import { normalize } from "node:path";
20312
19884
  import { EventEmitter } from "node:events";
20313
- import * as fs82 from "fs";
19885
+ import * as fs8 from "fs";
20314
19886
  import * as path52 from "path";
20315
19887
  import * as fs10 from "fs";
20316
19888
  import * as path72 from "path";
@@ -21244,22 +20816,22 @@ function getSubtaskReportPath(projectRoot, featureName, taskFolder, subtaskFolde
21244
20816
  return path22.join(getSubtaskPath(projectRoot, featureName, taskFolder, subtaskFolder), REPORT_FILE);
21245
20817
  }
21246
20818
  function ensureDir(dirPath) {
21247
- if (!fs8.existsSync(dirPath)) {
21248
- fs8.mkdirSync(dirPath, { recursive: true });
20819
+ if (!fs7.existsSync(dirPath)) {
20820
+ fs7.mkdirSync(dirPath, { recursive: true });
21249
20821
  }
21250
20822
  }
21251
20823
  function fileExists(filePath) {
21252
- return fs8.existsSync(filePath);
20824
+ return fs7.existsSync(filePath);
21253
20825
  }
21254
20826
  function readJson(filePath) {
21255
- if (!fs8.existsSync(filePath))
20827
+ if (!fs7.existsSync(filePath))
21256
20828
  return null;
21257
- const content = fs8.readFileSync(filePath, "utf-8");
20829
+ const content = fs7.readFileSync(filePath, "utf-8");
21258
20830
  return JSON.parse(content);
21259
20831
  }
21260
20832
  function writeJson(filePath, data) {
21261
20833
  ensureDir(path22.dirname(filePath));
21262
- fs8.writeFileSync(filePath, JSON.stringify(data, null, 2));
20834
+ fs7.writeFileSync(filePath, JSON.stringify(data, null, 2));
21263
20835
  }
21264
20836
  var DEFAULT_LOCK_OPTIONS = {
21265
20837
  timeout: 5000,
@@ -21271,7 +20843,7 @@ function getLockPath(filePath) {
21271
20843
  }
21272
20844
  function isLockStale(lockPath, staleTTL) {
21273
20845
  try {
21274
- const stat2 = fs8.statSync(lockPath);
20846
+ const stat2 = fs7.statSync(lockPath);
21275
20847
  const age = Date.now() - stat2.mtimeMs;
21276
20848
  return age > staleTTL;
21277
20849
  } catch {
@@ -21291,12 +20863,12 @@ function acquireLockSync(filePath, options = {}) {
21291
20863
  ensureDir(lockDir);
21292
20864
  while (true) {
21293
20865
  try {
21294
- const fd = fs8.openSync(lockPath, fs8.constants.O_CREAT | fs8.constants.O_EXCL | fs8.constants.O_WRONLY);
21295
- fs8.writeSync(fd, lockContent);
21296
- fs8.closeSync(fd);
20866
+ const fd = fs7.openSync(lockPath, fs7.constants.O_CREAT | fs7.constants.O_EXCL | fs7.constants.O_WRONLY);
20867
+ fs7.writeSync(fd, lockContent);
20868
+ fs7.closeSync(fd);
21297
20869
  return () => {
21298
20870
  try {
21299
- fs8.unlinkSync(lockPath);
20871
+ fs7.unlinkSync(lockPath);
21300
20872
  } catch {}
21301
20873
  };
21302
20874
  } catch (err) {
@@ -21306,7 +20878,7 @@ function acquireLockSync(filePath, options = {}) {
21306
20878
  } else if (error45.code === "EEXIST") {
21307
20879
  if (isLockStale(lockPath, opts.staleLockTTL)) {
21308
20880
  try {
21309
- fs8.unlinkSync(lockPath);
20881
+ fs7.unlinkSync(lockPath);
21310
20882
  continue;
21311
20883
  } catch {}
21312
20884
  }
@@ -21325,11 +20897,11 @@ function writeAtomic(filePath, content) {
21325
20897
  ensureDir(path22.dirname(filePath));
21326
20898
  const tempPath = `${filePath}.tmp.${process.pid}.${Date.now()}`;
21327
20899
  try {
21328
- fs8.writeFileSync(tempPath, content);
21329
- fs8.renameSync(tempPath, filePath);
20900
+ fs7.writeFileSync(tempPath, content);
20901
+ fs7.renameSync(tempPath, filePath);
21330
20902
  } catch (error45) {
21331
20903
  try {
21332
- fs8.unlinkSync(tempPath);
20904
+ fs7.unlinkSync(tempPath);
21333
20905
  } catch {}
21334
20906
  throw error45;
21335
20907
  }
@@ -21364,13 +20936,13 @@ function patchJsonLockedSync(filePath, patch, options = {}) {
21364
20936
  }
21365
20937
  }
21366
20938
  function readText(filePath) {
21367
- if (!fs8.existsSync(filePath))
20939
+ if (!fs7.existsSync(filePath))
21368
20940
  return null;
21369
- return fs8.readFileSync(filePath, "utf-8");
20941
+ return fs7.readFileSync(filePath, "utf-8");
21370
20942
  }
21371
20943
  function writeText(filePath, content) {
21372
20944
  ensureDir(path22.dirname(filePath));
21373
- fs8.writeFileSync(filePath, content);
20945
+ fs7.writeFileSync(filePath, content);
21374
20946
  }
21375
20947
  function detectContext(cwd) {
21376
20948
  const result = {
@@ -23461,7 +23033,7 @@ var init_git_executor_chain = __esm2({
23461
23033
  rejection = reason || rejection;
23462
23034
  }
23463
23035
  });
23464
- const spawned = spawn3(command, args2, spawnOptions);
23036
+ const spawned = spawn2(command, args2, spawnOptions);
23465
23037
  spawned.stdout.on("data", onDataReceived(stdOut, "stdOut", logger, outputLogger.step("stdOut")));
23466
23038
  spawned.stderr.on("data", onDataReceived(stdErr, "stdErr", logger, outputLogger.step("stdErr")));
23467
23039
  spawned.on("error", onErrorReceived(stdErr, logger));
@@ -26655,10 +26227,10 @@ class ContextService {
26655
26227
  const contextPath = getContextPath(this.projectRoot, featureName);
26656
26228
  if (!fileExists(contextPath))
26657
26229
  return [];
26658
- const files = fs82.readdirSync(contextPath, { withFileTypes: true }).filter((f) => f.isFile() && f.name.endsWith(".md")).map((f) => f.name);
26230
+ const files = fs8.readdirSync(contextPath, { withFileTypes: true }).filter((f) => f.isFile() && f.name.endsWith(".md")).map((f) => f.name);
26659
26231
  return files.map((name) => {
26660
26232
  const filePath = path52.join(contextPath, name);
26661
- const stat2 = fs82.statSync(filePath);
26233
+ const stat2 = fs8.statSync(filePath);
26662
26234
  const content = readText(filePath) || "";
26663
26235
  return {
26664
26236
  name: name.replace(/\.md$/, ""),
@@ -26671,7 +26243,7 @@ class ContextService {
26671
26243
  const contextPath = getContextPath(this.projectRoot, featureName);
26672
26244
  const filePath = path52.join(contextPath, this.normalizeFileName(fileName));
26673
26245
  if (fileExists(filePath)) {
26674
- fs82.unlinkSync(filePath);
26246
+ fs8.unlinkSync(filePath);
26675
26247
  return true;
26676
26248
  }
26677
26249
  return false;
@@ -26702,8 +26274,8 @@ ${f.content}`);
26702
26274
  const archiveName = `${timestamp}_${ctx.name}.md`;
26703
26275
  const src = path52.join(contextPath, `${ctx.name}.md`);
26704
26276
  const dest = path52.join(archiveDir, archiveName);
26705
- fs82.copyFileSync(src, dest);
26706
- fs82.unlinkSync(src);
26277
+ fs8.copyFileSync(src, dest);
26278
+ fs8.unlinkSync(src);
26707
26279
  archived.push(ctx.name);
26708
26280
  }
26709
26281
  return { archived, archivePath: archiveDir };
@@ -28565,12 +28137,6 @@ ${snapshot}
28565
28137
  auto_cr_scan: autoCrScanTool,
28566
28138
  auto_cr_diff: autoCrDiffTool,
28567
28139
  auto_cr_rules: autoCrRulesTool,
28568
- ast_grep_dump_syntax_tree: astGrepDumpSyntaxTreeTool,
28569
- ast_grep_test_match_code_rule: astGrepTestMatchCodeRuleTool,
28570
- ast_grep_find_code: astGrepFindCodeTool,
28571
- ast_grep_scan_code: astGrepScanCodeTool,
28572
- ast_grep_rewrite_code: astGrepRewriteCodeTool,
28573
- ast_grep_analyze_imports: astGrepAnalyzeImportsTool,
28574
28140
  hive_skill: createHiveSkillTool(filteredSkills),
28575
28141
  hive_feature_create: tool({
28576
28142
  description: "Create a new feature and set it as active",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hung319/opencode-hive",
3
- "version": "1.5.9",
3
+ "version": "1.6.0",
4
4
  "type": "module",
5
5
  "description": "OpenCode plugin for Agent Hive - from vibe coding to hive coding",
6
6
  "license": "MIT WITH Commons-Clause",
@@ -31,7 +31,7 @@
31
31
  "scripts": {
32
32
  "clean": "rm -rf dist",
33
33
  "generate-skills": "bun run scripts/generate-skills.ts",
34
- "build": "npm run clean && npm run generate-skills && bun build src/index.ts --outdir dist --target node --format esm --packages=bundle --external @ast-grep/napi && tsc --emitDeclarationOnly",
34
+ "build": "npm run clean && npm run generate-skills && bun build src/index.ts --outdir dist --target node --format esm --packages=bundle && tsc --emitDeclarationOnly",
35
35
  "dev": "opencode plugin dev",
36
36
  "test": "bun test"
37
37
  },
@@ -39,12 +39,10 @@
39
39
  "@opencode-ai/plugin": ">=0.13.7"
40
40
  },
41
41
  "dependencies": {
42
- "@ast-grep/napi": "^0.41.1",
43
42
  "simple-git": "^3.27.0"
44
43
  },
45
44
  "optionalDependencies": {
46
45
  "grep-mcp": "^1.1.0",
47
- "@notprolands/ast-grep-mcp": "^1.1.1",
48
46
  "@upstash/context7-mcp": "^2.1.0",
49
47
  "exa-mcp-server": "^3.1.5",
50
48
  "@sparkleideas/agent-booster": "^0.2.3",
@@ -1,7 +0,0 @@
1
- import type { LocalMcpConfig } from './types';
2
- /**
3
- * Ast-grep MCP for code analysis
4
- *
5
- * Uses local npx execution (remote endpoint mcp.ast-grep.dev is unavailable)
6
- */
7
- export declare const astGrepMcp: LocalMcpConfig;
@@ -1,19 +0,0 @@
1
- import { type ToolDefinition } from "@opencode-ai/plugin";
2
- /**
3
- * Check if native ast-grep is available
4
- */
5
- export declare function isAstGrepAvailable(): Promise<boolean>;
6
- /**
7
- * Get ast-grep status
8
- */
9
- export declare function getAstGrepStatus(): Promise<{
10
- available: boolean;
11
- mode: 'native' | 'cli' | 'unavailable';
12
- version?: string;
13
- }>;
14
- export declare const astGrepDumpSyntaxTreeTool: ToolDefinition;
15
- export declare const astGrepTestMatchCodeRuleTool: ToolDefinition;
16
- export declare const astGrepFindCodeTool: ToolDefinition;
17
- export declare const astGrepScanCodeTool: ToolDefinition;
18
- export declare const astGrepRewriteCodeTool: ToolDefinition;
19
- export declare const astGrepAnalyzeImportsTool: ToolDefinition;