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.
Files changed (226) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/bin/halfcop.js +22 -0
  4. package/dist/index.js +3 -0
  5. package/dist/packages/cli/dist/halfcop.d.ts +6 -0
  6. package/dist/packages/cli/dist/halfcop.d.ts.map +1 -0
  7. package/dist/packages/cli/dist/halfcop.js +448 -0
  8. package/dist/packages/cli/dist/halfcop.js.map +1 -0
  9. package/dist/packages/cli/dist/index.d.ts +3 -0
  10. package/dist/packages/cli/dist/index.d.ts.map +1 -0
  11. package/dist/packages/cli/dist/index.js +251 -0
  12. package/dist/packages/cli/dist/index.js.map +1 -0
  13. package/dist/packages/cli/dist/tui/app.d.ts +11 -0
  14. package/dist/packages/cli/dist/tui/app.d.ts.map +1 -0
  15. package/dist/packages/cli/dist/tui/app.js +72 -0
  16. package/dist/packages/cli/dist/tui/app.js.map +1 -0
  17. package/dist/packages/cli/dist/tui/components/ChatView.d.ts +12 -0
  18. package/dist/packages/cli/dist/tui/components/ChatView.d.ts.map +1 -0
  19. package/dist/packages/cli/dist/tui/components/ChatView.js +6 -0
  20. package/dist/packages/cli/dist/tui/components/ChatView.js.map +1 -0
  21. package/dist/packages/cli/dist/tui/components/InputField.d.ts +8 -0
  22. package/dist/packages/cli/dist/tui/components/InputField.d.ts.map +1 -0
  23. package/dist/packages/cli/dist/tui/components/InputField.js +22 -0
  24. package/dist/packages/cli/dist/tui/components/InputField.js.map +1 -0
  25. package/dist/packages/cli/dist/tui/components/StatusBar.d.ts +13 -0
  26. package/dist/packages/cli/dist/tui/components/StatusBar.d.ts.map +1 -0
  27. package/dist/packages/cli/dist/tui/components/StatusBar.js +6 -0
  28. package/dist/packages/cli/dist/tui/components/StatusBar.js.map +1 -0
  29. package/dist/packages/cli/dist/tui/components/ToolApproval.d.ts +10 -0
  30. package/dist/packages/cli/dist/tui/components/ToolApproval.d.ts.map +1 -0
  31. package/dist/packages/cli/dist/tui/components/ToolApproval.js +14 -0
  32. package/dist/packages/cli/dist/tui/components/ToolApproval.js.map +1 -0
  33. package/dist/packages/cli/dist/tui/components/index.d.ts +5 -0
  34. package/dist/packages/cli/dist/tui/components/index.d.ts.map +1 -0
  35. package/dist/packages/cli/dist/tui/components/index.js +5 -0
  36. package/dist/packages/cli/dist/tui/components/index.js.map +1 -0
  37. package/dist/packages/cli/dist/tui/index.d.ts +3 -0
  38. package/dist/packages/cli/dist/tui/index.d.ts.map +1 -0
  39. package/dist/packages/cli/dist/tui/index.js +3 -0
  40. package/dist/packages/cli/dist/tui/index.js.map +1 -0
  41. package/dist/packages/config/dist/defaults.d.ts +3 -0
  42. package/dist/packages/config/dist/defaults.d.ts.map +1 -0
  43. package/dist/packages/config/dist/defaults.js +30 -0
  44. package/dist/packages/config/dist/defaults.js.map +1 -0
  45. package/dist/packages/config/dist/index.d.ts +4 -0
  46. package/dist/packages/config/dist/index.d.ts.map +1 -0
  47. package/dist/packages/config/dist/index.js +4 -0
  48. package/dist/packages/config/dist/index.js.map +1 -0
  49. package/dist/packages/config/dist/loader.d.ts +4 -0
  50. package/dist/packages/config/dist/loader.d.ts.map +1 -0
  51. package/dist/packages/config/dist/loader.js +80 -0
  52. package/dist/packages/config/dist/loader.js.map +1 -0
  53. package/dist/packages/config/dist/schema.d.ts +323 -0
  54. package/dist/packages/config/dist/schema.d.ts.map +1 -0
  55. package/dist/packages/config/dist/schema.js +56 -0
  56. package/dist/packages/config/dist/schema.js.map +1 -0
  57. package/dist/packages/core/dist/agent-loop.d.ts +19 -0
  58. package/dist/packages/core/dist/agent-loop.d.ts.map +1 -0
  59. package/dist/packages/core/dist/agent-loop.js +140 -0
  60. package/dist/packages/core/dist/agent-loop.js.map +1 -0
  61. package/dist/packages/core/dist/conversation.d.ts +22 -0
  62. package/dist/packages/core/dist/conversation.d.ts.map +1 -0
  63. package/dist/packages/core/dist/conversation.js +66 -0
  64. package/dist/packages/core/dist/conversation.js.map +1 -0
  65. package/dist/packages/core/dist/hybrid/index.d.ts +4 -0
  66. package/dist/packages/core/dist/hybrid/index.d.ts.map +1 -0
  67. package/dist/packages/core/dist/hybrid/index.js +4 -0
  68. package/dist/packages/core/dist/hybrid/index.js.map +1 -0
  69. package/dist/packages/core/dist/hybrid/mapper.d.ts +11 -0
  70. package/dist/packages/core/dist/hybrid/mapper.d.ts.map +1 -0
  71. package/dist/packages/core/dist/hybrid/mapper.js +53 -0
  72. package/dist/packages/core/dist/hybrid/mapper.js.map +1 -0
  73. package/dist/packages/core/dist/hybrid/parser.d.ts +36 -0
  74. package/dist/packages/core/dist/hybrid/parser.d.ts.map +1 -0
  75. package/dist/packages/core/dist/hybrid/parser.js +118 -0
  76. package/dist/packages/core/dist/hybrid/parser.js.map +1 -0
  77. package/dist/packages/core/dist/hybrid/provider.d.ts +14 -0
  78. package/dist/packages/core/dist/hybrid/provider.d.ts.map +1 -0
  79. package/dist/packages/core/dist/hybrid/provider.js +109 -0
  80. package/dist/packages/core/dist/hybrid/provider.js.map +1 -0
  81. package/dist/packages/core/dist/index.d.ts +5 -0
  82. package/dist/packages/core/dist/index.d.ts.map +1 -0
  83. package/dist/packages/core/dist/index.js +5 -0
  84. package/dist/packages/core/dist/index.js.map +1 -0
  85. package/dist/packages/core/dist/types.d.ts +36 -0
  86. package/dist/packages/core/dist/types.d.ts.map +1 -0
  87. package/dist/packages/core/dist/types.js +11 -0
  88. package/dist/packages/core/dist/types.js.map +1 -0
  89. package/dist/packages/mcp/dist/adapter.d.ts +15 -0
  90. package/dist/packages/mcp/dist/adapter.d.ts.map +1 -0
  91. package/dist/packages/mcp/dist/adapter.js +44 -0
  92. package/dist/packages/mcp/dist/adapter.js.map +1 -0
  93. package/dist/packages/mcp/dist/client.d.ts +31 -0
  94. package/dist/packages/mcp/dist/client.d.ts.map +1 -0
  95. package/dist/packages/mcp/dist/client.js +140 -0
  96. package/dist/packages/mcp/dist/client.js.map +1 -0
  97. package/dist/packages/mcp/dist/index.d.ts +6 -0
  98. package/dist/packages/mcp/dist/index.d.ts.map +1 -0
  99. package/dist/packages/mcp/dist/index.js +4 -0
  100. package/dist/packages/mcp/dist/index.js.map +1 -0
  101. package/dist/packages/mcp/dist/transport.d.ts +47 -0
  102. package/dist/packages/mcp/dist/transport.d.ts.map +1 -0
  103. package/dist/packages/mcp/dist/transport.js +123 -0
  104. package/dist/packages/mcp/dist/transport.js.map +1 -0
  105. package/dist/packages/mcp/dist/types.d.ts +64 -0
  106. package/dist/packages/mcp/dist/types.d.ts.map +1 -0
  107. package/dist/packages/mcp/dist/types.js +2 -0
  108. package/dist/packages/mcp/dist/types.js.map +1 -0
  109. package/dist/packages/memory/dist/index.d.ts +3 -0
  110. package/dist/packages/memory/dist/index.d.ts.map +1 -0
  111. package/dist/packages/memory/dist/index.js +2 -0
  112. package/dist/packages/memory/dist/index.js.map +1 -0
  113. package/dist/packages/memory/dist/store.d.ts +15 -0
  114. package/dist/packages/memory/dist/store.d.ts.map +1 -0
  115. package/dist/packages/memory/dist/store.js +93 -0
  116. package/dist/packages/memory/dist/store.js.map +1 -0
  117. package/dist/packages/memory/dist/types.d.ts +14 -0
  118. package/dist/packages/memory/dist/types.d.ts.map +1 -0
  119. package/dist/packages/memory/dist/types.js +2 -0
  120. package/dist/packages/memory/dist/types.js.map +1 -0
  121. package/dist/packages/provider/dist/anthropic.d.ts +21 -0
  122. package/dist/packages/provider/dist/anthropic.d.ts.map +1 -0
  123. package/dist/packages/provider/dist/anthropic.js +148 -0
  124. package/dist/packages/provider/dist/anthropic.js.map +1 -0
  125. package/dist/packages/provider/dist/base.d.ts +16 -0
  126. package/dist/packages/provider/dist/base.d.ts.map +1 -0
  127. package/dist/packages/provider/dist/base.js +9 -0
  128. package/dist/packages/provider/dist/base.js.map +1 -0
  129. package/dist/packages/provider/dist/index.d.ts +6 -0
  130. package/dist/packages/provider/dist/index.d.ts.map +1 -0
  131. package/dist/packages/provider/dist/index.js +5 -0
  132. package/dist/packages/provider/dist/index.js.map +1 -0
  133. package/dist/packages/provider/dist/openai.d.ts +23 -0
  134. package/dist/packages/provider/dist/openai.d.ts.map +1 -0
  135. package/dist/packages/provider/dist/openai.js +171 -0
  136. package/dist/packages/provider/dist/openai.js.map +1 -0
  137. package/dist/packages/provider/dist/registry.d.ts +11 -0
  138. package/dist/packages/provider/dist/registry.d.ts.map +1 -0
  139. package/dist/packages/provider/dist/registry.js +61 -0
  140. package/dist/packages/provider/dist/registry.js.map +1 -0
  141. package/dist/packages/provider/dist/types.d.ts +84 -0
  142. package/dist/packages/provider/dist/types.d.ts.map +1 -0
  143. package/dist/packages/provider/dist/types.js +3 -0
  144. package/dist/packages/provider/dist/types.js.map +1 -0
  145. package/dist/packages/shared/dist/errors.d.ts +18 -0
  146. package/dist/packages/shared/dist/errors.d.ts.map +1 -0
  147. package/dist/packages/shared/dist/errors.js +35 -0
  148. package/dist/packages/shared/dist/errors.js.map +1 -0
  149. package/dist/packages/shared/dist/index.d.ts +4 -0
  150. package/dist/packages/shared/dist/index.d.ts.map +1 -0
  151. package/dist/packages/shared/dist/index.js +4 -0
  152. package/dist/packages/shared/dist/index.js.map +1 -0
  153. package/dist/packages/shared/dist/logger.d.ts +18 -0
  154. package/dist/packages/shared/dist/logger.d.ts.map +1 -0
  155. package/dist/packages/shared/dist/logger.js +39 -0
  156. package/dist/packages/shared/dist/logger.js.map +1 -0
  157. package/dist/packages/shared/dist/utils.d.ts +5 -0
  158. package/dist/packages/shared/dist/utils.d.ts.map +1 -0
  159. package/dist/packages/shared/dist/utils.js +27 -0
  160. package/dist/packages/shared/dist/utils.js.map +1 -0
  161. package/dist/packages/skills/dist/builtins.d.ts +8 -0
  162. package/dist/packages/skills/dist/builtins.d.ts.map +1 -0
  163. package/dist/packages/skills/dist/builtins.js +144 -0
  164. package/dist/packages/skills/dist/builtins.js.map +1 -0
  165. package/dist/packages/skills/dist/index.d.ts +4 -0
  166. package/dist/packages/skills/dist/index.d.ts.map +1 -0
  167. package/dist/packages/skills/dist/index.js +3 -0
  168. package/dist/packages/skills/dist/index.js.map +1 -0
  169. package/dist/packages/skills/dist/registry.d.ts +13 -0
  170. package/dist/packages/skills/dist/registry.d.ts.map +1 -0
  171. package/dist/packages/skills/dist/registry.js +93 -0
  172. package/dist/packages/skills/dist/registry.js.map +1 -0
  173. package/dist/packages/skills/dist/types.d.ts +35 -0
  174. package/dist/packages/skills/dist/types.d.ts.map +1 -0
  175. package/dist/packages/skills/dist/types.js +2 -0
  176. package/dist/packages/skills/dist/types.js.map +1 -0
  177. package/dist/packages/tools/dist/builtins/bash.d.ts +3 -0
  178. package/dist/packages/tools/dist/builtins/bash.d.ts.map +1 -0
  179. package/dist/packages/tools/dist/builtins/bash.js +38 -0
  180. package/dist/packages/tools/dist/builtins/bash.js.map +1 -0
  181. package/dist/packages/tools/dist/builtins/file-edit.d.ts +3 -0
  182. package/dist/packages/tools/dist/builtins/file-edit.d.ts.map +1 -0
  183. package/dist/packages/tools/dist/builtins/file-edit.js +45 -0
  184. package/dist/packages/tools/dist/builtins/file-edit.js.map +1 -0
  185. package/dist/packages/tools/dist/builtins/file-read.d.ts +3 -0
  186. package/dist/packages/tools/dist/builtins/file-read.d.ts.map +1 -0
  187. package/dist/packages/tools/dist/builtins/file-read.js +39 -0
  188. package/dist/packages/tools/dist/builtins/file-read.js.map +1 -0
  189. package/dist/packages/tools/dist/builtins/file-write.d.ts +3 -0
  190. package/dist/packages/tools/dist/builtins/file-write.d.ts.map +1 -0
  191. package/dist/packages/tools/dist/builtins/file-write.js +30 -0
  192. package/dist/packages/tools/dist/builtins/file-write.js.map +1 -0
  193. package/dist/packages/tools/dist/builtins/glob.d.ts +3 -0
  194. package/dist/packages/tools/dist/builtins/glob.d.ts.map +1 -0
  195. package/dist/packages/tools/dist/builtins/glob.js +33 -0
  196. package/dist/packages/tools/dist/builtins/glob.js.map +1 -0
  197. package/dist/packages/tools/dist/builtins/grep.d.ts +3 -0
  198. package/dist/packages/tools/dist/builtins/grep.d.ts.map +1 -0
  199. package/dist/packages/tools/dist/builtins/grep.js +59 -0
  200. package/dist/packages/tools/dist/builtins/grep.js.map +1 -0
  201. package/dist/packages/tools/dist/builtins/index.d.ts +10 -0
  202. package/dist/packages/tools/dist/builtins/index.d.ts.map +1 -0
  203. package/dist/packages/tools/dist/builtins/index.js +18 -0
  204. package/dist/packages/tools/dist/builtins/index.js.map +1 -0
  205. package/dist/packages/tools/dist/executor.d.ts +11 -0
  206. package/dist/packages/tools/dist/executor.d.ts.map +1 -0
  207. package/dist/packages/tools/dist/executor.js +36 -0
  208. package/dist/packages/tools/dist/executor.js.map +1 -0
  209. package/dist/packages/tools/dist/index.d.ts +7 -0
  210. package/dist/packages/tools/dist/index.d.ts.map +1 -0
  211. package/dist/packages/tools/dist/index.js +6 -0
  212. package/dist/packages/tools/dist/index.js.map +1 -0
  213. package/dist/packages/tools/dist/permission.d.ts +17 -0
  214. package/dist/packages/tools/dist/permission.d.ts.map +1 -0
  215. package/dist/packages/tools/dist/permission.js +74 -0
  216. package/dist/packages/tools/dist/permission.js.map +1 -0
  217. package/dist/packages/tools/dist/registry.d.ts +13 -0
  218. package/dist/packages/tools/dist/registry.d.ts.map +1 -0
  219. package/dist/packages/tools/dist/registry.js +34 -0
  220. package/dist/packages/tools/dist/registry.js.map +1 -0
  221. package/dist/packages/tools/dist/types.d.ts +28 -0
  222. package/dist/packages/tools/dist/types.d.ts.map +1 -0
  223. package/dist/packages/tools/dist/types.js +16 -0
  224. package/dist/packages/tools/dist/types.js.map +1 -0
  225. package/package.json +47 -0
  226. 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,3 @@
1
+
2
+ // HalfCopilot CLI Main Entry
3
+ export * from './packages/cli/dist/halfcop.js';
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * HalfCopilot CLI - Beautiful Chat Interface
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=halfcop.d.ts.map
@@ -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