halfcopilot 1.0.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/LICENSE +21 -0
- package/README.md +148 -0
- package/bin/halfcop.js +22 -0
- package/dist/index.js +3 -0
- package/dist/packages/cli/dist/halfcop.d.ts +6 -0
- package/dist/packages/cli/dist/halfcop.d.ts.map +1 -0
- package/dist/packages/cli/dist/halfcop.js +448 -0
- package/dist/packages/cli/dist/halfcop.js.map +1 -0
- package/dist/packages/cli/dist/index.d.ts +3 -0
- package/dist/packages/cli/dist/index.d.ts.map +1 -0
- package/dist/packages/cli/dist/index.js +251 -0
- package/dist/packages/cli/dist/index.js.map +1 -0
- package/dist/packages/cli/dist/tui/app.d.ts +11 -0
- package/dist/packages/cli/dist/tui/app.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/app.js +72 -0
- package/dist/packages/cli/dist/tui/app.js.map +1 -0
- package/dist/packages/cli/dist/tui/components/ChatView.d.ts +12 -0
- package/dist/packages/cli/dist/tui/components/ChatView.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/components/ChatView.js +6 -0
- package/dist/packages/cli/dist/tui/components/ChatView.js.map +1 -0
- package/dist/packages/cli/dist/tui/components/InputField.d.ts +8 -0
- package/dist/packages/cli/dist/tui/components/InputField.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/components/InputField.js +22 -0
- package/dist/packages/cli/dist/tui/components/InputField.js.map +1 -0
- package/dist/packages/cli/dist/tui/components/StatusBar.d.ts +13 -0
- package/dist/packages/cli/dist/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/components/StatusBar.js +6 -0
- package/dist/packages/cli/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/packages/cli/dist/tui/components/ToolApproval.d.ts +10 -0
- package/dist/packages/cli/dist/tui/components/ToolApproval.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/components/ToolApproval.js +14 -0
- package/dist/packages/cli/dist/tui/components/ToolApproval.js.map +1 -0
- package/dist/packages/cli/dist/tui/components/index.d.ts +5 -0
- package/dist/packages/cli/dist/tui/components/index.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/components/index.js +5 -0
- package/dist/packages/cli/dist/tui/components/index.js.map +1 -0
- package/dist/packages/cli/dist/tui/index.d.ts +3 -0
- package/dist/packages/cli/dist/tui/index.d.ts.map +1 -0
- package/dist/packages/cli/dist/tui/index.js +3 -0
- package/dist/packages/cli/dist/tui/index.js.map +1 -0
- package/dist/packages/config/dist/defaults.d.ts +3 -0
- package/dist/packages/config/dist/defaults.d.ts.map +1 -0
- package/dist/packages/config/dist/defaults.js +30 -0
- package/dist/packages/config/dist/defaults.js.map +1 -0
- package/dist/packages/config/dist/index.d.ts +4 -0
- package/dist/packages/config/dist/index.d.ts.map +1 -0
- package/dist/packages/config/dist/index.js +4 -0
- package/dist/packages/config/dist/index.js.map +1 -0
- package/dist/packages/config/dist/loader.d.ts +4 -0
- package/dist/packages/config/dist/loader.d.ts.map +1 -0
- package/dist/packages/config/dist/loader.js +80 -0
- package/dist/packages/config/dist/loader.js.map +1 -0
- package/dist/packages/config/dist/schema.d.ts +323 -0
- package/dist/packages/config/dist/schema.d.ts.map +1 -0
- package/dist/packages/config/dist/schema.js +56 -0
- package/dist/packages/config/dist/schema.js.map +1 -0
- package/dist/packages/core/dist/agent-loop.d.ts +19 -0
- package/dist/packages/core/dist/agent-loop.d.ts.map +1 -0
- package/dist/packages/core/dist/agent-loop.js +140 -0
- package/dist/packages/core/dist/agent-loop.js.map +1 -0
- package/dist/packages/core/dist/conversation.d.ts +22 -0
- package/dist/packages/core/dist/conversation.d.ts.map +1 -0
- package/dist/packages/core/dist/conversation.js +66 -0
- package/dist/packages/core/dist/conversation.js.map +1 -0
- package/dist/packages/core/dist/hybrid/index.d.ts +4 -0
- package/dist/packages/core/dist/hybrid/index.d.ts.map +1 -0
- package/dist/packages/core/dist/hybrid/index.js +4 -0
- package/dist/packages/core/dist/hybrid/index.js.map +1 -0
- package/dist/packages/core/dist/hybrid/mapper.d.ts +11 -0
- package/dist/packages/core/dist/hybrid/mapper.d.ts.map +1 -0
- package/dist/packages/core/dist/hybrid/mapper.js +53 -0
- package/dist/packages/core/dist/hybrid/mapper.js.map +1 -0
- package/dist/packages/core/dist/hybrid/parser.d.ts +36 -0
- package/dist/packages/core/dist/hybrid/parser.d.ts.map +1 -0
- package/dist/packages/core/dist/hybrid/parser.js +118 -0
- package/dist/packages/core/dist/hybrid/parser.js.map +1 -0
- package/dist/packages/core/dist/hybrid/provider.d.ts +14 -0
- package/dist/packages/core/dist/hybrid/provider.d.ts.map +1 -0
- package/dist/packages/core/dist/hybrid/provider.js +109 -0
- package/dist/packages/core/dist/hybrid/provider.js.map +1 -0
- package/dist/packages/core/dist/index.d.ts +5 -0
- package/dist/packages/core/dist/index.d.ts.map +1 -0
- package/dist/packages/core/dist/index.js +5 -0
- package/dist/packages/core/dist/index.js.map +1 -0
- package/dist/packages/core/dist/types.d.ts +36 -0
- package/dist/packages/core/dist/types.d.ts.map +1 -0
- package/dist/packages/core/dist/types.js +11 -0
- package/dist/packages/core/dist/types.js.map +1 -0
- package/dist/packages/mcp/dist/adapter.d.ts +15 -0
- package/dist/packages/mcp/dist/adapter.d.ts.map +1 -0
- package/dist/packages/mcp/dist/adapter.js +44 -0
- package/dist/packages/mcp/dist/adapter.js.map +1 -0
- package/dist/packages/mcp/dist/client.d.ts +31 -0
- package/dist/packages/mcp/dist/client.d.ts.map +1 -0
- package/dist/packages/mcp/dist/client.js +140 -0
- package/dist/packages/mcp/dist/client.js.map +1 -0
- package/dist/packages/mcp/dist/index.d.ts +6 -0
- package/dist/packages/mcp/dist/index.d.ts.map +1 -0
- package/dist/packages/mcp/dist/index.js +4 -0
- package/dist/packages/mcp/dist/index.js.map +1 -0
- package/dist/packages/mcp/dist/transport.d.ts +47 -0
- package/dist/packages/mcp/dist/transport.d.ts.map +1 -0
- package/dist/packages/mcp/dist/transport.js +123 -0
- package/dist/packages/mcp/dist/transport.js.map +1 -0
- package/dist/packages/mcp/dist/types.d.ts +64 -0
- package/dist/packages/mcp/dist/types.d.ts.map +1 -0
- package/dist/packages/mcp/dist/types.js +2 -0
- package/dist/packages/mcp/dist/types.js.map +1 -0
- package/dist/packages/memory/dist/index.d.ts +3 -0
- package/dist/packages/memory/dist/index.d.ts.map +1 -0
- package/dist/packages/memory/dist/index.js +2 -0
- package/dist/packages/memory/dist/index.js.map +1 -0
- package/dist/packages/memory/dist/store.d.ts +15 -0
- package/dist/packages/memory/dist/store.d.ts.map +1 -0
- package/dist/packages/memory/dist/store.js +93 -0
- package/dist/packages/memory/dist/store.js.map +1 -0
- package/dist/packages/memory/dist/types.d.ts +14 -0
- package/dist/packages/memory/dist/types.d.ts.map +1 -0
- package/dist/packages/memory/dist/types.js +2 -0
- package/dist/packages/memory/dist/types.js.map +1 -0
- package/dist/packages/provider/dist/anthropic.d.ts +21 -0
- package/dist/packages/provider/dist/anthropic.d.ts.map +1 -0
- package/dist/packages/provider/dist/anthropic.js +148 -0
- package/dist/packages/provider/dist/anthropic.js.map +1 -0
- package/dist/packages/provider/dist/base.d.ts +16 -0
- package/dist/packages/provider/dist/base.d.ts.map +1 -0
- package/dist/packages/provider/dist/base.js +9 -0
- package/dist/packages/provider/dist/base.js.map +1 -0
- package/dist/packages/provider/dist/index.d.ts +6 -0
- package/dist/packages/provider/dist/index.d.ts.map +1 -0
- package/dist/packages/provider/dist/index.js +5 -0
- package/dist/packages/provider/dist/index.js.map +1 -0
- package/dist/packages/provider/dist/openai.d.ts +23 -0
- package/dist/packages/provider/dist/openai.d.ts.map +1 -0
- package/dist/packages/provider/dist/openai.js +171 -0
- package/dist/packages/provider/dist/openai.js.map +1 -0
- package/dist/packages/provider/dist/registry.d.ts +11 -0
- package/dist/packages/provider/dist/registry.d.ts.map +1 -0
- package/dist/packages/provider/dist/registry.js +61 -0
- package/dist/packages/provider/dist/registry.js.map +1 -0
- package/dist/packages/provider/dist/types.d.ts +84 -0
- package/dist/packages/provider/dist/types.d.ts.map +1 -0
- package/dist/packages/provider/dist/types.js +3 -0
- package/dist/packages/provider/dist/types.js.map +1 -0
- package/dist/packages/shared/dist/errors.d.ts +18 -0
- package/dist/packages/shared/dist/errors.d.ts.map +1 -0
- package/dist/packages/shared/dist/errors.js +35 -0
- package/dist/packages/shared/dist/errors.js.map +1 -0
- package/dist/packages/shared/dist/index.d.ts +4 -0
- package/dist/packages/shared/dist/index.d.ts.map +1 -0
- package/dist/packages/shared/dist/index.js +4 -0
- package/dist/packages/shared/dist/index.js.map +1 -0
- package/dist/packages/shared/dist/logger.d.ts +18 -0
- package/dist/packages/shared/dist/logger.d.ts.map +1 -0
- package/dist/packages/shared/dist/logger.js +39 -0
- package/dist/packages/shared/dist/logger.js.map +1 -0
- package/dist/packages/shared/dist/utils.d.ts +5 -0
- package/dist/packages/shared/dist/utils.d.ts.map +1 -0
- package/dist/packages/shared/dist/utils.js +27 -0
- package/dist/packages/shared/dist/utils.js.map +1 -0
- package/dist/packages/skills/dist/builtins.d.ts +8 -0
- package/dist/packages/skills/dist/builtins.d.ts.map +1 -0
- package/dist/packages/skills/dist/builtins.js +144 -0
- package/dist/packages/skills/dist/builtins.js.map +1 -0
- package/dist/packages/skills/dist/index.d.ts +4 -0
- package/dist/packages/skills/dist/index.d.ts.map +1 -0
- package/dist/packages/skills/dist/index.js +3 -0
- package/dist/packages/skills/dist/index.js.map +1 -0
- package/dist/packages/skills/dist/registry.d.ts +13 -0
- package/dist/packages/skills/dist/registry.d.ts.map +1 -0
- package/dist/packages/skills/dist/registry.js +93 -0
- package/dist/packages/skills/dist/registry.js.map +1 -0
- package/dist/packages/skills/dist/types.d.ts +35 -0
- package/dist/packages/skills/dist/types.d.ts.map +1 -0
- package/dist/packages/skills/dist/types.js +2 -0
- package/dist/packages/skills/dist/types.js.map +1 -0
- package/dist/packages/tools/dist/builtins/bash.d.ts +3 -0
- package/dist/packages/tools/dist/builtins/bash.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/bash.js +38 -0
- package/dist/packages/tools/dist/builtins/bash.js.map +1 -0
- package/dist/packages/tools/dist/builtins/file-edit.d.ts +3 -0
- package/dist/packages/tools/dist/builtins/file-edit.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/file-edit.js +45 -0
- package/dist/packages/tools/dist/builtins/file-edit.js.map +1 -0
- package/dist/packages/tools/dist/builtins/file-read.d.ts +3 -0
- package/dist/packages/tools/dist/builtins/file-read.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/file-read.js +39 -0
- package/dist/packages/tools/dist/builtins/file-read.js.map +1 -0
- package/dist/packages/tools/dist/builtins/file-write.d.ts +3 -0
- package/dist/packages/tools/dist/builtins/file-write.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/file-write.js +30 -0
- package/dist/packages/tools/dist/builtins/file-write.js.map +1 -0
- package/dist/packages/tools/dist/builtins/glob.d.ts +3 -0
- package/dist/packages/tools/dist/builtins/glob.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/glob.js +33 -0
- package/dist/packages/tools/dist/builtins/glob.js.map +1 -0
- package/dist/packages/tools/dist/builtins/grep.d.ts +3 -0
- package/dist/packages/tools/dist/builtins/grep.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/grep.js +59 -0
- package/dist/packages/tools/dist/builtins/grep.js.map +1 -0
- package/dist/packages/tools/dist/builtins/index.d.ts +10 -0
- package/dist/packages/tools/dist/builtins/index.d.ts.map +1 -0
- package/dist/packages/tools/dist/builtins/index.js +18 -0
- package/dist/packages/tools/dist/builtins/index.js.map +1 -0
- package/dist/packages/tools/dist/executor.d.ts +11 -0
- package/dist/packages/tools/dist/executor.d.ts.map +1 -0
- package/dist/packages/tools/dist/executor.js +36 -0
- package/dist/packages/tools/dist/executor.js.map +1 -0
- package/dist/packages/tools/dist/index.d.ts +7 -0
- package/dist/packages/tools/dist/index.d.ts.map +1 -0
- package/dist/packages/tools/dist/index.js +6 -0
- package/dist/packages/tools/dist/index.js.map +1 -0
- package/dist/packages/tools/dist/permission.d.ts +17 -0
- package/dist/packages/tools/dist/permission.d.ts.map +1 -0
- package/dist/packages/tools/dist/permission.js +74 -0
- package/dist/packages/tools/dist/permission.js.map +1 -0
- package/dist/packages/tools/dist/registry.d.ts +13 -0
- package/dist/packages/tools/dist/registry.d.ts.map +1 -0
- package/dist/packages/tools/dist/registry.js +34 -0
- package/dist/packages/tools/dist/registry.js.map +1 -0
- package/dist/packages/tools/dist/types.d.ts +28 -0
- package/dist/packages/tools/dist/types.d.ts.map +1 -0
- package/dist/packages/tools/dist/types.js +16 -0
- package/dist/packages/tools/dist/types.js.map +1 -0
- package/package.json +47 -0
- package/scripts/postinstall.mjs +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 HalfCopilot Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# HalfCopilot
|
|
2
|
+
|
|
3
|
+
> Multi-model Agent Framework CLI with Beautiful Chat Interface
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- 🤖 **Multi-model Support**: DeepSeek, Xiaomi MiMo, Qwen, OpenAI, Anthropic
|
|
8
|
+
- 🎨 **Beautiful TUI**: Chat-like interface with colors and animations
|
|
9
|
+
- 🔧 **Built-in Tools**: File operations, command execution, search
|
|
10
|
+
- 🎯 **Skills System**: Extensible skill triggers
|
|
11
|
+
- 🔒 **Permission Control**: Safe command execution
|
|
12
|
+
|
|
13
|
+
## 🚀 Quick Start
|
|
14
|
+
|
|
15
|
+
### Install via npm
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install -g halfcopilot
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Install via pnpm
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pnpm add -g halfcopilot
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### One-line Install (Linux/macOS)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
curl -fsSL https://raw.githubusercontent.com/halfcopilot/halfcopilot/main/install.sh | bash
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### One-line Install (Windows PowerShell)
|
|
34
|
+
|
|
35
|
+
```powershell
|
|
36
|
+
irm https://raw.githubusercontent.com/halfcopilot/halfcopilot/main/install.ps1 | iex
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 📖 Usage
|
|
40
|
+
|
|
41
|
+
### Start Interactive Chat
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
halfcop
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Run Single Command
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
halfcop run "explain this code"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Use Different Models
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Use Xiaomi MiMo
|
|
57
|
+
halfcop --provider xiaomi --model mimo-v2.5-pro
|
|
58
|
+
|
|
59
|
+
# Use DeepSeek
|
|
60
|
+
halfcop --provider deepseek --model deepseek-chat
|
|
61
|
+
|
|
62
|
+
# Use OpenAI
|
|
63
|
+
halfcop --provider openai --model gpt-4o
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### List Available Models
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
halfcop models
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## ⚙️ Configuration
|
|
73
|
+
|
|
74
|
+
Create `~/.halfcopilot/settings.json`:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"defaultProvider": "xiaomi",
|
|
79
|
+
"defaultModel": "mimo-v2.5-pro",
|
|
80
|
+
"providers": {
|
|
81
|
+
"xiaomi": {
|
|
82
|
+
"type": "openai-compatible",
|
|
83
|
+
"baseUrl": "https://token-plan-cn.xiaomimimo.com/v1",
|
|
84
|
+
"apiKey": "YOUR_API_KEY",
|
|
85
|
+
"models": {
|
|
86
|
+
"mimo-v2.5-pro": {
|
|
87
|
+
"contextWindow": 128000,
|
|
88
|
+
"maxOutput": 8192
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"deepseek": {
|
|
93
|
+
"type": "openai-compatible",
|
|
94
|
+
"baseUrl": "https://api.deepseek.com/v1",
|
|
95
|
+
"apiKey": "YOUR_API_KEY",
|
|
96
|
+
"models": {
|
|
97
|
+
"deepseek-chat": {
|
|
98
|
+
"contextWindow": 64000,
|
|
99
|
+
"maxOutput": 8192
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## 🛠️ Built-in Commands
|
|
108
|
+
|
|
109
|
+
| Command | Description |
|
|
110
|
+
|---------|-------------|
|
|
111
|
+
| `halfcop` | Start interactive chat |
|
|
112
|
+
| `halfcop run "prompt"` | Run single prompt |
|
|
113
|
+
| `halfcop models` | List available models |
|
|
114
|
+
| `halfcop doctor` | Check configuration |
|
|
115
|
+
| `halfcop skills` | List available skills |
|
|
116
|
+
|
|
117
|
+
## 🎯 Interactive Commands
|
|
118
|
+
|
|
119
|
+
| Command | Description |
|
|
120
|
+
|---------|-------------|
|
|
121
|
+
| `/model <name>` | Switch model |
|
|
122
|
+
| `/provider <name>` | Switch provider |
|
|
123
|
+
| `/clear` | Clear screen |
|
|
124
|
+
| `/help` | Show help |
|
|
125
|
+
| `exit` | Exit program |
|
|
126
|
+
|
|
127
|
+
## 📦 Supported Models
|
|
128
|
+
|
|
129
|
+
| Provider | Models |
|
|
130
|
+
|----------|--------|
|
|
131
|
+
| Xiaomi | mimo-v2.5-pro, mimo-v2.5 |
|
|
132
|
+
| DeepSeek | deepseek-chat, deepseek-coder |
|
|
133
|
+
| Qwen | qwen-turbo, qwen-plus |
|
|
134
|
+
| OpenAI | gpt-4o, gpt-4o-mini |
|
|
135
|
+
| Anthropic | claude-sonnet-4-20250514 |
|
|
136
|
+
|
|
137
|
+
## 📄 License
|
|
138
|
+
|
|
139
|
+
MIT
|
|
140
|
+
|
|
141
|
+
## 🤝 Contributing
|
|
142
|
+
|
|
143
|
+
Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md).
|
|
144
|
+
|
|
145
|
+
## 📧 Contact
|
|
146
|
+
|
|
147
|
+
- GitHub: [halfcopilot/halfcopilot](https://github.com/halfcopilot/halfcopilot)
|
|
148
|
+
- Issues: [GitHub Issues](https://github.com/halfcopilot/halfcopilot/issues)
|
package/bin/halfcop.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HalfCopilot CLI Entry Point
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { dirname, join } from 'path';
|
|
9
|
+
import { pathToFileURL } from 'url';
|
|
10
|
+
|
|
11
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
12
|
+
const __dirname = dirname(__filename);
|
|
13
|
+
|
|
14
|
+
const mainPath = join(__dirname, '..', 'dist', 'packages', 'cli', 'dist', 'halfcop.js');
|
|
15
|
+
const mainModule = pathToFileURL(mainPath).href;
|
|
16
|
+
|
|
17
|
+
try {
|
|
18
|
+
await import(mainModule);
|
|
19
|
+
} catch (err) {
|
|
20
|
+
console.error('Failed to start HalfCopilot:', err.message);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"halfcop.d.ts","sourceRoot":"","sources":["../src/halfcop.ts"],"names":[],"mappings":";AAEA;;GAEG"}
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* HalfCopilot CLI - Beautiful Chat Interface
|
|
4
|
+
*/
|
|
5
|
+
import { Command } from 'commander';
|
|
6
|
+
import { loadConfig } from '@halfcopilot/config';
|
|
7
|
+
import { ProviderRegistry } from '@halfcopilot/provider';
|
|
8
|
+
import { ToolRegistry, createBuiltinTools, PermissionChecker, ToolExecutor } from '@halfcopilot/tools';
|
|
9
|
+
import { AgentLoop, HybridProvider } from '@halfcopilot/core';
|
|
10
|
+
import { SkillRegistry, createBuiltinSkills } from '@halfcopilot/skills';
|
|
11
|
+
import readline from 'readline';
|
|
12
|
+
const program = new Command();
|
|
13
|
+
program
|
|
14
|
+
.name('halfcop')
|
|
15
|
+
.description('HalfCopilot — Multi-model Agent Framework CLI')
|
|
16
|
+
.version('0.0.1');
|
|
17
|
+
// Beautiful color palette
|
|
18
|
+
const c = {
|
|
19
|
+
reset: '\x1b[0m',
|
|
20
|
+
bold: '\x1b[1m',
|
|
21
|
+
dim: '\x1b[2m',
|
|
22
|
+
// Colors
|
|
23
|
+
cyan: '\x1b[36m',
|
|
24
|
+
green: '\x1b[32m',
|
|
25
|
+
yellow: '\x1b[33m',
|
|
26
|
+
red: '\x1b[31m',
|
|
27
|
+
magenta: '\x1b[35m',
|
|
28
|
+
blue: '\x1b[34m',
|
|
29
|
+
white: '\x1b[37m',
|
|
30
|
+
gray: '\x1b[90m',
|
|
31
|
+
// Background
|
|
32
|
+
bgCyan: '\x1b[46m',
|
|
33
|
+
bgGreen: '\x1b[42m',
|
|
34
|
+
bgYellow: '\x1b[43m',
|
|
35
|
+
bgBlue: '\x1b[44m',
|
|
36
|
+
};
|
|
37
|
+
// Box drawing characters
|
|
38
|
+
const box = {
|
|
39
|
+
tl: '╭',
|
|
40
|
+
tr: '╮',
|
|
41
|
+
bl: '╰',
|
|
42
|
+
br: '╯',
|
|
43
|
+
h: '─',
|
|
44
|
+
v: '│',
|
|
45
|
+
ml: '├',
|
|
46
|
+
mr: '┤',
|
|
47
|
+
};
|
|
48
|
+
function sleep(ms) {
|
|
49
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
50
|
+
}
|
|
51
|
+
// Animated loading indicator
|
|
52
|
+
async function showLoading(message, duration = 1500) {
|
|
53
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
54
|
+
const startTime = Date.now();
|
|
55
|
+
let i = 0;
|
|
56
|
+
process.stdout.write(`\r${c.cyan}${frames[0]} ${message}${c.reset}`);
|
|
57
|
+
while (Date.now() - startTime < duration) {
|
|
58
|
+
await sleep(80);
|
|
59
|
+
i = (i + 1) % frames.length;
|
|
60
|
+
process.stdout.write(`\r${c.cyan}${frames[i]} ${message}${c.reset}`);
|
|
61
|
+
}
|
|
62
|
+
process.stdout.write('\r' + ' '.repeat(message.length + 4) + '\r');
|
|
63
|
+
}
|
|
64
|
+
function printBox(content, color = c.cyan, width = 50) {
|
|
65
|
+
const lines = content.split('\n');
|
|
66
|
+
const maxLen = Math.max(...lines.map(l => l.length), width - 4);
|
|
67
|
+
console.log(`${color}${box.tl}${box.h.repeat(maxLen + 2)}${box.tr}${c.reset}`);
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
const padding = ' '.repeat(maxLen - line.length);
|
|
70
|
+
console.log(`${color}${box.v}${c.reset} ${line}${padding} ${color}${box.v}${c.reset}`);
|
|
71
|
+
}
|
|
72
|
+
console.log(`${color}${box.bl}${box.h.repeat(maxLen + 2)}${box.br}${c.reset}`);
|
|
73
|
+
}
|
|
74
|
+
function printHeader() {
|
|
75
|
+
console.log('');
|
|
76
|
+
console.log(`${c.cyan}${c.bold} ╭─────────────────────────────────────────────────────╮${c.reset}`);
|
|
77
|
+
console.log(`${c.cyan}${c.bold} │ │${c.reset}`);
|
|
78
|
+
console.log(`${c.cyan}${c.bold} │ ██╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██████╗ │${c.reset}`);
|
|
79
|
+
console.log(`${c.cyan}${c.bold} │ ██║ ██║██╔══██╗██║ ██╔════╝██╔═══██╗██╔══██╗ │${c.reset}`);
|
|
80
|
+
console.log(`${c.cyan}${c.bold} │ ███████║███████║██║ ██║ ██║ ██║██████╔╝ │${c.reset}`);
|
|
81
|
+
console.log(`${c.cyan}${c.bold} │ ██╔══██║██╔══██║██║ ██║ ██║ ██║██╔═══╝ │${c.reset}`);
|
|
82
|
+
console.log(`${c.cyan}${c.bold} │ ██║ ██║██║ ██║██║ ╚██████╗╚██████╔╝██║ │${c.reset}`);
|
|
83
|
+
console.log(`${c.cyan}${c.bold} │ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚═════╝ ╚═╝ │${c.reset}`);
|
|
84
|
+
console.log(`${c.cyan}${c.bold} │ │${c.reset}`);
|
|
85
|
+
console.log(`${c.cyan}${c.bold} │ Multi-model Agent Framework CLI │${c.reset}`);
|
|
86
|
+
console.log(`${c.cyan}${c.bold} │ │${c.reset}`);
|
|
87
|
+
console.log(`${c.cyan}${c.bold} ╰─────────────────────────────────────────────────────╯${c.reset}`);
|
|
88
|
+
console.log('');
|
|
89
|
+
}
|
|
90
|
+
function printInfo(label, value) {
|
|
91
|
+
console.log(` ${c.gray}${label}:${c.reset} ${c.white}${c.bold}${value}${c.reset}`);
|
|
92
|
+
}
|
|
93
|
+
function printUserMessage(message) {
|
|
94
|
+
console.log('');
|
|
95
|
+
console.log(` ${c.green}╭─────────────────────────────────────────────────╮${c.reset}`);
|
|
96
|
+
console.log(` ${c.green}│${c.reset} ${c.green}${c.bold}👤 You${c.reset} ${c.green}│${c.reset}`);
|
|
97
|
+
console.log(` ${c.green}├─────────────────────────────────────────────────┤${c.reset}`);
|
|
98
|
+
const lines = message.split('\n');
|
|
99
|
+
for (const line of lines) {
|
|
100
|
+
const padding = ' '.repeat(Math.max(0, 47 - line.length));
|
|
101
|
+
console.log(` ${c.green}│${c.reset} ${line}${padding} ${c.green}│${c.reset}`);
|
|
102
|
+
}
|
|
103
|
+
console.log(` ${c.green}╰─────────────────────────────────────────────────╯${c.reset}`);
|
|
104
|
+
}
|
|
105
|
+
function printAssistantStart() {
|
|
106
|
+
console.log('');
|
|
107
|
+
console.log(` ${c.blue}╭─────────────────────────────────────────────────╮${c.reset}`);
|
|
108
|
+
console.log(` ${c.blue}│${c.reset} ${c.blue}${c.bold}🤖 HalfCopilot${c.reset} ${c.blue}│${c.reset}`);
|
|
109
|
+
console.log(` ${c.blue}├─────────────────────────────────────────────────┤${c.reset}`);
|
|
110
|
+
}
|
|
111
|
+
function printAssistantEnd() {
|
|
112
|
+
console.log(` ${c.blue}╰─────────────────────────────────────────────────╯${c.reset}`);
|
|
113
|
+
console.log('');
|
|
114
|
+
}
|
|
115
|
+
function printAssistantText(text) {
|
|
116
|
+
const lines = text.split('\n');
|
|
117
|
+
for (const line of lines) {
|
|
118
|
+
const padding = ' '.repeat(Math.max(0, 47 - line.length));
|
|
119
|
+
console.log(` ${c.blue}│${c.reset} ${c.white}${line}${padding} ${c.blue}│${c.reset}`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function printThinking() {
|
|
123
|
+
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
124
|
+
return {
|
|
125
|
+
frame: (i) => process.stdout.write(`\r ${c.cyan}${frames[i % frames.length]} ${c.dim}Thinking...${c.reset} `),
|
|
126
|
+
clear: () => process.stdout.write('\r' + ' '.repeat(30) + '\r'),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function createAgent(options = {}) {
|
|
130
|
+
const config = loadConfig();
|
|
131
|
+
const providerRegistry = new ProviderRegistry();
|
|
132
|
+
providerRegistry.createFromConfig(config);
|
|
133
|
+
const providerName = options.provider ?? config.defaultProvider ?? 'xiaomi';
|
|
134
|
+
let provider = providerRegistry.get(providerName);
|
|
135
|
+
if (options.hybrid) {
|
|
136
|
+
provider = new HybridProvider(provider);
|
|
137
|
+
}
|
|
138
|
+
const toolRegistry = new ToolRegistry();
|
|
139
|
+
const builtinTools = createBuiltinTools();
|
|
140
|
+
builtinTools.forEach(t => toolRegistry.register(t));
|
|
141
|
+
const skillRegistry = new SkillRegistry();
|
|
142
|
+
const builtinSkills = createBuiltinSkills();
|
|
143
|
+
builtinSkills.forEach(s => skillRegistry.register(s));
|
|
144
|
+
const permissions = new PermissionChecker({
|
|
145
|
+
autoApproveSafe: config.permissions.autoApproveSafe,
|
|
146
|
+
allow: config.permissions.allow,
|
|
147
|
+
deny: config.permissions.deny,
|
|
148
|
+
});
|
|
149
|
+
const rl = readline.createInterface({
|
|
150
|
+
input: process.stdin,
|
|
151
|
+
output: process.stdout,
|
|
152
|
+
});
|
|
153
|
+
const executor = new ToolExecutor(toolRegistry, permissions, async (toolName, input) => {
|
|
154
|
+
// This should rarely be called now due to auto-approval
|
|
155
|
+
return new Promise((resolve) => {
|
|
156
|
+
rl.question(`${c.yellow} ⚠️ Allow ${toolName}? (y/n): ${c.reset}`, (answer) => {
|
|
157
|
+
resolve(answer.toLowerCase().trim() === 'y');
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
const modelName = options.model ?? config.defaultModel ?? 'mimo-v2.5-pro';
|
|
162
|
+
const agent = new AgentLoop({
|
|
163
|
+
provider,
|
|
164
|
+
providerName,
|
|
165
|
+
model: modelName,
|
|
166
|
+
tools: toolRegistry,
|
|
167
|
+
executor,
|
|
168
|
+
permissions,
|
|
169
|
+
maxTurns: config.maxTurns,
|
|
170
|
+
mode: options.mode ?? 'auto',
|
|
171
|
+
});
|
|
172
|
+
return { agent, providerName, config, skillRegistry, modelName, rl };
|
|
173
|
+
}
|
|
174
|
+
async function runInteractive(options = {}) {
|
|
175
|
+
const { agent, providerName, config, skillRegistry, modelName, rl } = createAgent(options);
|
|
176
|
+
// Print beautiful header
|
|
177
|
+
printHeader();
|
|
178
|
+
printInfo('Provider', providerName);
|
|
179
|
+
printInfo('Model', modelName);
|
|
180
|
+
printInfo('Mode', options.mode ?? 'auto');
|
|
181
|
+
console.log('');
|
|
182
|
+
console.log(` ${c.dim}Type your message and press Enter. Type "exit" to quit.${c.reset}`);
|
|
183
|
+
console.log(` ${c.dim}Commands: /model <name> | /provider <name> | /clear | /help${c.reset}`);
|
|
184
|
+
console.log('');
|
|
185
|
+
const thinking = printThinking();
|
|
186
|
+
let isProcessing = false;
|
|
187
|
+
let thinkingInterval = null;
|
|
188
|
+
const startThinking = () => {
|
|
189
|
+
isProcessing = true;
|
|
190
|
+
let i = 0;
|
|
191
|
+
thinkingInterval = setInterval(() => {
|
|
192
|
+
thinking.frame(i++);
|
|
193
|
+
}, 80);
|
|
194
|
+
};
|
|
195
|
+
const stopThinking = () => {
|
|
196
|
+
isProcessing = false;
|
|
197
|
+
if (thinkingInterval) {
|
|
198
|
+
clearInterval(thinkingInterval);
|
|
199
|
+
thinkingInterval = null;
|
|
200
|
+
}
|
|
201
|
+
thinking.clear();
|
|
202
|
+
};
|
|
203
|
+
const ask = () => {
|
|
204
|
+
rl.question(`${c.green}${c.bold} ❯ ${c.reset}`, async (input) => {
|
|
205
|
+
const trimmed = input.trim();
|
|
206
|
+
// Handle commands
|
|
207
|
+
if (trimmed.startsWith('/')) {
|
|
208
|
+
handleCommand(trimmed, options);
|
|
209
|
+
ask();
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
if (trimmed.toLowerCase() === 'exit' || trimmed.toLowerCase() === 'quit') {
|
|
213
|
+
console.log('');
|
|
214
|
+
console.log(` ${c.yellow}Goodbye! 👋${c.reset}`);
|
|
215
|
+
console.log('');
|
|
216
|
+
rl.close();
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
if (trimmed === '') {
|
|
220
|
+
ask();
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// Show user message
|
|
224
|
+
printUserMessage(trimmed);
|
|
225
|
+
console.log('');
|
|
226
|
+
// Start thinking animation
|
|
227
|
+
startThinking();
|
|
228
|
+
let isFirstChunk = true;
|
|
229
|
+
let hasOutput = false;
|
|
230
|
+
try {
|
|
231
|
+
for await (const event of agent.run(trimmed)) {
|
|
232
|
+
switch (event.type) {
|
|
233
|
+
case 'text':
|
|
234
|
+
if (isFirstChunk) {
|
|
235
|
+
stopThinking();
|
|
236
|
+
printAssistantStart();
|
|
237
|
+
isFirstChunk = false;
|
|
238
|
+
}
|
|
239
|
+
hasOutput = true;
|
|
240
|
+
// Don't print newlines before text
|
|
241
|
+
process.stdout.write(` ${c.blue}│${c.reset} ${c.white}`);
|
|
242
|
+
process.stdout.write(event.content ?? '');
|
|
243
|
+
process.stdout.write(`${c.reset}`);
|
|
244
|
+
break;
|
|
245
|
+
case 'tool_use':
|
|
246
|
+
// Hide tool calls - just keep thinking
|
|
247
|
+
break;
|
|
248
|
+
case 'tool_result':
|
|
249
|
+
// Hide tool results
|
|
250
|
+
break;
|
|
251
|
+
case 'error':
|
|
252
|
+
stopThinking();
|
|
253
|
+
if (!isFirstChunk)
|
|
254
|
+
printAssistantEnd();
|
|
255
|
+
console.log(` ${c.red}❌ Error: ${event.error?.message}${c.reset}`);
|
|
256
|
+
console.log('');
|
|
257
|
+
break;
|
|
258
|
+
case 'done':
|
|
259
|
+
if (!isFirstChunk && hasOutput) {
|
|
260
|
+
// Print the closing line
|
|
261
|
+
const padding = ' '.repeat(47);
|
|
262
|
+
console.log(` ${c.blue}│${c.reset}${padding} ${c.blue}│${c.reset}`);
|
|
263
|
+
printAssistantEnd();
|
|
264
|
+
}
|
|
265
|
+
else if (isFirstChunk) {
|
|
266
|
+
stopThinking();
|
|
267
|
+
}
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
catch (err) {
|
|
273
|
+
stopThinking();
|
|
274
|
+
console.log(` ${c.red}❌ Error: ${err instanceof Error ? err.message : err}${c.reset}`);
|
|
275
|
+
}
|
|
276
|
+
ask();
|
|
277
|
+
});
|
|
278
|
+
};
|
|
279
|
+
function handleCommand(cmd, opts) {
|
|
280
|
+
const parts = cmd.split(' ');
|
|
281
|
+
const command = parts[0].toLowerCase();
|
|
282
|
+
const arg = parts.slice(1).join(' ');
|
|
283
|
+
switch (command) {
|
|
284
|
+
case '/model':
|
|
285
|
+
if (arg) {
|
|
286
|
+
opts.model = arg;
|
|
287
|
+
console.log(` ${c.green}✓ Model changed to: ${arg}${c.reset}`);
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
console.log(` ${c.yellow}Current model: ${modelName}${c.reset}`);
|
|
291
|
+
console.log(` ${c.dim}Usage: /model <model-name>${c.reset}`);
|
|
292
|
+
}
|
|
293
|
+
break;
|
|
294
|
+
case '/provider':
|
|
295
|
+
if (arg) {
|
|
296
|
+
opts.provider = arg;
|
|
297
|
+
console.log(` ${c.green}✓ Provider changed to: ${arg}${c.reset}`);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
console.log(` ${c.yellow}Current provider: ${providerName}${c.reset}`);
|
|
301
|
+
console.log(` ${c.dim}Usage: /provider <provider-name>${c.reset}`);
|
|
302
|
+
}
|
|
303
|
+
break;
|
|
304
|
+
case '/clear':
|
|
305
|
+
console.clear();
|
|
306
|
+
printHeader();
|
|
307
|
+
break;
|
|
308
|
+
case '/help':
|
|
309
|
+
console.log('');
|
|
310
|
+
console.log(` ${c.cyan}Available Commands:${c.reset}`);
|
|
311
|
+
console.log(` ${c.white}/model <name>${c.reset} - Switch model`);
|
|
312
|
+
console.log(` ${c.white}/provider <name>${c.reset} - Switch provider`);
|
|
313
|
+
console.log(` ${c.white}/clear${c.reset} - Clear screen`);
|
|
314
|
+
console.log(` ${c.white}/help${c.reset} - Show this help`);
|
|
315
|
+
console.log(` ${c.white}/exit${c.reset} - Exit the program`);
|
|
316
|
+
console.log('');
|
|
317
|
+
break;
|
|
318
|
+
default:
|
|
319
|
+
console.log(` ${c.red}Unknown command: ${command}${c.reset}`);
|
|
320
|
+
console.log(` ${c.dim}Type /help for available commands${c.reset}`);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
ask();
|
|
324
|
+
}
|
|
325
|
+
async function runSingle(prompt, options = {}) {
|
|
326
|
+
const { agent, rl } = createAgent(options);
|
|
327
|
+
const thinking = printThinking();
|
|
328
|
+
let isFirstChunk = true;
|
|
329
|
+
try {
|
|
330
|
+
for await (const event of agent.run(prompt)) {
|
|
331
|
+
switch (event.type) {
|
|
332
|
+
case 'text':
|
|
333
|
+
if (isFirstChunk) {
|
|
334
|
+
thinking.clear();
|
|
335
|
+
isFirstChunk = false;
|
|
336
|
+
}
|
|
337
|
+
process.stdout.write(event.content ?? '');
|
|
338
|
+
break;
|
|
339
|
+
case 'tool_use':
|
|
340
|
+
case 'tool_result':
|
|
341
|
+
// Hide tool calls
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
console.log('');
|
|
346
|
+
}
|
|
347
|
+
catch (err) {
|
|
348
|
+
thinking.clear();
|
|
349
|
+
console.error(`Error: ${err instanceof Error ? err.message : err}`);
|
|
350
|
+
}
|
|
351
|
+
rl.close();
|
|
352
|
+
}
|
|
353
|
+
// Default command
|
|
354
|
+
program
|
|
355
|
+
.argument('[prompt]', 'Optional prompt to start with')
|
|
356
|
+
.option('-m, --model <model>', 'Model to use')
|
|
357
|
+
.option('-p, --provider <provider>', 'Provider to use')
|
|
358
|
+
.option('--mode <mode>', 'Agent mode (plan/review/act/auto)', 'auto')
|
|
359
|
+
.option('--hybrid', 'Enable hybrid mode')
|
|
360
|
+
.action(async (prompt, options) => {
|
|
361
|
+
if (prompt) {
|
|
362
|
+
await runSingle(prompt, options);
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
await runInteractive(options);
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
// Subcommands
|
|
369
|
+
program
|
|
370
|
+
.command('chat')
|
|
371
|
+
.description('Start interactive chat mode')
|
|
372
|
+
.option('-m, --model <model>', 'Model to use')
|
|
373
|
+
.option('-p, --provider <provider>', 'Provider to use')
|
|
374
|
+
.option('--mode <mode>', 'Agent mode (plan/review/act/auto)', 'auto')
|
|
375
|
+
.option('--hybrid', 'Enable hybrid mode')
|
|
376
|
+
.action(async (options) => {
|
|
377
|
+
await runInteractive(options);
|
|
378
|
+
});
|
|
379
|
+
program
|
|
380
|
+
.command('run <prompt>')
|
|
381
|
+
.description('Run a single prompt and exit')
|
|
382
|
+
.option('-m, --model <model>', 'Model to use')
|
|
383
|
+
.option('-p, --provider <provider>', 'Provider to use')
|
|
384
|
+
.option('--mode <mode>', 'Agent mode (plan/review/act/auto)', 'act')
|
|
385
|
+
.option('--hybrid', 'Enable hybrid mode')
|
|
386
|
+
.action(async (prompt, options) => {
|
|
387
|
+
await runSingle(prompt, options);
|
|
388
|
+
process.exit(0);
|
|
389
|
+
});
|
|
390
|
+
program
|
|
391
|
+
.command('models')
|
|
392
|
+
.description('List available models')
|
|
393
|
+
.action(() => {
|
|
394
|
+
console.log('');
|
|
395
|
+
console.log(` ${c.cyan}${c.bold}Available Models:${c.reset}`);
|
|
396
|
+
console.log('');
|
|
397
|
+
const config = loadConfig();
|
|
398
|
+
for (const [provider, pConfig] of Object.entries(config.providers)) {
|
|
399
|
+
console.log(` ${c.green}${c.bold}${provider}${c.reset}`);
|
|
400
|
+
for (const model of Object.keys(pConfig.models)) {
|
|
401
|
+
console.log(` ${c.white}• ${model}${c.reset}`);
|
|
402
|
+
}
|
|
403
|
+
console.log('');
|
|
404
|
+
}
|
|
405
|
+
});
|
|
406
|
+
program
|
|
407
|
+
.command('doctor')
|
|
408
|
+
.description('Check configuration and environment')
|
|
409
|
+
.action(() => {
|
|
410
|
+
console.log('');
|
|
411
|
+
console.log(` ${c.cyan}${c.bold}HalfCopilot Doctor${c.reset}`);
|
|
412
|
+
console.log('');
|
|
413
|
+
try {
|
|
414
|
+
const config = loadConfig();
|
|
415
|
+
console.log(` ${c.green}✓${c.reset} Configuration loaded`);
|
|
416
|
+
console.log(` ${c.green}✓${c.reset} Providers: ${Object.keys(config.providers).join(', ')}`);
|
|
417
|
+
console.log(` ${c.green}✓${c.reset} Default: ${config.defaultProvider}/${config.defaultModel}`);
|
|
418
|
+
const toolRegistry = new ToolRegistry();
|
|
419
|
+
createBuiltinTools().forEach(t => toolRegistry.register(t));
|
|
420
|
+
console.log(` ${c.green}✓${c.reset} Tools: ${toolRegistry.list().length} available`);
|
|
421
|
+
const skillRegistry = new SkillRegistry();
|
|
422
|
+
createBuiltinSkills().forEach(s => skillRegistry.register(s));
|
|
423
|
+
console.log(` ${c.green}✓${c.reset} Skills: ${skillRegistry.list().length} available`);
|
|
424
|
+
console.log('');
|
|
425
|
+
console.log(` ${c.green}${c.bold}All checks passed! ✓${c.reset}`);
|
|
426
|
+
console.log('');
|
|
427
|
+
}
|
|
428
|
+
catch (err) {
|
|
429
|
+
console.log(` ${c.red}✗ Error: ${err instanceof Error ? err.message : err}${c.reset}`);
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
program
|
|
433
|
+
.command('skills')
|
|
434
|
+
.description('List available skills')
|
|
435
|
+
.action(() => {
|
|
436
|
+
const skillRegistry = new SkillRegistry();
|
|
437
|
+
createBuiltinSkills().forEach(s => skillRegistry.register(s));
|
|
438
|
+
console.log('');
|
|
439
|
+
console.log(` ${c.cyan}${c.bold}Available Skills:${c.reset}`);
|
|
440
|
+
console.log('');
|
|
441
|
+
for (const skill of skillRegistry.list()) {
|
|
442
|
+
console.log(` ${c.green}• ${skill.name}${c.reset}`);
|
|
443
|
+
console.log(` ${c.dim}${skill.description}${c.reset}`);
|
|
444
|
+
}
|
|
445
|
+
console.log('');
|
|
446
|
+
});
|
|
447
|
+
program.parse();
|
|
448
|
+
//# sourceMappingURL=halfcop.js.map
|