@hung319/opencode-hive 1.6.3 → 1.6.5

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.
Files changed (4) hide show
  1. package/README.md +88 -39
  2. package/bin/doctor.ts +231 -195
  3. package/dist/index.js +81 -139
  4. package/package.json +1 -1
package/README.md CHANGED
@@ -540,58 +540,107 @@ hive_doctor_quick()
540
540
 
541
541
  **Standalone (before installing):**
542
542
  ```bash
543
- bunx @hung319/opencode-hive doctor
543
+ bunx @hung319/opencode-hive doctor # Check system
544
+ bunx @hung319/opencode-hive doctor --fix # Auto-fix issues
544
545
  ```
545
546
 
546
547
  ### What it checks
547
548
 
548
- 1. **Dependencies** - npm packages installed?
549
- - Core: `@ast-grep/napi`
550
- - Agent: `@sparkleideas/agent-booster`, `@sparkleideas/memory`
551
- - MCPs: `@paretools/search`, `@upstash/context7-mcp`, `exa-mcp-server`, `grep-mcp`
552
- - Blockchain: `btca`, `opencode-model-selector`
549
+ 1. **Agent Tools** (optional)
550
+ - `@sparkleideas/agent-booster` - 52x faster code editing
551
+ - `@sparkleideas/memory` - Vector memory for semantic search
553
552
 
554
- 2. **CLI Tools** - npx tools available?
553
+ 2. **CLI Tools** (optional)
555
554
  - `dora` - Code navigation (SCIP-based)
556
555
  - `auto-cr` - Automated code review (SWC)
557
556
  - `scip-typescript` - TypeScript indexer
558
557
  - `veil` - Code discovery
559
- - `btca` - BTC/A blockchain agent (from npmx.dev)
558
+ - `btca` - BTC/A blockchain agent
559
+
560
+ 3. **MCPs** - Auto-installed with plugin
561
+ - websearch, context7, grep_app
562
+ - pare_search, veil
560
563
 
561
- 3. **Config** - Features enabled?
562
- - snip, vectorMemory, agentBooster
563
- - sandbox mode
564
- - MCPs: veil, pare_search
564
+ 4. **C++20 Tip** - For @ast-grep/napi native modules
565
565
 
566
566
  ### Example Output
567
567
 
568
- ```json
569
- {
570
- "status": "warning",
571
- "summary": {
572
- "dependencies": "⚠️ 2 missing: agent-booster, memory",
573
- "cliTools": "⚠️ 1 missing: auto-cr",
574
- "config": "💡 2 disabled: snip, vectorMemory"
575
- },
576
- "actionItems": [
577
- {
578
- "priority": "high",
579
- "action": "Install auto-cr",
580
- "command": "npx -y auto-cr-cmd",
581
- "reason": "SWC-based automated code review"
582
- },
583
- {
584
- "priority": "medium",
585
- "action": "Install agent-booster",
586
- "command": "npm install @sparkleideas/agent-booster",
587
- "reason": "52x faster code editing"
588
- }
589
- ],
590
- "quickInstall": {
591
- "deps": ["@sparkleideas/agent-booster", "@sparkleideas/memory"],
592
- "cliTools": ["auto-cr-cmd"]
593
- }
594
- }
568
+ ```
569
+ ╔═══════════════════════════════════════════════════════════╗
570
+ ║ 🐝 Hive Doctor v1.6.5 - System Check ║
571
+ ╚═══════════════════════════════════════════════════════════╝
572
+
573
+ Status: ⚠️ NEEDS SETUP
574
+
575
+ 🚀 Agent Tools (0/2)
576
+ @sparkleideas/agent-booster not installed
577
+ ○ @sparkleideas/memory not installed
578
+
579
+ 🔧 CLI Tools (4/5)
580
+ dora (via npx)
581
+ auto-cr (check) installed
582
+ ...
583
+
584
+ 📦 MCPs: Auto-installed with plugin
585
+
586
+ C++20 for native modules:
587
+ Already configured
588
+
589
+ 🚀 Quick Install
590
+
591
+ npm install @sparkleideas/agent-booster
592
+ ```
593
+
594
+ ### Auto-fix Mode
595
+
596
+ ```bash
597
+ bunx @hung319/opencode-hive doctor --fix
598
+ ```
599
+
600
+ This will:
601
+ 1. Set CXXFLAGS for current session
602
+ 2. Add to ~/.bashrc for future sessions
603
+ 3. Install available CLI tools via npx
604
+
605
+ ### C++20 for Native Modules
606
+
607
+ Node.js v24+ requires C++20 for native modules like `@ast-grep/napi`.
608
+
609
+ **Auto-fix:**
610
+ ```bash
611
+ bunx @hung319/opencode-hive doctor --fix
612
+ ```
613
+
614
+ **Manual:**
615
+ ```bash
616
+ echo 'export CXXFLAGS="-std=c++20"' >> ~/.bashrc
617
+ source ~/.bashrc
618
+ CXXFLAGS="-std=c++20" npm install @ast-grep/napi
619
+ ```
620
+ ╔═══════════════════════════════════════════════════════════╗
621
+ ║ 🐝 Hive Doctor v1.6.3 - System Check ║
622
+ ╚═══════════════════════════════════════════════════════════╝
623
+
624
+ Status: ⚠️ NEEDS SETUP
625
+
626
+ 🚀 Agent Tools (0/2)
627
+ ○ @sparkleideas/agent-booster not installed
628
+ ○ @sparkleideas/memory not installed
629
+
630
+ 🔧 CLI Tools (1/5)
631
+ ✅ dora (via npx)
632
+ ○ auto-cr not available
633
+ ...
634
+
635
+ 📦 MCPs: Auto-installed with plugin
636
+
637
+ 💡 Tip: Enable C++20 for native modules?
638
+ Not detected. Run to fix @ast-grep/napi build:
639
+ echo 'export CXXFLAGS="-std=c++20"' >> ~/.bashrc
640
+
641
+ 🚀 Quick Install
642
+
643
+ npx -y auto-cr-cmd && npm install @sparkleideas/agent-booster
595
644
  ```
596
645
 
597
646
  ### Setup Workflow
package/bin/doctor.ts CHANGED
@@ -8,10 +8,8 @@
8
8
  * bunx @hung319/opencode-hive doctor
9
9
  * npx @hung319/opencode-hive doctor
10
10
  *
11
- * Or install and run:
12
- *
13
- * npm install @hung319/opencode-hive
14
- * hive_doctor() // via OpenCode
11
+ * Auto-fix issues:
12
+ * bunx @hung319/opencode-hive doctor --fix
15
13
  */
16
14
 
17
15
  import { execSync } from 'child_process';
@@ -26,7 +24,6 @@ interface CheckResult {
26
24
  name: string;
27
25
  installed: boolean;
28
26
  version?: string;
29
- reason?: string;
30
27
  }
31
28
 
32
29
  interface CliCheck {
@@ -46,7 +43,7 @@ interface DoctorOutput {
46
43
  packageManager: string;
47
44
  };
48
45
  checks: {
49
- dependencies: {
46
+ agentTools: {
50
47
  total: number;
51
48
  installed: number;
52
49
  items: CheckResult[];
@@ -56,26 +53,15 @@ interface DoctorOutput {
56
53
  available: number;
57
54
  items: CliCheck[];
58
55
  };
59
- nativeBinaries: {
60
- status: 'native' | 'cli-mode';
61
- reason?: string;
62
- };
63
- config: {
64
- exists: boolean;
65
- path?: string;
66
- optimizations: string[];
67
- };
68
56
  };
69
57
  actionItems: {
70
- priority: 'critical' | 'high' | 'medium' | 'low';
58
+ priority: 'high' | 'medium' | 'low';
71
59
  action: string;
72
60
  command?: string;
73
61
  reason: string;
74
62
  }[];
75
- installCommands: {
76
- deps: string;
77
- cliTools: string;
78
- };
63
+ quickInstall: string;
64
+ cxxflagsStatus: 'set' | 'not-set' | 'auto-fixed';
79
65
  }
80
66
 
81
67
  // ============================================================================
@@ -91,6 +77,18 @@ const colors = {
91
77
  gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
92
78
  };
93
79
 
80
+ const noColors = {
81
+ green: (text: string) => text,
82
+ yellow: (text: string) => text,
83
+ red: (text: string) => text,
84
+ blue: (text: string) => text,
85
+ cyan: (text: string) => text,
86
+ gray: (text: string) => text,
87
+ };
88
+
89
+ const isTTY = process.stdout.isTTY;
90
+ const c = isTTY ? colors : noColors;
91
+
94
92
  // ============================================================================
95
93
  // Check functions
96
94
  // ============================================================================
@@ -132,19 +130,19 @@ function checkNpmPackage(name: string): CheckResult {
132
130
 
133
131
  function checkCliTool(name: string, command: string, description: string): CliCheck {
134
132
  const result: CliCheck = { name, command, installed: false, description };
133
+ const cmdName = command.split(' ')[0];
135
134
 
136
- // Try direct command
135
+ // Try direct command with --help (some binaries don't have --version)
137
136
  try {
138
- const cmd = command.split(' ')[0];
139
- execSync(cmd, { stdio: 'ignore', timeout: 3000 });
137
+ execSync(cmdName, { stdio: 'ignore', timeout: 3000 });
140
138
  result.installed = true;
141
139
  result.version = 'installed';
142
140
  return result;
143
141
  } catch {}
144
142
 
145
- // Try npx
143
+ // Try npx with --help
146
144
  try {
147
- execSync(`npx -y ${command.split(' ')[0]} --version`, {
145
+ execSync(`npx -y ${cmdName} --help`, {
148
146
  stdio: 'ignore',
149
147
  timeout: 10000
150
148
  });
@@ -153,172 +151,230 @@ function checkCliTool(name: string, command: string, description: string): CliCh
153
151
  return result;
154
152
  } catch {}
155
153
 
154
+ // Special case for auto-cr: binary is "check", not "auto-cr"
155
+ if (name === 'auto-cr') {
156
+ try {
157
+ execSync('check --help', { stdio: 'ignore', timeout: 3000 });
158
+ result.installed = true;
159
+ result.version = 'installed (check)';
160
+ return result;
161
+ } catch {}
162
+ }
163
+
156
164
  return result;
157
165
  }
158
166
 
159
- function checkAstGrepNative(): { status: 'native' | 'cli-mode'; reason?: string } {
160
- // Check if @ast-grep/napi package exists with native binaries
161
- const napiDirs = [
162
- path.join(process.cwd(), 'node_modules/@ast-grep/napi'),
163
- path.join(process.env.HOME || '', '.npm-global/lib/node_modules/@ast-grep/napi'),
167
+ // ============================================================================
168
+ // CXXFLAGS: Check and Auto-fix
169
+ // ============================================================================
170
+
171
+ function checkCxxFlags(): 'set' | 'not-set' {
172
+ const shellConfigs = [
173
+ path.join(process.env.HOME || '', '.bashrc'),
174
+ path.join(process.env.HOME || '', '.bash_profile'),
175
+ path.join(process.env.HOME || '', '.zshrc'),
176
+ path.join(process.env.HOME || '', '.profile'),
164
177
  ];
165
178
 
166
- for (const napiDir of napiDirs) {
167
- if (!fs.existsSync(napiDir)) continue;
168
-
169
- const binaryPaths = [
170
- path.join(napiDir, 'index.node'),
171
- path.join(napiDir, 'build/Release/ast_grep.node'),
172
- path.join(napiDir, 'dist/index.node'),
173
- ];
179
+ const pattern = 'CXXFLAGS="-std=c++20"';
180
+
181
+ for (const config of shellConfigs) {
182
+ if (fs.existsSync(config)) {
183
+ const content = fs.readFileSync(config, 'utf-8');
184
+ if (content.includes(pattern)) {
185
+ return 'set';
186
+ }
187
+ }
188
+ }
189
+
190
+ return 'not-set';
191
+ }
192
+
193
+ function autoFixCxxFlags(): boolean {
194
+ if (checkCxxFlags() === 'set') {
195
+ return true;
196
+ }
197
+
198
+ const bashrc = path.join(process.env.HOME || '', '.bashrc');
199
+ const exportLine = '\nexport CXXFLAGS="-std=c++20"\nexport CXXFLAGS="std=c++20"\n';
200
+ const comment = '\n# For tree-sitter native modules (e.g., @ast-grep/napi)\n';
201
+
202
+ try {
203
+ // Check if bashrc exists
204
+ if (!fs.existsSync(bashrc)) {
205
+ fs.writeFileSync(bashrc, '');
206
+ }
174
207
 
175
- const hasBinary = binaryPaths.some(p => fs.existsSync(p));
208
+ const content = fs.readFileSync(bashrc, 'utf-8');
176
209
 
177
- if (hasBinary) {
178
- return { status: 'native' };
210
+ // Check if already set
211
+ if (content.includes('CXXFLAGS')) {
212
+ return true;
179
213
  }
214
+
215
+ // Add to bashrc
216
+ fs.appendFileSync(bashrc, `${comment}${exportLine}`);
217
+ console.log(c.green(`✓ Added CXXFLAGS to ${bashrc}`));
218
+ return true;
219
+ } catch {
220
+ return false;
180
221
  }
181
-
182
- return {
183
- status: 'cli-mode',
184
- reason: 'Native binaries not found (tree-sitter compilation may have failed)'
185
- };
186
222
  }
187
223
 
188
- function checkConfig(): { exists: boolean; path?: string; optimizations: string[] } {
189
- const configPaths = [
190
- path.join(process.env.HOME || '', '.config/opencode/agent_hive.json'),
191
- path.join(process.env.HOME || '', '.config/opencode/agent_hive.jsonc'),
192
- ];
224
+ // ============================================================================
225
+ // Auto-set CXXFLAGS for current session
226
+ // ============================================================================
227
+
228
+ function setCxxFlagsForCurrentSession(): boolean {
229
+ try {
230
+ process.env.CXXFLAGS = '"-std=c++20"';
231
+ process.env.npm_config_cxxflags = '"-std=c++20"';
232
+ console.log(c.green('✓ CXXFLAGS set for current session'));
233
+ return true;
234
+ } catch {
235
+ return false;
236
+ }
237
+ }
238
+
239
+ // ============================================================================
240
+ // Auto-install CLI tools
241
+ // ============================================================================
242
+
243
+ function autoInstallCliTools(tools: CliCheck[]): { success: string[]; failed: string[] } {
244
+ const result = { success: [] as string[], failed: [] as string[] };
193
245
 
194
- for (const configPath of configPaths) {
195
- if (fs.existsSync(configPath)) {
196
- try {
197
- const content = fs.readFileSync(configPath, 'utf-8');
198
- const config = JSON.parse(content.replace(/\\/g, ''));
199
- const optimizations: string[] = [];
200
-
201
- if (config.snip?.enabled) optimizations.push('snip');
202
- if (config.vectorMemory?.enabled) optimizations.push('vectorMemory');
203
- if (config.agentBooster?.enabled !== false) optimizations.push('agentBooster');
204
- if (config.sandbox?.mode !== 'none') optimizations.push('sandbox');
205
-
206
- return { exists: true, path: configPath, optimizations };
207
- } catch {}
246
+ for (const tool of tools) {
247
+ if (tool.installed) continue;
248
+
249
+ try {
250
+ console.log(c.cyan(` Installing ${tool.name}...`));
251
+ execSync(`npx -y ${tool.command} --version`, {
252
+ stdio: 'ignore',
253
+ timeout: 60000
254
+ });
255
+ result.success.push(tool.name);
256
+ console.log(c.green(` ✓ ${tool.name} ready`));
257
+ } catch {
258
+ result.failed.push(tool.name);
259
+ console.log(c.red(` ✗ ${tool.name} failed`));
208
260
  }
209
261
  }
210
262
 
211
- return { exists: false, optimizations: [] };
263
+ return result;
212
264
  }
213
265
 
214
266
  // ============================================================================
215
267
  // Main check
216
268
  // ============================================================================
217
269
 
218
- function runDoctor(): DoctorOutput {
270
+ function runDoctor(autoFix = false): DoctorOutput {
219
271
  const output: DoctorOutput = {
220
272
  status: 'ready',
221
- version: '1.5.8',
273
+ version: '1.6.5',
222
274
  summary: getSystemInfo(),
223
275
  checks: {
224
- dependencies: { total: 0, installed: 0, items: [] },
276
+ agentTools: { total: 0, installed: 0, items: [] },
225
277
  cliTools: { total: 0, available: 0, items: [] },
226
- nativeBinaries: { status: 'cli-mode' },
227
- config: { exists: false, optimizations: [] },
228
278
  },
229
279
  actionItems: [],
230
- installCommands: { deps: '', cliTools: '' },
280
+ quickInstall: '',
281
+ cxxflagsStatus: checkCxxFlags(),
231
282
  };
232
283
 
233
- // Check dependencies
234
- const deps = [
235
- '@ast-grep/napi',
236
- '@sparkleideas/agent-booster',
237
- '@sparkleideas/memory',
238
- '@paretools/search',
239
- '@upstash/context7-mcp',
240
- 'exa-mcp-server',
241
- 'grep-mcp',
242
- 'btca',
243
- 'opencode-model-selector',
284
+ // Auto-fix CXXFLAGS if requested
285
+ if (autoFix) {
286
+ console.log(c.cyan('\n🔧 Auto-fixing...\n'));
287
+
288
+ // Set for current session
289
+ setCxxFlagsForCurrentSession();
290
+
291
+ // Add to shell config
292
+ if (output.cxxflagsStatus === 'not-set') {
293
+ autoFixCxxFlags();
294
+ output.cxxflagsStatus = 'auto-fixed';
295
+ }
296
+ }
297
+
298
+ // Check optional agent tools
299
+ const agentToolsList = [
300
+ { name: '@sparkleideas/agent-booster', desc: '52x faster code editing' },
301
+ { name: '@sparkleideas/memory', desc: 'Vector memory for semantic search' },
244
302
  ];
245
303
 
246
- output.checks.dependencies.items = deps.map(d => checkNpmPackage(d));
247
- output.checks.dependencies.total = deps.length;
248
- output.checks.dependencies.installed = output.checks.dependencies.items.filter(d => d.installed).length;
304
+ output.checks.agentTools.items = agentToolsList.map(t => checkNpmPackage(t.name));
305
+ output.checks.agentTools.total = agentToolsList.length;
306
+ output.checks.agentTools.installed = output.checks.agentTools.items.filter(t => t.installed).length;
249
307
 
250
308
  // Check CLI tools
251
- const cliTools = [
252
- { name: 'dora', command: '@butttons/dora', description: 'SCIP-based code navigation' },
253
- { name: 'auto-cr', command: 'auto-cr-cmd', description: 'SWC-based automated code review' },
254
- { name: 'veil', command: '@ushiradineth/veil', description: 'Code discovery and retrieval' },
255
- { name: 'scip-typescript', command: '@sourcegraph/scip-typescript', description: 'TypeScript SCIP indexer' },
256
- { name: 'btca', command: 'btca', description: 'BTC/A agent for blockchain tasks' },
309
+ const cliToolsList = [
310
+ { name: 'dora', command: '@butttons/dora', desc: 'SCIP-based code navigation' },
311
+ { name: 'auto-cr', command: 'auto-cr-cmd', desc: 'SWC-based code review' },
312
+ { name: 'scip-typescript', command: '@sourcegraph/scip-typescript', desc: 'TypeScript indexer' },
313
+ { name: 'veil', command: '@ushiradineth/veil', desc: 'Code discovery' },
314
+ { name: 'btca', command: 'btca', desc: 'BTC/A blockchain agent' },
257
315
  ];
258
316
 
259
- output.checks.cliTools.items = cliTools.map(t => checkCliTool(t.name, t.command, t.description));
260
- output.checks.cliTools.total = cliTools.length;
317
+ output.checks.cliTools.items = cliToolsList.map(t => checkCliTool(t.name, t.command, t.desc));
318
+ output.checks.cliTools.total = cliToolsList.length;
261
319
  output.checks.cliTools.available = output.checks.cliTools.items.filter(t => t.installed).length;
262
320
 
263
- // Check native binaries
264
- output.checks.nativeBinaries = checkAstGrepNative();
265
-
266
- // Check config
267
- output.checks.config = checkConfig();
268
-
269
321
  // Generate action items
270
- const missingDeps = output.checks.dependencies.items.filter(d => !d.installed);
271
322
  const missingTools = output.checks.cliTools.items.filter(t => !t.installed);
323
+ const missingAgent = output.checks.agentTools.items.filter(t => !t.installed);
272
324
 
273
325
  if (missingTools.length > 0) {
274
326
  output.actionItems.push({
275
327
  priority: 'high',
276
- action: `Install ${missingTools.length} CLI tool(s)`,
328
+ action: `Install CLI tools`,
277
329
  command: missingTools.map(t => `npx -y ${t.command}`).join(' && '),
278
- reason: 'CLI tools provide code navigation, review, and analysis features',
330
+ reason: 'CLI tools enhance code navigation and review',
279
331
  });
280
332
  }
281
333
 
282
- if (missingDeps.length > 0) {
283
- const important = missingDeps.filter(d =>
284
- ['@ast-grep/napi', '@notprolands/ast-grep-mcp', '@paretools/search'].includes(d.name)
285
- );
286
-
287
- if (important.length > 0) {
288
- output.actionItems.push({
289
- priority: 'medium',
290
- action: `Install ${important.length} important package(s)`,
291
- command: important.map(d => `npm install ${d.name}`).join(' && '),
292
- reason: 'These packages enable core functionality',
293
- });
294
- }
295
- }
296
-
297
- if (!output.checks.config.exists) {
334
+ if (missingAgent.length > 0) {
298
335
  output.actionItems.push({
299
- priority: 'low',
300
- action: 'Create config file',
301
- command: `mkdir -p ~/.config/opencode && cat > ~/.config/opencode/agent_hive.json << 'EOF'\n{\n "snip": { "enabled": true },\n "vectorMemory": { "enabled": true }\n}\nEOF`,
302
- reason: 'Enable optimizations for better performance',
336
+ priority: 'medium',
337
+ action: `Install agent tools`,
338
+ command: missingAgent.map(t => `npm install ${t.name}`).join(' && '),
339
+ reason: 'Agent tools provide faster editing and memory',
303
340
  });
304
341
  }
305
342
 
306
- // Generate install commands
307
- if (missingDeps.length > 0) {
308
- output.installCommands.deps = `npm install ${missingDeps.map(d => d.name).join(' ')}`;
343
+ // Generate quick install
344
+ const allCommands: string[] = [];
345
+ for (const tool of missingTools) {
346
+ allCommands.push(`npx -y ${tool.command}`);
309
347
  }
310
-
311
- if (missingTools.length > 0) {
312
- output.installCommands.cliTools = `npx -y ${missingTools.map(t => t.command.split(' ')[0]).join(' ')}`;
348
+ for (const agent of missingAgent) {
349
+ allCommands.push(`npm install ${agent.name}`);
313
350
  }
351
+ output.quickInstall = allCommands.join(' && ');
314
352
 
315
353
  // Determine status
316
- if (output.actionItems.some(a => a.priority === 'critical')) {
354
+ if (missingTools.length >= 3) {
317
355
  output.status = 'action-required';
318
- } else if (output.actionItems.some(a => a.priority === 'high' || a.priority === 'medium')) {
356
+ } else if (missingTools.length > 0 || missingAgent.length > 0) {
319
357
  output.status = 'needs-setup';
320
358
  }
321
359
 
360
+ // Auto-install CLI tools if requested
361
+ if (autoFix && missingTools.length > 0) {
362
+ console.log(c.cyan('\n🔧 Installing CLI tools...\n'));
363
+ const installResult = autoInstallCliTools(missingTools);
364
+
365
+ // Re-check after installation
366
+ if (installResult.success.length > 0) {
367
+ for (const name of installResult.success) {
368
+ const tool = output.checks.cliTools.items.find(t => t.name === name);
369
+ if (tool) {
370
+ tool.installed = true;
371
+ tool.version = 'installed';
372
+ }
373
+ }
374
+ output.checks.cliTools.available = output.checks.cliTools.items.filter(t => t.installed).length;
375
+ }
376
+ }
377
+
322
378
  return output;
323
379
  }
324
380
 
@@ -327,113 +383,93 @@ function runDoctor(): DoctorOutput {
327
383
  // ============================================================================
328
384
 
329
385
  function printDoctor(output: DoctorOutput) {
330
- console.log('\n' + colors.blue('╔═══════════════════════════════════════════════════════════╗'));
331
- console.log(colors.blue('║') + ' 🐝 Hive Doctor v' + output.version + ' - System Check' + ' '.repeat(14) + colors.blue('║'));
332
- console.log(colors.blue('╚═══════════════════════════════════════════════════════════╝'));
386
+ console.log('\n' + c.blue('╔═══════════════════════════════════════════════════════════╗'));
387
+ console.log(c.blue('║') + ' 🐝 Hive Doctor v' + output.version + ' - System Check' + ' '.repeat(14) + c.blue('║'));
388
+ console.log(c.blue('╚═══════════════════════════════════════════════════════════╝'));
333
389
 
334
- // Summary
335
- console.log('\n' + colors.gray('─'.repeat(55)));
390
+ console.log('\n' + c.gray('─'.repeat(55)));
336
391
  console.log(` OS: ${output.summary.os}`);
337
392
  console.log(` Node: ${output.summary.nodeVersion}`);
338
- console.log(` Package Manager: ${output.summary.packageManager}`);
339
- console.log(colors.gray('─'.repeat(55)));
393
+ console.log(` PM: ${output.summary.packageManager}`);
394
+ console.log(c.gray('─'.repeat(55)));
340
395
 
341
396
  // Status
342
- const statusColor = output.status === 'ready' ? colors.green :
343
- output.status === 'needs-setup' ? colors.yellow : colors.red;
397
+ const statusColor = output.status === 'ready' ? c.green :
398
+ output.status === 'needs-setup' ? c.yellow : c.red;
344
399
  const statusText = output.status === 'ready' ? '✅ READY' :
345
400
  output.status === 'needs-setup' ? '⚠️ NEEDS SETUP' : '❌ ACTION REQUIRED';
346
401
 
347
402
  console.log('\n Status: ' + statusColor(statusText));
348
403
 
349
- // Dependencies
350
- console.log('\n📦 Dependencies (' + output.checks.dependencies.installed + '/' + output.checks.dependencies.total + ')');
351
- for (const dep of output.checks.dependencies.items) {
352
- const icon = dep.installed ? colors.green('✅') : colors.yellow('○');
353
- const version = dep.version ? colors.gray(`v${dep.version}`) : colors.red('not installed');
354
- console.log(` ${icon} ${dep.name} ${version}`);
404
+ // Agent tools
405
+ console.log('\n🚀 Agent Tools (' + output.checks.agentTools.installed + '/' + output.checks.agentTools.total + ')');
406
+ for (const tool of output.checks.agentTools.items) {
407
+ const icon = tool.installed ? c.green('✅') : c.yellow('○');
408
+ const version = tool.version ? c.gray(`v${tool.version}`) : c.red('not installed');
409
+ console.log(` ${icon} ${tool.name} ${version}`);
355
410
  }
356
411
 
357
- // CLI Tools
412
+ // CLI tools
358
413
  console.log('\n🔧 CLI Tools (' + output.checks.cliTools.available + '/' + output.checks.cliTools.total + ')');
359
414
  for (const tool of output.checks.cliTools.items) {
360
- const icon = tool.installed ? colors.green('✅') : colors.yellow('○');
361
- const version = tool.version ? colors.gray(`(${tool.version})`) : colors.red('not available');
415
+ const icon = tool.installed ? c.green('✅') : c.yellow('○');
416
+ const version = tool.version ? c.gray(`(${tool.version})`) : c.red('not available');
362
417
  console.log(` ${icon} ${tool.name} - ${tool.description} ${version}`);
363
418
  }
364
419
 
365
- // Native binaries
366
- console.log('\n Native Binaries');
367
- if (output.checks.nativeBinaries.status === 'native') {
368
- console.log(' ' + colors.green('✅ Native mode (fastest)'));
369
- } else {
370
- console.log(' ' + colors.yellow('○ CLI mode (falls back via npx)'));
371
- if (output.checks.nativeBinaries.reason) {
372
- console.log(' ' + colors.gray(output.checks.nativeBinaries.reason));
373
- }
374
- }
420
+ // Note about MCPs
421
+ console.log('\n📦 MCPs: ' + c.gray('Auto-installed with plugin'));
375
422
 
376
- // Config
377
- console.log('\n⚙️ Config');
378
- if (output.checks.config.exists) {
379
- console.log(' ' + colors.green(' Config file found'));
380
- if (output.checks.config.optimizations.length > 0) {
381
- console.log(' ' + colors.gray('Optimizations: ' + output.checks.config.optimizations.join(', ')));
382
- }
423
+ // C++20 status
424
+ console.log('\n⚡ C++20 for native modules:');
425
+ if (output.cxxflagsStatus === 'set') {
426
+ console.log(' ' + c.green(' Already configured in shell'));
427
+ } else if (output.cxxflagsStatus === 'auto-fixed') {
428
+ console.log(' ' + c.green(' Auto-configured! (run "source ~/.bashrc" or restart terminal)'));
383
429
  } else {
384
- console.log(' ' + colors.yellow('○ No config file (optional)'));
430
+ console.log(' ' + c.yellow('○ Not set (needed for @ast-grep/napi)'));
431
+ console.log(' ' + c.gray(' Run with --fix to auto-configure'));
385
432
  }
386
433
 
387
434
  // Action items
388
435
  if (output.actionItems.length > 0) {
389
- console.log('\n' + colors.gray('─'.repeat(55)));
390
- console.log('📋 Action Items\n');
436
+ console.log('\n' + c.gray('─'.repeat(55)));
437
+ console.log('\n📋 Action Items\n');
391
438
 
392
439
  for (const item of output.actionItems) {
393
- const priorityColor = item.priority === 'critical' ? colors.red :
394
- item.priority === 'high' ? colors.yellow :
395
- item.priority === 'medium' ? colors.blue : colors.gray;
440
+ const priorityColor = item.priority === 'high' ? c.red :
441
+ item.priority === 'medium' ? c.yellow : c.gray;
396
442
 
397
443
  console.log(` [${priorityColor(item.priority.toUpperCase())}] ${item.action}`);
398
- console.log(` ${colors.gray(item.reason)}`);
444
+ console.log(` ${c.gray(item.reason)}`);
399
445
  if (item.command) {
400
- console.log(` ${colors.green(item.command)}`);
446
+ console.log(` ${c.green(item.command)}`);
401
447
  }
402
448
  console.log();
403
449
  }
404
450
  }
405
451
 
406
452
  // Quick install
407
- if (output.installCommands.deps || output.installCommands.cliTools) {
408
- console.log(colors.gray('─'.repeat(55)));
453
+ if (output.quickInstall) {
454
+ console.log(c.gray('─'.repeat(55)));
409
455
  console.log('\n🚀 Quick Install\n');
410
-
411
- if (output.installCommands.deps) {
412
- console.log(' ' + colors.cyan('Dependencies:'));
413
- console.log(' ' + colors.green(output.installCommands.deps));
414
- }
415
-
416
- if (output.installCommands.cliTools) {
417
- console.log('\n ' + colors.cyan('CLI Tools:'));
418
- console.log(' ' + colors.green(output.installCommands.cliTools));
419
- }
420
-
421
- // Note about C++20 for native modules
422
- console.log('\n' + colors.yellow('💡 Tip: ') + colors.gray('If @ast-grep/napi fails to build, try:'));
423
- console.log(' ' + colors.green('export CXXFLAGS="-std=c++20" && npm install'));
456
+ console.log(' ' + c.green(output.quickInstall));
424
457
  }
425
458
 
426
- console.log('\n' + colors.blue('═'.repeat(55)));
427
- console.log(colors.gray(' Run with: bunx @hung319/opencode-hive doctor'));
428
- console.log(colors.blue('═'.repeat(55)) + '\n');
459
+ console.log('\n' + c.blue('═'.repeat(55)));
460
+ console.log(c.gray(' bunx @hung319/opencode-hive doctor'));
461
+ console.log(c.gray(' bunx @hung319/opencode-hive doctor --fix'));
462
+ console.log(c.blue('═'.repeat(55)) + '\n');
429
463
  }
430
464
 
431
465
  // ============================================================================
432
466
  // Main
433
467
  // ============================================================================
434
468
 
435
- const output = runDoctor();
469
+ const args = process.argv.slice(2);
470
+ const autoFix = args.includes('--fix') || args.includes('-f');
471
+
472
+ const output = runDoctor(autoFix);
436
473
  printDoctor(output);
437
474
 
438
- // Exit with appropriate code
439
475
  process.exit(output.status === 'ready' ? 0 : 1);
package/dist/index.js CHANGED
@@ -17811,7 +17811,6 @@ import * as path6 from "path";
17811
17811
  async function checkPackage(packageName) {
17812
17812
  const result = {
17813
17813
  name: packageName,
17814
- package: packageName,
17815
17814
  installed: false
17816
17815
  };
17817
17816
  try {
@@ -17846,183 +17845,126 @@ function checkCliTool(name, command, description) {
17846
17845
  }
17847
17846
  return result;
17848
17847
  }
17849
- function checkConfig() {
17850
- const checks3 = [];
17851
- const configPaths = [
17852
- path6.join(process.env.HOME || "", ".config/opencode/agent_hive.json"),
17853
- path6.join(process.env.HOME || "", ".config/opencode/agent_hive.jsonc")
17848
+ function checkCxxFlags() {
17849
+ const configs = [
17850
+ path6.join(process.env.HOME || "", ".bashrc"),
17851
+ path6.join(process.env.HOME || "", ".zshrc")
17854
17852
  ];
17855
- let config2 = null;
17856
- for (const configPath of configPaths) {
17857
- if (fs5.existsSync(configPath)) {
17858
- try {
17859
- const content = fs5.readFileSync(configPath, "utf-8");
17860
- config2 = JSON.parse(content.replace(/\\/g, ""));
17861
- break;
17862
- } catch {}
17853
+ for (const config2 of configs) {
17854
+ if (fs5.existsSync(config2)) {
17855
+ const content = fs5.readFileSync(config2, "utf-8");
17856
+ if (content.includes('CXXFLAGS="-std=c++20"')) {
17857
+ return "set";
17858
+ }
17863
17859
  }
17864
17860
  }
17865
- const snipEnabled = config2?.snip?.enabled === true;
17866
- checks3.push({
17867
- name: "snip",
17868
- enabled: snipEnabled,
17869
- value: config2?.snip,
17870
- recommendation: snipEnabled ? "snip enabled for 60-90% token reduction" : 'Enable snip: Add { "snip": { "enabled": true } } to config'
17871
- });
17872
- const vectorEnabled = config2?.vectorMemory?.enabled === true;
17873
- checks3.push({
17874
- name: "vectorMemory",
17875
- enabled: vectorEnabled,
17876
- value: config2?.vectorMemory,
17877
- recommendation: vectorEnabled ? "Vector memory enabled for semantic search" : 'Enable vector memory: Add { "vectorMemory": { "enabled": true } } to config'
17878
- });
17879
- const boosterEnabled = config2?.agentBooster?.enabled !== false;
17880
- checks3.push({
17881
- name: "agentBooster",
17882
- enabled: boosterEnabled,
17883
- value: config2?.agentBooster,
17884
- recommendation: boosterEnabled ? "Agent booster enabled for 52x faster editing" : 'Agent booster disabled: Set { "agentBooster": { "enabled": true } } to enable'
17885
- });
17886
- const sandboxMode = config2?.sandbox?.mode || "none";
17887
- const sandboxEnabled = sandboxMode !== "none";
17888
- checks3.push({
17889
- name: "sandbox",
17890
- enabled: sandboxEnabled,
17891
- value: sandboxMode,
17892
- recommendation: sandboxEnabled ? `Sandbox enabled (${sandboxMode} mode)` : 'Enable sandbox: Add { "sandbox": { "mode": "docker" } } to config for isolated testing'
17893
- });
17894
- const disabledMcps = config2?.disableMcps || [];
17895
- checks3.push({
17896
- name: "veil MCP",
17897
- enabled: !disabledMcps.includes("veil"),
17898
- recommendation: !disabledMcps.includes("veil") ? "veil MCP enabled" : 'Enable veil: Remove "veil" from disableMcps array'
17899
- });
17900
- checks3.push({
17901
- name: "pare_search MCP",
17902
- enabled: !disabledMcps.includes("pare_search"),
17903
- recommendation: !disabledMcps.includes("pare_search") ? "pare_search MCP enabled" : 'Enable pare_search: Remove "pare_search" from disableMcps array'
17904
- });
17905
- return checks3;
17861
+ return "not-set";
17906
17862
  }
17907
17863
  var hiveDoctorTool = tool({
17908
- description: `Hive Doctor - System health check with actionable fixes.
17864
+ description: `Hive Doctor - System health check for Hive plugin.
17909
17865
 
17910
- **Checks performed:**
17911
- 1. Dependencies - MCP packages, agent tools, blockchain, etc.
17912
- 2. CLI Tools - dora, auto-cr, scip-typescript, veil, btca, etc.
17913
- 3. Config - optimizations and MCPs enabled
17866
+ **Checks:**
17867
+ 1. Agent Tools (optional): agent-booster, memory
17868
+ 2. CLI Tools (optional): dora, auto-cr, scip-typescript, veil, btca
17869
+ 3. C++20 config: For @ast-grep/napi native modules
17914
17870
 
17915
- **Output includes:**
17916
- - Status summary (healthy/warning/action-required)
17917
- - Missing items with install commands
17918
- - Action items prioritized by impact
17919
- - Quick install commands for all missing items
17871
+ **Status:**
17872
+ - ready: All good
17873
+ - needs-setup: Some optional tools missing
17874
+ - action-required: Multiple tools missing
17920
17875
 
17921
- **Tip:** Run standalone before installing: \`bunx @hung319/opencode-hive doctor\``,
17876
+ **Tip:** Run standalone for auto-fix: \`bunx @hung319/opencode-hive doctor --fix\``,
17922
17877
  args: {},
17923
17878
  async execute() {
17924
- const dependencyChecks = await Promise.all([
17879
+ const result = {
17880
+ status: "ready",
17881
+ version: "1.6.4",
17882
+ checks: {
17883
+ agentTools: { total: 0, installed: 0, items: [] },
17884
+ cliTools: { total: 0, available: 0, items: [] }
17885
+ },
17886
+ cxxflagsStatus: checkCxxFlags(),
17887
+ actionItems: [],
17888
+ quickInstall: ""
17889
+ };
17890
+ const agentTools = await Promise.all([
17925
17891
  checkPackage("@sparkleideas/agent-booster"),
17926
- checkPackage("@sparkleideas/memory"),
17927
- checkPackage("@paretools/search"),
17928
- checkPackage("@upstash/context7-mcp"),
17929
- checkPackage("exa-mcp-server"),
17930
- checkPackage("grep-mcp"),
17931
- checkPackage("btca"),
17932
- checkPackage("opencode-model-selector")
17892
+ checkPackage("@sparkleideas/memory")
17933
17893
  ]);
17934
- const cliToolChecks = [
17894
+ result.checks.agentTools.items = agentTools;
17895
+ result.checks.agentTools.total = agentTools.length;
17896
+ result.checks.agentTools.installed = agentTools.filter((t) => t.installed).length;
17897
+ const cliTools = [
17935
17898
  checkCliTool("dora", "@butttons/dora", "SCIP-based code navigation"),
17936
- checkCliTool("auto-cr", "auto-cr-cmd", "SWC-based automated code review"),
17937
- checkCliTool("scip-typescript", "@sourcegraph/scip-typescript", "TypeScript SCIP indexer"),
17938
- checkCliTool("veil", "@ushiradineth/veil", "Code discovery and retrieval"),
17939
- checkCliTool("btca", "btca", "BTC/A agent for blockchain tasks")
17899
+ checkCliTool("auto-cr", "auto-cr-cmd", "SWC-based code review"),
17900
+ checkCliTool("scip-typescript", "@sourcegraph/scip-typescript", "TypeScript indexer"),
17901
+ checkCliTool("veil", "@ushiradineth/veil", "Code discovery"),
17902
+ checkCliTool("btca", "btca", "BTC/A blockchain agent")
17940
17903
  ];
17941
- const configChecks = checkConfig();
17942
- const missingDeps = dependencyChecks.filter((d) => !d.installed);
17943
- const missingTools = cliToolChecks.filter((t) => !t.installed);
17944
- const disabledConfigs = configChecks.filter((c) => !c.enabled);
17945
- let status = "healthy";
17946
- if (missingTools.length >= 2 || missingDeps.length >= 3) {
17947
- status = "action-required";
17948
- } else if (missingTools.length >= 1 || missingDeps.length >= 1 || disabledConfigs.length >= 2) {
17949
- status = "warning";
17950
- }
17951
- const actionItems = [];
17952
- for (const tool3 of missingTools) {
17953
- actionItems.push({
17904
+ result.checks.cliTools.items = cliTools;
17905
+ result.checks.cliTools.total = cliTools.length;
17906
+ result.checks.cliTools.available = cliTools.filter((t) => t.installed).length;
17907
+ const missingTools = cliTools.filter((t) => !t.installed);
17908
+ const missingAgent = agentTools.filter((t) => !t.installed);
17909
+ if (missingTools.length > 0) {
17910
+ result.actionItems.push({
17954
17911
  priority: "high",
17955
- action: `Install ${tool3.name}`,
17956
- command: `npx -y ${tool3.command}`,
17957
- reason: `${tool3.description}`
17912
+ action: "Install CLI tools",
17913
+ command: missingTools.map((t) => `npx -y ${t.command}`).join(" && "),
17914
+ reason: "CLI tools enhance code navigation and review"
17958
17915
  });
17959
17916
  }
17960
- if (!dependencyChecks.find((d) => d.package === "btca")?.installed) {
17961
- actionItems.push({
17917
+ if (missingAgent.length > 0) {
17918
+ result.actionItems.push({
17962
17919
  priority: "medium",
17963
- action: "Install btca for blockchain tasks",
17964
- command: `npm install btca`,
17965
- reason: "BTC/A agent for blockchain analysis and development"
17920
+ action: "Install agent tools",
17921
+ command: missingAgent.map((t) => `npm install ${t.name}`).join(" && "),
17922
+ reason: "Agent tools provide faster editing and memory"
17966
17923
  });
17967
17924
  }
17968
- for (const config2 of disabledConfigs) {
17969
- actionItems.push({
17925
+ if (result.cxxflagsStatus === "not-set") {
17926
+ result.actionItems.push({
17970
17927
  priority: "low",
17971
- action: config2.recommendation,
17972
- reason: `Enable ${config2.name} for better performance/features`
17928
+ action: "Enable C++20 for native modules",
17929
+ command: `echo 'export CXXFLAGS="-std=c++20"' >> ~/.bashrc`,
17930
+ reason: "Required for @ast-grep/napi tree-sitter build"
17973
17931
  });
17974
17932
  }
17975
- const quickInstall = {
17976
- deps: missingDeps.map((d) => d.package),
17977
- cliTools: missingTools.map((t) => t.command)
17978
- };
17979
- const summary = {
17980
- dependencies: missingDeps.length === 0 ? "✅ All dependencies installed" : `⚠️ ${missingDeps.length} missing: ${missingDeps.map((d) => d.name).join(", ")}`,
17981
- cliTools: missingTools.length === 0 ? "✅ All CLI tools available" : `⚠️ ${missingTools.length} missing: ${missingTools.map((t) => t.name).join(", ")}`,
17982
- config: disabledConfigs.length === 0 ? "✅ All optimizations enabled" : `\uD83D\uDCA1 ${disabledConfigs.length} disabled: ${disabledConfigs.map((c) => c.name).join(", ")}`
17983
- };
17984
- const result = {
17985
- status,
17986
- summary,
17987
- details: {
17988
- dependencies: {
17989
- total: dependencyChecks.length,
17990
- installed: dependencyChecks.filter((d) => d.installed).length,
17991
- missing: missingDeps
17992
- },
17993
- cliTools: {
17994
- total: cliToolChecks.length,
17995
- available: cliToolChecks.filter((t) => t.installed).length,
17996
- missing: missingTools
17997
- },
17998
- config: configChecks
17999
- },
18000
- actionItems,
18001
- quickInstall
18002
- };
17933
+ const allCommands = [];
17934
+ for (const tool3 of missingTools) {
17935
+ allCommands.push(`npx -y ${tool3.command}`);
17936
+ }
17937
+ for (const agent of missingAgent) {
17938
+ allCommands.push(`npm install ${agent.name}`);
17939
+ }
17940
+ result.quickInstall = allCommands.join(" && ");
17941
+ if (missingTools.length >= 3) {
17942
+ result.status = "action-required";
17943
+ } else if (missingTools.length > 0 || missingAgent.length > 0) {
17944
+ result.status = "needs-setup";
17945
+ }
18003
17946
  return JSON.stringify(result, null, 2);
18004
17947
  }
18005
17948
  });
18006
17949
  var hiveDoctorQuickTool = tool({
18007
- description: `Quick health status - shows summary without details.
17950
+ description: `Quick health status - shows summary only.
18008
17951
 
18009
17952
  **Returns:**
18010
- - healthy: All dependencies and CLI tools available
18011
- - warning: Some items missing (not blocking)
18012
- - action-required: Multiple items missing (fix recommended)`,
17953
+ - ready: All optional tools installed
17954
+ - needs-setup: Some tools missing (recommended)
17955
+ - action-required: Multiple tools missing`,
18013
17956
  args: {},
18014
17957
  async execute() {
18015
17958
  const checks3 = await Promise.all([
18016
17959
  checkPackage("@sparkleideas/agent-booster"),
18017
- checkPackage("btca"),
18018
17960
  checkCliTool("dora", "@butttons/dora", ""),
18019
17961
  checkCliTool("auto-cr", "auto-cr-cmd", "")
18020
17962
  ]);
18021
17963
  const missing = checks3.filter((c) => !c.installed).length;
18022
17964
  return JSON.stringify({
18023
- status: missing === 0 ? "healthy" : missing >= 2 ? "action-required" : "warning",
17965
+ status: missing === 0 ? "ready" : missing >= 2 ? "action-required" : "needs-setup",
18024
17966
  missingCount: missing,
18025
- runFullCheck: "Run hive_doctor for detailed analysis and install commands"
17967
+ autoFix: "Run standalone: bunx @hung319/opencode-hive doctor --fix"
18026
17968
  }, null, 2);
18027
17969
  }
18028
17970
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hung319/opencode-hive",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
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",