@hung319/opencode-hive 1.5.6 → 1.5.9
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 +118 -34
- package/bin/doctor.ts +436 -0
- package/dist/index.js +430 -535
- package/dist/tools/ast-grep-native.d.ts +2 -1
- package/dist/tools/hive-doctor.d.ts +1 -1
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -14,6 +14,49 @@ Vibe: "Just make it work"
|
|
|
14
14
|
Hive: Plan → Review → Approve → Execute → Ship
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
## Quick Setup (3 Steps)
|
|
18
|
+
|
|
19
|
+
### For AI Agents (LLM)
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
1. Run: hive_doctor
|
|
23
|
+
2. Install missing: npm install <packages> && npx -y <tools>
|
|
24
|
+
3. Config: Add to ~/.config/opencode/agent_hive.json
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### For Humans
|
|
28
|
+
|
|
29
|
+
**Step 1: Check if your system is ready** (run BEFORE installing)
|
|
30
|
+
```bash
|
|
31
|
+
# Run standalone doctor to see what's needed
|
|
32
|
+
bunx @hung319/opencode-hive doctor
|
|
33
|
+
# or
|
|
34
|
+
npx @hung319/opencode-hive doctor
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Step 2: Install the plugin**
|
|
38
|
+
```bash
|
|
39
|
+
npm install @hung319/opencode-hive
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Step 3: Install extras you want**
|
|
43
|
+
- For **code analysis**: `npm install @notprolands/ast-grep-mcp`
|
|
44
|
+
- For **fast code search**: `npm install @paretools/search`
|
|
45
|
+
- For **code navigation**: `npx -y @butttons/dora`
|
|
46
|
+
- For **auto code review**: `npx -y auto-cr-cmd`
|
|
47
|
+
- For **blockchain tasks**: `npm install btca-ask`
|
|
48
|
+
|
|
49
|
+
**Step 4: Optional config**
|
|
50
|
+
Create `~/.config/opencode/agent_hive.json`:
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"snip": { "enabled": true },
|
|
54
|
+
"vectorMemory": { "enabled": true }
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
17
60
|
## Installation
|
|
18
61
|
|
|
19
62
|
```bash
|
|
@@ -489,71 +532,112 @@ hive_vector_search({
|
|
|
489
532
|
|
|
490
533
|
## Hive Doctor
|
|
491
534
|
|
|
492
|
-
System health check
|
|
535
|
+
System health check with actionable fixes. Run this when setting up or troubleshooting.
|
|
493
536
|
|
|
494
537
|
### Tools
|
|
495
538
|
|
|
496
539
|
| Tool | Description |
|
|
497
540
|
|------|-------------|
|
|
498
|
-
| `hive_doctor` | Full health check with
|
|
541
|
+
| `hive_doctor` | Full health check with install commands |
|
|
499
542
|
| `hive_doctor_quick` | Quick status summary |
|
|
500
543
|
|
|
501
544
|
### Usage
|
|
502
545
|
|
|
503
546
|
```typescript
|
|
504
|
-
// Full health check
|
|
547
|
+
// Full health check with actionable output
|
|
505
548
|
hive_doctor()
|
|
506
549
|
|
|
507
|
-
// Quick
|
|
550
|
+
// Quick status
|
|
508
551
|
hive_doctor_quick()
|
|
509
552
|
```
|
|
510
553
|
|
|
554
|
+
**Standalone (before installing):**
|
|
555
|
+
```bash
|
|
556
|
+
bunx @hung319/opencode-hive doctor
|
|
557
|
+
```
|
|
558
|
+
|
|
511
559
|
### What it checks
|
|
512
560
|
|
|
513
|
-
1. **Dependencies** -
|
|
514
|
-
-
|
|
515
|
-
-
|
|
516
|
-
-
|
|
517
|
-
-
|
|
518
|
-
|
|
519
|
-
|
|
561
|
+
1. **Dependencies** - npm packages installed?
|
|
562
|
+
- Core: `@ast-grep/napi`, `@notprolands/ast-grep-mcp`, `@paretools/search`
|
|
563
|
+
- Agent: `@sparkleideas/agent-booster`, `@sparkleideas/memory`
|
|
564
|
+
- MCPs: `@upstash/context7-mcp`, `exa-mcp-server`, `grep-mcp`
|
|
565
|
+
- Blockchain: `btca-ask`, `opencode-model-selector`
|
|
566
|
+
|
|
567
|
+
2. **CLI Tools** - npx tools available?
|
|
568
|
+
- `dora` - Code navigation (SCIP-based)
|
|
569
|
+
- `auto-cr` - Automated code review (SWC)
|
|
570
|
+
- `scip-typescript` - TypeScript indexer
|
|
571
|
+
- `veil` - Code discovery
|
|
572
|
+
- `btca` - BTC/A blockchain agent
|
|
520
573
|
|
|
521
|
-
|
|
522
|
-
-
|
|
523
|
-
-
|
|
524
|
-
- agent booster (fast code editing)
|
|
525
|
-
- Docker sandbox (isolated environments)
|
|
526
|
-
- native ast-grep (fast AST analysis)
|
|
527
|
-
- pare-search (structured search)
|
|
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
|
|
528
577
|
|
|
529
|
-
|
|
578
|
+
4. **Config** - Features enabled?
|
|
579
|
+
- snip, vectorMemory, agentBooster
|
|
580
|
+
- sandbox mode
|
|
581
|
+
- MCPs: ast_grep, veil, pare_search
|
|
530
582
|
|
|
531
583
|
### Example Output
|
|
532
584
|
|
|
533
585
|
```json
|
|
534
586
|
{
|
|
535
587
|
"status": "warning",
|
|
536
|
-
"
|
|
537
|
-
"dependencies":
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
588
|
+
"summary": {
|
|
589
|
+
"dependencies": "⚠️ 2 missing: agent-booster, vector-memory",
|
|
590
|
+
"cliTools": "⚠️ 1 missing: auto-cr",
|
|
591
|
+
"nativeBinaries": "⚡ CLI mode (native unavailable)",
|
|
592
|
+
"config": "💡 2 disabled: snip, vectorMemory"
|
|
593
|
+
},
|
|
594
|
+
"actionItems": [
|
|
595
|
+
{
|
|
596
|
+
"priority": "high",
|
|
597
|
+
"action": "Install auto-cr",
|
|
598
|
+
"command": "npx -y auto-cr-cmd",
|
|
599
|
+
"reason": "SWC-based automated code review"
|
|
541
600
|
},
|
|
542
|
-
|
|
543
|
-
"
|
|
544
|
-
"
|
|
545
|
-
"
|
|
601
|
+
{
|
|
602
|
+
"priority": "medium",
|
|
603
|
+
"action": "Install agent-booster",
|
|
604
|
+
"command": "npm install @sparkleideas/agent-booster",
|
|
605
|
+
"reason": "52x faster code editing"
|
|
546
606
|
}
|
|
547
|
-
},
|
|
548
|
-
"recommendations": [
|
|
549
|
-
"Enable vector memory for semantic search across memories"
|
|
550
607
|
],
|
|
551
|
-
"
|
|
552
|
-
|
|
553
|
-
|
|
608
|
+
"quickInstall": {
|
|
609
|
+
"deps": ["@sparkleideas/agent-booster", "@sparkleideas/memory"],
|
|
610
|
+
"cliTools": ["auto-cr-cmd"]
|
|
611
|
+
}
|
|
554
612
|
}
|
|
555
613
|
```
|
|
556
614
|
|
|
615
|
+
### Setup Workflow
|
|
616
|
+
|
|
617
|
+
**For AI Agents (LLM):**
|
|
618
|
+
|
|
619
|
+
```
|
|
620
|
+
1. Run: hive_doctor
|
|
621
|
+
2. Parse: actionItems[] for priority: "high"
|
|
622
|
+
3. Install: Run quickInstall.commands
|
|
623
|
+
4. Config: Apply config recommendations
|
|
624
|
+
5. Verify: Run hive_doctor again to confirm
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
**For Humans:**
|
|
628
|
+
|
|
629
|
+
1. **Open OpenCode** and ask "Run hive_doctor"
|
|
630
|
+
2. **Look at the summary** - it tells you what's missing
|
|
631
|
+
3. **Install what you need** - commands are ready to copy
|
|
632
|
+
4. **Optional: Configure** - enable snip, vector memory for extra features
|
|
633
|
+
|
|
634
|
+
```
|
|
635
|
+
Quick Install All:
|
|
636
|
+
npm install @notprolands/ast-grep-mcp @paretools/search @sparkleideas/memory
|
|
637
|
+
npx -y @butttons/dora auto-cr-cmd
|
|
638
|
+
```
|
|
639
|
+
```
|
|
640
|
+
|
|
557
641
|
## License
|
|
558
642
|
|
|
559
643
|
MIT with Commons Clause — Free for personal and non-commercial use. See [LICENSE](../../LICENSE) for details.
|
package/bin/doctor.ts
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Hive Doctor - Standalone version
|
|
5
|
+
*
|
|
6
|
+
* Run BEFORE installing the plugin to check if your system is ready:
|
|
7
|
+
*
|
|
8
|
+
* bunx @hung319/opencode-hive doctor
|
|
9
|
+
* npx @hung319/opencode-hive doctor
|
|
10
|
+
*
|
|
11
|
+
* Or install and run:
|
|
12
|
+
*
|
|
13
|
+
* npm install @hung319/opencode-hive
|
|
14
|
+
* hive_doctor() // via OpenCode
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { execSync } from 'child_process';
|
|
18
|
+
import * as fs from 'fs';
|
|
19
|
+
import * as path from 'path';
|
|
20
|
+
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Types
|
|
23
|
+
// ============================================================================
|
|
24
|
+
|
|
25
|
+
interface CheckResult {
|
|
26
|
+
name: string;
|
|
27
|
+
installed: boolean;
|
|
28
|
+
version?: string;
|
|
29
|
+
reason?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface CliCheck {
|
|
33
|
+
name: string;
|
|
34
|
+
command: string;
|
|
35
|
+
installed: boolean;
|
|
36
|
+
version?: string;
|
|
37
|
+
description: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface DoctorOutput {
|
|
41
|
+
status: 'ready' | 'needs-setup' | 'action-required';
|
|
42
|
+
version: string;
|
|
43
|
+
summary: {
|
|
44
|
+
os: string;
|
|
45
|
+
nodeVersion: string;
|
|
46
|
+
packageManager: string;
|
|
47
|
+
};
|
|
48
|
+
checks: {
|
|
49
|
+
dependencies: {
|
|
50
|
+
total: number;
|
|
51
|
+
installed: number;
|
|
52
|
+
items: CheckResult[];
|
|
53
|
+
};
|
|
54
|
+
cliTools: {
|
|
55
|
+
total: number;
|
|
56
|
+
available: number;
|
|
57
|
+
items: CliCheck[];
|
|
58
|
+
};
|
|
59
|
+
nativeBinaries: {
|
|
60
|
+
status: 'native' | 'cli-mode';
|
|
61
|
+
reason?: string;
|
|
62
|
+
};
|
|
63
|
+
config: {
|
|
64
|
+
exists: boolean;
|
|
65
|
+
path?: string;
|
|
66
|
+
optimizations: string[];
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
actionItems: {
|
|
70
|
+
priority: 'critical' | 'high' | 'medium' | 'low';
|
|
71
|
+
action: string;
|
|
72
|
+
command?: string;
|
|
73
|
+
reason: string;
|
|
74
|
+
}[];
|
|
75
|
+
installCommands: {
|
|
76
|
+
deps: string;
|
|
77
|
+
cliTools: string;
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Color helpers
|
|
83
|
+
// ============================================================================
|
|
84
|
+
|
|
85
|
+
const colors = {
|
|
86
|
+
green: (text: string) => `\x1b[32m${text}\x1b[0m`,
|
|
87
|
+
yellow: (text: string) => `\x1b[33m${text}\x1b[0m`,
|
|
88
|
+
red: (text: string) => `\x1b[31m${text}\x1b[0m`,
|
|
89
|
+
blue: (text: string) => `\x1b[34m${text}\x1b[0m`,
|
|
90
|
+
gray: (text: string) => `\x1b[90m${text}\x1b[0m`,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// Check functions
|
|
95
|
+
// ============================================================================
|
|
96
|
+
|
|
97
|
+
function getSystemInfo() {
|
|
98
|
+
return {
|
|
99
|
+
os: process.platform,
|
|
100
|
+
nodeVersion: process.version,
|
|
101
|
+
packageManager: exists('npm') ? 'npm' : exists('bun') ? 'bun' : 'unknown',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function exists(cmd: string): boolean {
|
|
106
|
+
try {
|
|
107
|
+
execSync(cmd, { stdio: 'ignore' });
|
|
108
|
+
return true;
|
|
109
|
+
} catch {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function checkNpmPackage(name: string): CheckResult {
|
|
115
|
+
const result: CheckResult = { name, installed: false };
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const output = execSync(`npm list ${name} --depth=0 --json 2>/dev/null`, {
|
|
119
|
+
encoding: 'utf-8',
|
|
120
|
+
timeout: 10000,
|
|
121
|
+
});
|
|
122
|
+
const json = JSON.parse(output);
|
|
123
|
+
if (json.dependencies && json.dependencies[name]) {
|
|
124
|
+
result.installed = true;
|
|
125
|
+
result.version = json.dependencies[name].version;
|
|
126
|
+
}
|
|
127
|
+
} catch {}
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function checkCliTool(name: string, command: string, description: string): CliCheck {
|
|
133
|
+
const result: CliCheck = { name, command, installed: false, description };
|
|
134
|
+
|
|
135
|
+
// Try direct command
|
|
136
|
+
try {
|
|
137
|
+
const cmd = command.split(' ')[0];
|
|
138
|
+
execSync(cmd, { stdio: 'ignore', timeout: 3000 });
|
|
139
|
+
result.installed = true;
|
|
140
|
+
result.version = 'installed';
|
|
141
|
+
return result;
|
|
142
|
+
} catch {}
|
|
143
|
+
|
|
144
|
+
// Try npx
|
|
145
|
+
try {
|
|
146
|
+
execSync(`npx -y ${command.split(' ')[0]} --version`, {
|
|
147
|
+
stdio: 'ignore',
|
|
148
|
+
timeout: 10000
|
|
149
|
+
});
|
|
150
|
+
result.installed = true;
|
|
151
|
+
result.version = 'via npx';
|
|
152
|
+
return result;
|
|
153
|
+
} catch {}
|
|
154
|
+
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function checkAstGrepNative(): { status: 'native' | 'cli-mode'; reason?: string } {
|
|
159
|
+
// Check if @ast-grep/napi package exists with native binaries
|
|
160
|
+
const napiDirs = [
|
|
161
|
+
path.join(process.cwd(), 'node_modules/@ast-grep/napi'),
|
|
162
|
+
path.join(process.env.HOME || '', '.npm-global/lib/node_modules/@ast-grep/napi'),
|
|
163
|
+
];
|
|
164
|
+
|
|
165
|
+
for (const napiDir of napiDirs) {
|
|
166
|
+
if (!fs.existsSync(napiDir)) continue;
|
|
167
|
+
|
|
168
|
+
const binaryPaths = [
|
|
169
|
+
path.join(napiDir, 'index.node'),
|
|
170
|
+
path.join(napiDir, 'build/Release/ast_grep.node'),
|
|
171
|
+
path.join(napiDir, 'dist/index.node'),
|
|
172
|
+
];
|
|
173
|
+
|
|
174
|
+
const hasBinary = binaryPaths.some(p => fs.existsSync(p));
|
|
175
|
+
|
|
176
|
+
if (hasBinary) {
|
|
177
|
+
return { status: 'native' };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return {
|
|
182
|
+
status: 'cli-mode',
|
|
183
|
+
reason: 'Native binaries not found (tree-sitter compilation may have failed)'
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function checkConfig(): { exists: boolean; path?: string; optimizations: string[] } {
|
|
188
|
+
const configPaths = [
|
|
189
|
+
path.join(process.env.HOME || '', '.config/opencode/agent_hive.json'),
|
|
190
|
+
path.join(process.env.HOME || '', '.config/opencode/agent_hive.jsonc'),
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
for (const configPath of configPaths) {
|
|
194
|
+
if (fs.existsSync(configPath)) {
|
|
195
|
+
try {
|
|
196
|
+
const content = fs.readFileSync(configPath, 'utf-8');
|
|
197
|
+
const config = JSON.parse(content.replace(/\\/g, ''));
|
|
198
|
+
const optimizations: string[] = [];
|
|
199
|
+
|
|
200
|
+
if (config.snip?.enabled) optimizations.push('snip');
|
|
201
|
+
if (config.vectorMemory?.enabled) optimizations.push('vectorMemory');
|
|
202
|
+
if (config.agentBooster?.enabled !== false) optimizations.push('agentBooster');
|
|
203
|
+
if (config.sandbox?.mode !== 'none') optimizations.push('sandbox');
|
|
204
|
+
|
|
205
|
+
return { exists: true, path: configPath, optimizations };
|
|
206
|
+
} catch {}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return { exists: false, optimizations: [] };
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// Main check
|
|
215
|
+
// ============================================================================
|
|
216
|
+
|
|
217
|
+
function runDoctor(): DoctorOutput {
|
|
218
|
+
const output: DoctorOutput = {
|
|
219
|
+
status: 'ready',
|
|
220
|
+
version: '1.5.8',
|
|
221
|
+
summary: getSystemInfo(),
|
|
222
|
+
checks: {
|
|
223
|
+
dependencies: { total: 0, installed: 0, items: [] },
|
|
224
|
+
cliTools: { total: 0, available: 0, items: [] },
|
|
225
|
+
nativeBinaries: { status: 'cli-mode' },
|
|
226
|
+
config: { exists: false, optimizations: [] },
|
|
227
|
+
},
|
|
228
|
+
actionItems: [],
|
|
229
|
+
installCommands: { deps: '', cliTools: '' },
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Check dependencies
|
|
233
|
+
const deps = [
|
|
234
|
+
'@ast-grep/napi',
|
|
235
|
+
'@notprolands/ast-grep-mcp',
|
|
236
|
+
'@sparkleideas/agent-booster',
|
|
237
|
+
'@sparkleideas/memory',
|
|
238
|
+
'@paretools/search',
|
|
239
|
+
'@upstash/context7-mcp',
|
|
240
|
+
'exa-mcp-server',
|
|
241
|
+
'grep-mcp',
|
|
242
|
+
'btca-ask',
|
|
243
|
+
'opencode-model-selector',
|
|
244
|
+
];
|
|
245
|
+
|
|
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;
|
|
249
|
+
|
|
250
|
+
// 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-ask', description: 'BTC/A agent for blockchain tasks' },
|
|
257
|
+
{ name: 'ast-grep', command: '@notprolands/ast-grep-mcp', description: 'AST-based pattern matching' },
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
output.checks.cliTools.items = cliTools.map(t => checkCliTool(t.name, t.command, t.description));
|
|
261
|
+
output.checks.cliTools.total = cliTools.length;
|
|
262
|
+
output.checks.cliTools.available = output.checks.cliTools.items.filter(t => t.installed).length;
|
|
263
|
+
|
|
264
|
+
// Check native binaries
|
|
265
|
+
output.checks.nativeBinaries = checkAstGrepNative();
|
|
266
|
+
|
|
267
|
+
// Check config
|
|
268
|
+
output.checks.config = checkConfig();
|
|
269
|
+
|
|
270
|
+
// Generate action items
|
|
271
|
+
const missingDeps = output.checks.dependencies.items.filter(d => !d.installed);
|
|
272
|
+
const missingTools = output.checks.cliTools.items.filter(t => !t.installed);
|
|
273
|
+
|
|
274
|
+
if (missingTools.length > 0) {
|
|
275
|
+
output.actionItems.push({
|
|
276
|
+
priority: 'high',
|
|
277
|
+
action: `Install ${missingTools.length} CLI tool(s)`,
|
|
278
|
+
command: missingTools.map(t => `npx -y ${t.command}`).join(' && '),
|
|
279
|
+
reason: 'CLI tools provide code navigation, review, and analysis features',
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (missingDeps.length > 0) {
|
|
284
|
+
const important = missingDeps.filter(d =>
|
|
285
|
+
['@ast-grep/napi', '@notprolands/ast-grep-mcp', '@paretools/search'].includes(d.name)
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
if (important.length > 0) {
|
|
289
|
+
output.actionItems.push({
|
|
290
|
+
priority: 'medium',
|
|
291
|
+
action: `Install ${important.length} important package(s)`,
|
|
292
|
+
command: important.map(d => `npm install ${d.name}`).join(' && '),
|
|
293
|
+
reason: 'These packages enable core functionality',
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (!output.checks.config.exists) {
|
|
299
|
+
output.actionItems.push({
|
|
300
|
+
priority: 'low',
|
|
301
|
+
action: 'Create config file',
|
|
302
|
+
command: `mkdir -p ~/.config/opencode && cat > ~/.config/opencode/agent_hive.json << 'EOF'\n{\n "snip": { "enabled": true },\n "vectorMemory": { "enabled": true }\n}\nEOF`,
|
|
303
|
+
reason: 'Enable optimizations for better performance',
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Generate install commands
|
|
308
|
+
if (missingDeps.length > 0) {
|
|
309
|
+
output.installCommands.deps = `npm install ${missingDeps.map(d => d.name).join(' ')}`;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (missingTools.length > 0) {
|
|
313
|
+
output.installCommands.cliTools = `npx -y ${missingTools.map(t => t.command.split(' ')[0]).join(' ')}`;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Determine status
|
|
317
|
+
if (output.actionItems.some(a => a.priority === 'critical')) {
|
|
318
|
+
output.status = 'action-required';
|
|
319
|
+
} else if (output.actionItems.some(a => a.priority === 'high' || a.priority === 'medium')) {
|
|
320
|
+
output.status = 'needs-setup';
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return output;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// ============================================================================
|
|
327
|
+
// Print output
|
|
328
|
+
// ============================================================================
|
|
329
|
+
|
|
330
|
+
function printDoctor(output: DoctorOutput) {
|
|
331
|
+
console.log('\n' + colors.blue('╔═══════════════════════════════════════════════════════════╗'));
|
|
332
|
+
console.log(colors.blue('║') + ' 🐝 Hive Doctor v' + output.version + ' - System Check' + ' '.repeat(14) + colors.blue('║'));
|
|
333
|
+
console.log(colors.blue('╚═══════════════════════════════════════════════════════════╝'));
|
|
334
|
+
|
|
335
|
+
// Summary
|
|
336
|
+
console.log('\n' + colors.gray('─'.repeat(55)));
|
|
337
|
+
console.log(` OS: ${output.summary.os}`);
|
|
338
|
+
console.log(` Node: ${output.summary.nodeVersion}`);
|
|
339
|
+
console.log(` Package Manager: ${output.summary.packageManager}`);
|
|
340
|
+
console.log(colors.gray('─'.repeat(55)));
|
|
341
|
+
|
|
342
|
+
// Status
|
|
343
|
+
const statusColor = output.status === 'ready' ? colors.green :
|
|
344
|
+
output.status === 'needs-setup' ? colors.yellow : colors.red;
|
|
345
|
+
const statusText = output.status === 'ready' ? '✅ READY' :
|
|
346
|
+
output.status === 'needs-setup' ? '⚠️ NEEDS SETUP' : '❌ ACTION REQUIRED';
|
|
347
|
+
|
|
348
|
+
console.log('\n Status: ' + statusColor(statusText));
|
|
349
|
+
|
|
350
|
+
// Dependencies
|
|
351
|
+
console.log('\n📦 Dependencies (' + output.checks.dependencies.installed + '/' + output.checks.dependencies.total + ')');
|
|
352
|
+
for (const dep of output.checks.dependencies.items) {
|
|
353
|
+
const icon = dep.installed ? colors.green('✅') : colors.yellow('○');
|
|
354
|
+
const version = dep.version ? colors.gray(`v${dep.version}`) : colors.red('not installed');
|
|
355
|
+
console.log(` ${icon} ${dep.name} ${version}`);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// CLI Tools
|
|
359
|
+
console.log('\n🔧 CLI Tools (' + output.checks.cliTools.available + '/' + output.checks.cliTools.total + ')');
|
|
360
|
+
for (const tool of output.checks.cliTools.items) {
|
|
361
|
+
const icon = tool.installed ? colors.green('✅') : colors.yellow('○');
|
|
362
|
+
const version = tool.version ? colors.gray(`(${tool.version})`) : colors.red('not available');
|
|
363
|
+
console.log(` ${icon} ${tool.name} - ${tool.description} ${version}`);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Native binaries
|
|
367
|
+
console.log('\n⚡ Native Binaries');
|
|
368
|
+
if (output.checks.nativeBinaries.status === 'native') {
|
|
369
|
+
console.log(' ' + colors.green('✅ Native mode (fastest)'));
|
|
370
|
+
} else {
|
|
371
|
+
console.log(' ' + colors.yellow('○ CLI mode (falls back via npx)'));
|
|
372
|
+
if (output.checks.nativeBinaries.reason) {
|
|
373
|
+
console.log(' ' + colors.gray(output.checks.nativeBinaries.reason));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Config
|
|
378
|
+
console.log('\n⚙️ Config');
|
|
379
|
+
if (output.checks.config.exists) {
|
|
380
|
+
console.log(' ' + colors.green('✅ Config file found'));
|
|
381
|
+
if (output.checks.config.optimizations.length > 0) {
|
|
382
|
+
console.log(' ' + colors.gray('Optimizations: ' + output.checks.config.optimizations.join(', ')));
|
|
383
|
+
}
|
|
384
|
+
} else {
|
|
385
|
+
console.log(' ' + colors.yellow('○ No config file (optional)'));
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Action items
|
|
389
|
+
if (output.actionItems.length > 0) {
|
|
390
|
+
console.log('\n' + colors.gray('─'.repeat(55)));
|
|
391
|
+
console.log('📋 Action Items\n');
|
|
392
|
+
|
|
393
|
+
for (const item of output.actionItems) {
|
|
394
|
+
const priorityColor = item.priority === 'critical' ? colors.red :
|
|
395
|
+
item.priority === 'high' ? colors.yellow :
|
|
396
|
+
item.priority === 'medium' ? colors.blue : colors.gray;
|
|
397
|
+
|
|
398
|
+
console.log(` [${priorityColor(item.priority.toUpperCase())}] ${item.action}`);
|
|
399
|
+
console.log(` ${colors.gray(item.reason)}`);
|
|
400
|
+
if (item.command) {
|
|
401
|
+
console.log(` ${colors.green(item.command)}`);
|
|
402
|
+
}
|
|
403
|
+
console.log();
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// Quick install
|
|
408
|
+
if (output.installCommands.deps || output.installCommands.cliTools) {
|
|
409
|
+
console.log(colors.gray('─'.repeat(55)));
|
|
410
|
+
console.log('\n🚀 Quick Install\n');
|
|
411
|
+
|
|
412
|
+
if (output.installCommands.deps) {
|
|
413
|
+
console.log(' ' + colors.cyan('Dependencies:'));
|
|
414
|
+
console.log(' ' + colors.green(output.installCommands.deps));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (output.installCommands.cliTools) {
|
|
418
|
+
console.log('\n ' + colors.cyan('CLI Tools:'));
|
|
419
|
+
console.log(' ' + colors.green(output.installCommands.cliTools));
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
console.log('\n' + colors.blue('═'.repeat(55)));
|
|
424
|
+
console.log(colors.gray(' Run with: bunx @hung319/opencode-hive doctor'));
|
|
425
|
+
console.log(colors.blue('═'.repeat(55)) + '\n');
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// ============================================================================
|
|
429
|
+
// Main
|
|
430
|
+
// ============================================================================
|
|
431
|
+
|
|
432
|
+
const output = runDoctor();
|
|
433
|
+
printDoctor(output);
|
|
434
|
+
|
|
435
|
+
// Exit with appropriate code
|
|
436
|
+
process.exit(output.status === 'ready' ? 0 : 1);
|