agentk8 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -259
- package/dist/components/App.js +15 -10
- package/dist/components/Banner.js +12 -12
- package/dist/components/ChatMessage.js +14 -10
- package/dist/components/Input.js +67 -2
- package/dist/components/StatusBar.js +12 -8
- package/dist/components/ThinkingIndicator.d.ts +7 -0
- package/dist/components/ThinkingIndicator.js +59 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/lib/claude.js +163 -31
- package/dist/themes/retro.d.ts +3 -0
- package/dist/themes/retro.js +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,331 +3,183 @@
|
|
|
3
3
|
**Multi-Agent Claude Code Terminal Suite**
|
|
4
4
|
|
|
5
5
|
```
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
|
|
7
|
+
◇ ─── AGENT-K ─── ◇ ─ Multi-Agent Intelligence System ─────────────── v2.0.0
|
|
8
|
+
─────────────────────────────────────────────────────────────────────────────────
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
## What is AGENT-K?
|
|
14
|
-
|
|
15
|
-
AGENT-K extends Claude Code with **multi-agent orchestration**. Instead of a single AI assistant, you get a coordinated team of specialists - each with domain expertise, working together on complex tasks.
|
|
16
|
-
|
|
17
|
-
```
|
|
18
|
-
╭─ You ────────────────────────────────────────────────────────────────────────────╮
|
|
19
|
-
│ Build a secure REST API with user authentication │
|
|
20
|
-
╰──────────────────────────────────────────────────────────────────────────────────╯
|
|
21
|
-
|
|
22
|
-
╭─ Orchestrator ───────────────────────────────────────────────────────────────────╮
|
|
23
|
-
│ Breaking down task... │
|
|
24
|
-
│ → Engineer: Implement REST endpoints and JWT authentication │
|
|
25
|
-
│ → Tester: Write API integration tests │
|
|
26
|
-
│ → Security: Review for OWASP vulnerabilities │
|
|
27
|
-
│ → Scout: Find latest best practices for JWT in 2025 │
|
|
28
|
-
╰──────────────────────────────────────────────────────────────────────────────────╯
|
|
29
|
-
|
|
30
|
-
[●] Orchestrator Coordinating
|
|
31
|
-
[◐] Engineer Writing src/api/auth.py...
|
|
32
|
-
[◐] Scout Searching for JWT best practices...
|
|
33
|
-
[ ] Tester Waiting for implementation
|
|
34
|
-
[ ] Security Queued for review
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Why AGENT-K?
|
|
38
|
-
|
|
39
|
-
### The Problem
|
|
40
|
-
|
|
41
|
-
Claude is brilliant, but complex tasks often require:
|
|
42
|
-
- **Multiple perspectives** (implementation, testing, security)
|
|
43
|
-
- **Parallel work** (why write tests sequentially after code?)
|
|
44
|
-
- **Up-to-date information** (Claude's training data becomes stale)
|
|
45
|
-
- **Specialized focus** (security reviews need different prompts than coding)
|
|
46
|
-
|
|
47
|
-
### The Solution
|
|
48
|
-
|
|
49
|
-
AGENT-K spawns specialized Claude agents that:
|
|
50
|
-
- **Work in parallel** on different aspects of your task
|
|
51
|
-
- **Coordinate automatically** through a central orchestrator
|
|
52
|
-
- **Stay current** with a dedicated Scout agent for real-time research
|
|
53
|
-
- **Follow best practices** with domain-specific system prompts
|
|
11
|
+
A sophisticated terminal UI for orchestrating Claude AI agents. Built with React + Ink, featuring a beautiful dark theme and intelligent task analysis.
|
|
54
12
|
|
|
55
13
|
## Features
|
|
56
14
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
| **Scout Agent** | Real-time web/GitHub/paper search to stay current |
|
|
64
|
-
| **Date Awareness** | Agents know when to verify potentially outdated info |
|
|
65
|
-
| **Focus Mode** | Talk directly to any specialist agent |
|
|
66
|
-
| **File-Based IPC** | Agents coordinate through structured JSON messages |
|
|
67
|
-
|
|
68
|
-
## Agent Teams
|
|
69
|
-
|
|
70
|
-
### Development Mode (Default)
|
|
71
|
-
|
|
72
|
-
| Agent | Specialty |
|
|
73
|
-
|-------|-----------|
|
|
74
|
-
| **Orchestrator** | Task decomposition, coordination, result aggregation |
|
|
75
|
-
| **Engineer** | Code implementation, debugging, refactoring |
|
|
76
|
-
| **Tester** | Unit/integration tests, coverage analysis |
|
|
77
|
-
| **Security** | OWASP vulnerability review, secrets detection |
|
|
78
|
-
| **Scout** | Real-time search for current best practices |
|
|
79
|
-
|
|
80
|
-
### ML Mode (`--mode ml`)
|
|
81
|
-
|
|
82
|
-
| Agent | Specialty |
|
|
83
|
-
|-------|-----------|
|
|
84
|
-
| **Orchestrator** | ML project lifecycle management |
|
|
85
|
-
| **Researcher** | Literature review, SOTA analysis, paper summaries |
|
|
86
|
-
| **ML Engineer** | Model implementation, training loops, optimization |
|
|
87
|
-
| **Data Engineer** | Data pipelines, preprocessing, augmentation |
|
|
88
|
-
| **Evaluator** | Metrics, benchmarking, experiment tracking |
|
|
89
|
-
| **Scout** | arXiv, HuggingFace, Papers With Code search |
|
|
15
|
+
- **Sophisticated UI** - Dark teal/purple theme inspired by modern terminal aesthetics
|
|
16
|
+
- **Intelligent Orchestrator** - Analyzes task complexity and coordinates specialist agents
|
|
17
|
+
- **Command History** - Use ↑/↓ arrows to browse past messages
|
|
18
|
+
- **Live Token Tracking** - Real-time token usage display
|
|
19
|
+
- **Animated Thinking Indicator** - Beautiful spinner with elapsed time
|
|
20
|
+
- **Two Modes** - Development and ML Research
|
|
90
21
|
|
|
91
22
|
## Installation
|
|
92
23
|
|
|
93
|
-
###
|
|
94
|
-
```bash
|
|
95
|
-
brew tap de5truct0/agentk
|
|
96
|
-
brew install agentk8
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
### npm
|
|
24
|
+
### npm (Recommended)
|
|
100
25
|
```bash
|
|
101
26
|
npm install -g agentk8
|
|
102
27
|
```
|
|
103
28
|
|
|
104
|
-
###
|
|
105
|
-
```bash
|
|
106
|
-
pip install agentk8
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
### Quick Install Script
|
|
29
|
+
### Homebrew (macOS/Linux)
|
|
110
30
|
```bash
|
|
111
|
-
|
|
31
|
+
brew tap de5truct0/agentk
|
|
32
|
+
brew install agentk8
|
|
112
33
|
```
|
|
113
34
|
|
|
114
35
|
### From Source
|
|
115
36
|
```bash
|
|
116
37
|
git clone https://github.com/de5truct0/agentk.git
|
|
117
38
|
cd agentk
|
|
118
|
-
|
|
39
|
+
npm install
|
|
40
|
+
npm run build
|
|
41
|
+
npm link
|
|
119
42
|
```
|
|
120
43
|
|
|
121
|
-
> **Note**: Package name is `agentk8` on all registries. The installed command is `agentk`.
|
|
122
|
-
|
|
123
44
|
## Requirements
|
|
124
45
|
|
|
125
|
-
- **
|
|
126
|
-
- **
|
|
127
|
-
- **tmux** - Optional, for visual mode (`brew install tmux`)
|
|
46
|
+
- **Node.js** 18+
|
|
47
|
+
- **Claude Code CLI** - [Install from claude.ai/code](https://claude.ai/code)
|
|
128
48
|
|
|
129
49
|
## Quick Start
|
|
130
50
|
|
|
131
51
|
```bash
|
|
132
|
-
# Start interactive session
|
|
52
|
+
# Start interactive session (Development mode)
|
|
133
53
|
agentk
|
|
134
54
|
|
|
135
|
-
# Start ML
|
|
55
|
+
# Start ML Research mode
|
|
136
56
|
agentk --mode ml
|
|
137
57
|
|
|
138
|
-
#
|
|
139
|
-
agentk --
|
|
140
|
-
|
|
141
|
-
# One-shot task
|
|
142
|
-
agentk -c "Refactor the user service to use async/await"
|
|
58
|
+
# Show help
|
|
59
|
+
agentk --help
|
|
143
60
|
```
|
|
144
61
|
|
|
145
62
|
## Usage
|
|
146
63
|
|
|
147
|
-
###
|
|
64
|
+
### Chat Interface
|
|
148
65
|
|
|
149
|
-
```
|
|
150
|
-
|
|
66
|
+
```
|
|
67
|
+
◆ You
|
|
68
|
+
Build a REST API with authentication
|
|
151
69
|
|
|
152
|
-
|
|
153
|
-
│ AGENT-K v1.0 │
|
|
154
|
-
╰─────────────────────────────────────────────────╯
|
|
155
|
-
Mode: Software Development Mode
|
|
70
|
+
⣾ Synthesizing… (ctrl+c to interrupt · 12s · thinking)
|
|
156
71
|
|
|
157
|
-
|
|
72
|
+
◆ Orchestrator
|
|
73
|
+
<task_analysis>
|
|
74
|
+
┌─────────────────────────────────────────────────────────
|
|
75
|
+
│ COMPLEXITY: Moderate
|
|
76
|
+
│ AGENTS: Engineer, Security, Tester
|
|
77
|
+
│ SUBTASKS: API endpoints, JWT auth, tests, security review
|
|
78
|
+
└─────────────────────────────────────────────────────────
|
|
79
|
+
</task_analysis>
|
|
158
80
|
|
|
159
|
-
|
|
160
|
-
|
|
81
|
+
[Detailed response...]
|
|
82
|
+
→ 1,247 tokens
|
|
161
83
|
```
|
|
162
84
|
|
|
163
|
-
###
|
|
164
|
-
|
|
165
|
-
| Command | Description |
|
|
166
|
-
|---------|-------------|
|
|
167
|
-
| `/status` | Show all agent states and current tasks |
|
|
168
|
-
| `/logs <agent>` | View agent output |
|
|
169
|
-
| `/kill <agent\|all>` | Stop agent(s) |
|
|
170
|
-
| `/focus <agent>` | Talk directly to one agent |
|
|
171
|
-
| `/unfocus` | Return to orchestrator |
|
|
172
|
-
| `/visual` | Toggle tmux panel view |
|
|
173
|
-
| `/clear` | Clear screen |
|
|
174
|
-
| `/help` | Show all commands |
|
|
175
|
-
| `/exit` | End session |
|
|
176
|
-
|
|
177
|
-
### Scout Commands (Both Modes)
|
|
85
|
+
### Commands
|
|
178
86
|
|
|
179
87
|
| Command | Description |
|
|
180
88
|
|---------|-------------|
|
|
181
|
-
| `/
|
|
182
|
-
| `/
|
|
183
|
-
| `/
|
|
184
|
-
| `/
|
|
185
|
-
| `/sota <topic>` | Get state-of-the-art approaches |
|
|
89
|
+
| `/help` | Show available commands |
|
|
90
|
+
| `/clear` | Clear chat history |
|
|
91
|
+
| `/status` | Show session status |
|
|
92
|
+
| `/exit` | Exit AGENT-K |
|
|
186
93
|
|
|
187
|
-
###
|
|
188
|
-
|
|
189
|
-
| Command | Description |
|
|
190
|
-
|---------|-------------|
|
|
191
|
-
| `/experiment <name>` | Start a new experiment |
|
|
192
|
-
| `/metrics` | Show current training metrics |
|
|
193
|
-
| `/tensorboard` | Open TensorBoard |
|
|
194
|
-
| `/checkpoint` | Save model state |
|
|
195
|
-
| `/compare <e1> <e2>` | Compare experiments |
|
|
196
|
-
| `/huggingface <query>` | Search HuggingFace Hub |
|
|
94
|
+
### Keyboard Shortcuts
|
|
197
95
|
|
|
198
|
-
|
|
96
|
+
| Key | Action |
|
|
97
|
+
|-----|--------|
|
|
98
|
+
| `↑` / `↓` | Browse command history |
|
|
99
|
+
| `Ctrl+C` | Exit |
|
|
100
|
+
| `Ctrl+U` | Clear input line |
|
|
101
|
+
| `Ctrl+A` | Jump to start of line |
|
|
102
|
+
| `Ctrl+E` | Jump to end of line |
|
|
199
103
|
|
|
200
|
-
|
|
104
|
+
## Agent Teams
|
|
201
105
|
|
|
202
|
-
|
|
203
|
-
┌───────────────────┬───────────────────┬───────────────────┐
|
|
204
|
-
│ ORCHESTRATOR │ ENGINEER │ TESTER │
|
|
205
|
-
│ │ │ │
|
|
206
|
-
│ Breaking down │ Implementing │ Waiting for │
|
|
207
|
-
│ task into │ auth module... │ implementation... │
|
|
208
|
-
│ subtasks... │ │ │
|
|
209
|
-
├───────────────────┼───────────────────┼───────────────────┤
|
|
210
|
-
│ SECURITY │ SCOUT │ [MAIN] │
|
|
211
|
-
│ │ │ │
|
|
212
|
-
│ Queued for │ Searching JWT │ You: _ │
|
|
213
|
-
│ review │ best practices... │ │
|
|
214
|
-
│ │ │ │
|
|
215
|
-
└───────────────────┴───────────────────┴───────────────────┘
|
|
216
|
-
```
|
|
106
|
+
### Development Mode (Default)
|
|
217
107
|
|
|
218
|
-
|
|
108
|
+
| Agent | Role |
|
|
109
|
+
|-------|------|
|
|
110
|
+
| **Orchestrator** | Task decomposition, coordination |
|
|
111
|
+
| **Engineer** | Code implementation, debugging |
|
|
112
|
+
| **Tester** | Unit/integration tests, coverage |
|
|
113
|
+
| **Security** | OWASP review, vulnerability detection |
|
|
114
|
+
| **Scout** | Real-time research, best practices |
|
|
219
115
|
|
|
220
|
-
|
|
221
|
-
┌─────────────┐
|
|
222
|
-
│ User │
|
|
223
|
-
└──────┬──────┘
|
|
224
|
-
│
|
|
225
|
-
▼
|
|
226
|
-
┌────────────────────────┐
|
|
227
|
-
│ Orchestrator │
|
|
228
|
-
│ (task decomposition) │
|
|
229
|
-
└───────────┬────────────┘
|
|
230
|
-
│
|
|
231
|
-
┌────────────────────┼────────────────────┐
|
|
232
|
-
│ │ │
|
|
233
|
-
▼ ▼ ▼
|
|
234
|
-
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
|
|
235
|
-
│ Engineer │ │ Tester │ │ Security │
|
|
236
|
-
│ (implements) │ │ (validates) │ │ (reviews) │
|
|
237
|
-
└───────┬───────┘ └───────┬───────┘ └───────┬───────┘
|
|
238
|
-
│ │ │
|
|
239
|
-
└────────────────────┴────────────────────┘
|
|
240
|
-
│
|
|
241
|
-
▼
|
|
242
|
-
┌────────────────────────┐
|
|
243
|
-
│ File-Based IPC │
|
|
244
|
-
│ workspace/tasks/*.json │
|
|
245
|
-
└────────────────────────┘
|
|
246
|
-
```
|
|
116
|
+
### ML Mode (`--mode ml`)
|
|
247
117
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
118
|
+
| Agent | Role |
|
|
119
|
+
|-------|------|
|
|
120
|
+
| **Orchestrator** | ML project lifecycle coordination |
|
|
121
|
+
| **Researcher** | Literature review, SOTA analysis |
|
|
122
|
+
| **ML Engineer** | Model implementation, training |
|
|
123
|
+
| **Data Engineer** | Data pipelines, preprocessing |
|
|
124
|
+
| **Evaluator** | Metrics, benchmarking, experiments |
|
|
125
|
+
| **Scout** | arXiv, HuggingFace, Papers With Code |
|
|
254
126
|
|
|
255
|
-
##
|
|
127
|
+
## Orchestrator Intelligence
|
|
256
128
|
|
|
257
|
-
|
|
129
|
+
The Orchestrator uses a sophisticated prompt based on:
|
|
258
130
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
131
|
+
- [Anthropic's Multi-Agent Research System](https://www.anthropic.com/engineering/multi-agent-research-system) - Orchestrator-worker pattern
|
|
132
|
+
- [CrewAI Framework](https://github.com/crewAIInc/crewAI) - Role-Goal-Backstory agents
|
|
133
|
+
- [Claude 2026 Best Practices](https://promptbuilder.cc/blog/claude-prompt-engineering-best-practices-2026) - Contract-style prompts
|
|
134
|
+
- [Microsoft Azure AI Patterns](https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/ai-agent-design-patterns) - Task decomposition
|
|
262
135
|
|
|
263
|
-
|
|
264
|
-
|
|
136
|
+
Every response includes:
|
|
137
|
+
1. **Task Analysis** - Complexity assessment and agent identification
|
|
138
|
+
2. **Structured Thinking** - Transparent reasoning process
|
|
139
|
+
3. **Coordinated Response** - Synthesized output from relevant agents
|
|
265
140
|
|
|
266
|
-
|
|
267
|
-
export AGENTK_WORKSPACE="/custom/path/workspace"
|
|
141
|
+
## Tech Stack
|
|
268
142
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
143
|
+
- **React** + **Ink** - Terminal UI framework (same as Claude Code)
|
|
144
|
+
- **TypeScript** - Type-safe codebase
|
|
145
|
+
- **Meow** - CLI argument parsing
|
|
146
|
+
- **Claude Code CLI** - AI backend
|
|
272
147
|
|
|
273
148
|
## Project Structure
|
|
274
149
|
|
|
275
150
|
```
|
|
276
151
|
agentk/
|
|
277
|
-
├──
|
|
278
|
-
├──
|
|
279
|
-
│ ├──
|
|
280
|
-
│ ├──
|
|
281
|
-
│ ├──
|
|
282
|
-
│ ├──
|
|
283
|
-
│
|
|
284
|
-
├──
|
|
285
|
-
│
|
|
286
|
-
│
|
|
287
|
-
│
|
|
288
|
-
│
|
|
289
|
-
│
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
│ └── ml/ # ML mode prompts
|
|
293
|
-
│ ├── orchestrator.md
|
|
294
|
-
│ ├── researcher.md
|
|
295
|
-
│ ├── ml-engineer.md
|
|
296
|
-
│ ├── data-engineer.md
|
|
297
|
-
│ └── evaluator.md
|
|
298
|
-
└── workspace/ # Runtime data (gitignored)
|
|
299
|
-
├── tasks/ # Task queue (JSON)
|
|
300
|
-
├── results/ # Agent outputs
|
|
301
|
-
├── logs/ # Agent logs
|
|
302
|
-
└── experiments/ # ML experiment tracking
|
|
152
|
+
├── src/
|
|
153
|
+
│ ├── cli.tsx # CLI entry point
|
|
154
|
+
│ ├── components/
|
|
155
|
+
│ │ ├── App.tsx # Main application
|
|
156
|
+
│ │ ├── Banner.tsx # Header banner
|
|
157
|
+
│ │ ├── ChatMessage.tsx # Message display
|
|
158
|
+
│ │ ├── Input.tsx # Input with history
|
|
159
|
+
│ │ ├── StatusBar.tsx # Footer status
|
|
160
|
+
│ │ └── ThinkingIndicator.tsx
|
|
161
|
+
│ ├── lib/
|
|
162
|
+
│ │ └── claude.ts # Claude CLI integration
|
|
163
|
+
│ └── themes/
|
|
164
|
+
│ └── retro.ts # Color theme
|
|
165
|
+
├── dist/ # Compiled output
|
|
166
|
+
└── package.json
|
|
303
167
|
```
|
|
304
168
|
|
|
305
|
-
##
|
|
306
|
-
|
|
307
|
-
| Limitation | Workaround |
|
|
308
|
-
|------------|------------|
|
|
309
|
-
| File conflicts when agents edit same file | Use `/focus` to serialize work on critical files |
|
|
310
|
-
| Each agent = separate API call (cost) | Use orchestrator's judgment on when to parallelize |
|
|
311
|
-
| Agents don't share real-time context | Orchestrator maintains shared state in workspace |
|
|
312
|
-
| Rate limiting with many parallel agents | `AGENTK_MAX_PARALLEL` limits concurrent spawns |
|
|
169
|
+
## Configuration
|
|
313
170
|
|
|
314
|
-
|
|
171
|
+
Environment variables:
|
|
315
172
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- [ ] Cost tracking per agent
|
|
320
|
-
- [ ] Team collaboration mode
|
|
321
|
-
- [ ] Plugin system for custom tools
|
|
173
|
+
| Variable | Description | Default |
|
|
174
|
+
|----------|-------------|---------|
|
|
175
|
+
| `AGENTK_MODE` | Default mode (`dev` or `ml`) | `dev` |
|
|
322
176
|
|
|
323
177
|
## Contributing
|
|
324
178
|
|
|
325
|
-
Contributions welcome!
|
|
326
|
-
|
|
327
179
|
1. Fork the repository
|
|
328
|
-
2. Create a feature branch
|
|
180
|
+
2. Create a feature branch
|
|
329
181
|
3. Make your changes
|
|
330
|
-
4. Run
|
|
182
|
+
4. Run `npm run build` to compile
|
|
331
183
|
5. Submit a pull request
|
|
332
184
|
|
|
333
185
|
## License
|
|
@@ -336,18 +188,18 @@ MIT License - see [LICENSE](LICENSE) for details.
|
|
|
336
188
|
|
|
337
189
|
## Acknowledgments
|
|
338
190
|
|
|
339
|
-
-
|
|
340
|
-
- Built for the Claude Code community
|
|
191
|
+
- Built with [Ink](https://github.com/vadimdemedes/ink) by Vadim Demedes
|
|
341
192
|
- Powered by [Anthropic's Claude](https://anthropic.com)
|
|
193
|
+
- Inspired by Claude Code's beautiful terminal UI
|
|
342
194
|
|
|
343
195
|
---
|
|
344
196
|
|
|
345
197
|
<p align="center">
|
|
346
|
-
<strong>AGENT-K</strong> -
|
|
198
|
+
<strong>AGENT-K</strong> - Multi-Agent Intelligence for Your Terminal
|
|
347
199
|
</p>
|
|
348
200
|
|
|
349
201
|
<p align="center">
|
|
350
|
-
<a href="https://github.com/de5truct0/agentk">GitHub</a>
|
|
351
|
-
<a href="https://www.npmjs.com/package/agentk8">npm</a>
|
|
202
|
+
<a href="https://github.com/de5truct0/agentk">GitHub</a> •
|
|
203
|
+
<a href="https://www.npmjs.com/package/agentk8">npm</a> •
|
|
352
204
|
<a href="https://pypi.org/project/agentk8/">PyPI</a>
|
|
353
205
|
</p>
|
package/dist/components/App.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import { Box, Text, useApp, useInput } from 'ink';
|
|
3
|
+
import { Box, Text, useApp, useInput, Static } from 'ink';
|
|
4
4
|
import { Banner } from './Banner.js';
|
|
5
5
|
import { ChatMessage } from './ChatMessage.js';
|
|
6
6
|
import { Input } from './Input.js';
|
|
7
7
|
import { StatusBar } from './StatusBar.js';
|
|
8
|
+
import { ThinkingIndicator } from './ThinkingIndicator.js';
|
|
8
9
|
import { runClaude } from '../lib/claude.js';
|
|
9
|
-
import { colors, icons } from '../themes/retro.js';
|
|
10
10
|
export const App = ({ mode, version }) => {
|
|
11
11
|
const { exit } = useApp();
|
|
12
12
|
const [messages, setMessages] = useState([]);
|
|
13
13
|
const [isProcessing, setIsProcessing] = useState(false);
|
|
14
|
+
const [processingStartTime, setProcessingStartTime] = useState(null);
|
|
14
15
|
const [totalTokens, setTotalTokens] = useState(0);
|
|
15
16
|
const [startTime] = useState(new Date());
|
|
16
17
|
const [error, setError] = useState(null);
|
|
@@ -30,6 +31,7 @@ export const App = ({ mode, version }) => {
|
|
|
30
31
|
};
|
|
31
32
|
setMessages(prev => [...prev, userMessage]);
|
|
32
33
|
setIsProcessing(true);
|
|
34
|
+
setProcessingStartTime(new Date());
|
|
33
35
|
setError(null);
|
|
34
36
|
try {
|
|
35
37
|
// Call Claude
|
|
@@ -54,11 +56,12 @@ export const App = ({ mode, version }) => {
|
|
|
54
56
|
}
|
|
55
57
|
finally {
|
|
56
58
|
setIsProcessing(false);
|
|
59
|
+
setProcessingStartTime(null);
|
|
57
60
|
}
|
|
58
61
|
};
|
|
59
62
|
// Handle slash commands
|
|
60
63
|
const handleCommand = (cmd) => {
|
|
61
|
-
const [command
|
|
64
|
+
const [command] = cmd.slice(1).split(' ');
|
|
62
65
|
switch (command) {
|
|
63
66
|
case 'exit':
|
|
64
67
|
case 'quit':
|
|
@@ -75,12 +78,14 @@ export const App = ({ mode, version }) => {
|
|
|
75
78
|
content: `Available commands:
|
|
76
79
|
/help - Show this help
|
|
77
80
|
/clear - Clear chat history
|
|
78
|
-
/status - Show
|
|
81
|
+
/status - Show session status
|
|
79
82
|
/exit - Exit AGENT-K
|
|
80
83
|
|
|
81
84
|
Keyboard shortcuts:
|
|
85
|
+
↑/↓ - Browse command history
|
|
82
86
|
Ctrl+C - Exit
|
|
83
|
-
Ctrl+U - Clear input line
|
|
87
|
+
Ctrl+U - Clear input line
|
|
88
|
+
Ctrl+A/E - Jump to start/end`,
|
|
84
89
|
timestamp: new Date(),
|
|
85
90
|
};
|
|
86
91
|
setMessages(prev => [...prev, helpMessage]);
|
|
@@ -91,10 +96,10 @@ Ctrl+U - Clear input line`,
|
|
|
91
96
|
role: 'agent',
|
|
92
97
|
agentName: 'System',
|
|
93
98
|
content: `Session Status:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
99
|
+
◇ Mode: ${mode === 'dev' ? 'Development' : 'ML Research'}
|
|
100
|
+
◇ Messages: ${messages.length}
|
|
101
|
+
◇ Total Tokens: ${totalTokens}
|
|
102
|
+
◇ Session Time: ${formatElapsed(startTime)}`,
|
|
98
103
|
timestamp: new Date(),
|
|
99
104
|
};
|
|
100
105
|
setMessages(prev => [...prev, statusMessage]);
|
|
@@ -109,7 +114,7 @@ ${icons.bullet} Session Time: ${formatElapsed(startTime)}`,
|
|
|
109
114
|
exit();
|
|
110
115
|
}
|
|
111
116
|
});
|
|
112
|
-
return (_jsxs(Box, { flexDirection: "column",
|
|
117
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Banner, { version: version }), _jsx(Static, { items: messages, children: (msg) => (_jsx(ChatMessage, { role: msg.role, agentName: msg.agentName, content: msg.content, tokens: msg.tokens }, msg.id)) }), isProcessing && processingStartTime && (_jsx(ThinkingIndicator, { startTime: processingStartTime })), error && (_jsx(Box, { marginY: 1, marginLeft: 1, children: _jsxs(Text, { color: "#e53e3e", children: ["\u2717 Error: ", error] }) })), _jsx(Input, { onSubmit: handleSubmit, disabled: isProcessing, placeholder: "Type a message or /help for commands..." }), _jsx(StatusBar, { mode: mode, tokens: totalTokens, startTime: startTime, isProcessing: isProcessing })] }));
|
|
113
118
|
};
|
|
114
119
|
function formatElapsed(start) {
|
|
115
120
|
const secs = Math.floor((Date.now() - start.getTime()) / 1000);
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
-
|
|
3
|
+
// Sophisticated dark palette
|
|
4
|
+
const theme = {
|
|
5
|
+
border: '#2d3748', // Slate gray
|
|
6
|
+
accent: '#4fd1c5', // Teal
|
|
7
|
+
highlight: '#81e6d9', // Light teal
|
|
8
|
+
text: '#e2e8f0', // Light gray
|
|
9
|
+
dim: '#4a5568', // Medium gray
|
|
10
|
+
glow: '#319795', // Deep teal
|
|
11
|
+
};
|
|
4
12
|
export const Banner = ({ version }) => {
|
|
5
13
|
const termWidth = process.stdout.columns || 80;
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
const title = `${icons.star} A G E N T - K ${icons.star}`;
|
|
9
|
-
const subtitle = 'Multi-Agent Claude Code Suite';
|
|
10
|
-
const versionText = `v${version}`;
|
|
11
|
-
const centerPad = (text, width) => {
|
|
12
|
-
const pad = Math.max(0, Math.floor((width - text.length) / 2));
|
|
13
|
-
return ' '.repeat(pad) + text + ' '.repeat(width - pad - text.length);
|
|
14
|
-
};
|
|
15
|
-
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { color: colors.secondary, children: [boxDouble.topLeft, boxDouble.horizontal.repeat(innerWidth), boxDouble.topRight] }), _jsxs(Text, { color: colors.secondary, children: [boxDouble.vertical, _jsx(Text, { bold: true, color: colors.primary, children: centerPad(title, innerWidth) }), boxDouble.vertical] }), _jsxs(Text, { color: colors.secondary, children: [boxDouble.vertical, _jsx(Text, { dimColor: true, children: centerPad(subtitle, innerWidth) }), boxDouble.vertical] }), _jsxs(Text, { color: colors.secondary, children: [boxDouble.vertical, _jsx(Text, { dimColor: true, children: centerPad(versionText, innerWidth) }), boxDouble.vertical] }), _jsxs(Text, { color: colors.secondary, children: [boxDouble.bottomLeft, boxDouble.horizontal.repeat(innerWidth), boxDouble.bottomRight] })] }));
|
|
14
|
+
const w = termWidth;
|
|
15
|
+
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Box, { children: _jsx(Text, { color: theme.glow, children: '▁'.repeat(w) }) }), _jsxs(Box, { children: [_jsx(Text, { color: theme.border, children: ' ' }), _jsx(Text, { color: theme.dim, children: '◇' }), _jsx(Text, { color: theme.border, children: ' ─── ' }), _jsx(Text, { color: theme.highlight, bold: true, children: "AGENT" }), _jsx(Text, { color: theme.accent, bold: true, children: "-" }), _jsx(Text, { color: theme.highlight, bold: true, children: "K" }), _jsx(Text, { color: theme.border, children: ' ─── ' }), _jsx(Text, { color: theme.dim, children: '◇' }), _jsx(Text, { color: theme.border, children: ' ─ ' }), _jsx(Text, { color: theme.dim, italic: true, children: "Multi-Agent Intelligence System" }), _jsx(Text, { color: theme.border, children: ' ─'.repeat(Math.max(1, Math.floor((w - 58) / 2))) }), _jsxs(Text, { color: theme.dim, children: [" v", version] })] }), _jsx(Box, { children: _jsx(Text, { color: theme.border, children: '─'.repeat(w) }) })] }));
|
|
16
16
|
};
|
|
17
17
|
export default Banner;
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Box, Text } from 'ink';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
// Sophisticated theme
|
|
4
|
+
const theme = {
|
|
5
|
+
border: '#2d3748',
|
|
6
|
+
accent: '#4fd1c5',
|
|
7
|
+
highlight: '#81e6d9',
|
|
8
|
+
text: '#e2e8f0',
|
|
9
|
+
dim: '#4a5568',
|
|
10
|
+
user: '#9f7aea', // Purple for user
|
|
11
|
+
agent: '#4fd1c5', // Teal for agent
|
|
12
|
+
};
|
|
13
|
+
export const ChatMessage = ({ role, agentName = 'Agent', content, tokens, }) => {
|
|
5
14
|
const isUser = role === 'user';
|
|
6
|
-
const
|
|
15
|
+
const symbolColor = isUser ? theme.user : theme.agent;
|
|
7
16
|
const title = isUser ? 'You' : agentName;
|
|
8
17
|
const termWidth = process.stdout.columns || 80;
|
|
9
|
-
const
|
|
10
|
-
const contentWidth = boxWidth - 4;
|
|
11
|
-
// Word wrap content
|
|
18
|
+
const contentWidth = termWidth - 6;
|
|
12
19
|
const lines = wrapText(content, contentWidth);
|
|
13
|
-
|
|
14
|
-
const topLineWidth = boxWidth - 2 - titleText.length;
|
|
15
|
-
return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsxs(Text, { color: color, children: [box.topLeft, box.horizontal, _jsx(Text, { bold: true, children: titleText }), box.horizontal.repeat(Math.max(0, topLineWidth)), box.topRight] }), lines.map((line, i) => (_jsxs(Text, { color: color, children: [box.vertical, " ", _jsx(Text, { color: "white", children: line.padEnd(contentWidth) }), " ", box.vertical] }, i))), tokens && tokens.input + tokens.output > 0 && (_jsxs(Text, { color: color, children: [box.vertical, " ", _jsxs(Text, { dimColor: true, children: [icons.arrow, " ", tokens.input + tokens.output, " tokens (in: ", tokens.input, ", out: ", tokens.output, ")"] }), ' '.repeat(Math.max(0, contentWidth - 40)), " ", box.vertical] })), _jsxs(Text, { color: color, children: [box.bottomLeft, box.horizontal.repeat(boxWidth - 2), box.bottomRight] })] }));
|
|
20
|
+
return (_jsxs(Box, { flexDirection: "column", marginY: 1, marginLeft: 1, children: [_jsxs(Box, { children: [_jsx(Text, { color: symbolColor, children: '◆ ' }), _jsx(Text, { color: symbolColor, bold: true, children: title })] }), _jsx(Box, { flexDirection: "column", marginLeft: 2, children: lines.map((line, i) => (_jsx(Text, { color: theme.text, children: line }, i))) }), tokens && tokens.input + tokens.output > 0 && (_jsx(Box, { marginLeft: 2, children: _jsxs(Text, { color: theme.dim, children: ["\u2192 ", tokens.input + tokens.output, " tokens"] }) }))] }));
|
|
16
21
|
};
|
|
17
|
-
// Simple word wrap function
|
|
18
22
|
function wrapText(text, width) {
|
|
19
23
|
const lines = [];
|
|
20
24
|
const paragraphs = text.split('\n');
|
package/dist/components/Input.js
CHANGED
|
@@ -1,24 +1,79 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { Box, Text, useInput } from 'ink';
|
|
4
|
-
|
|
4
|
+
// Sophisticated theme
|
|
5
|
+
const theme = {
|
|
6
|
+
accent: '#4fd1c5',
|
|
7
|
+
dim: '#4a5568',
|
|
8
|
+
};
|
|
9
|
+
// Store history globally so it persists across re-renders
|
|
10
|
+
const commandHistory = [];
|
|
11
|
+
const MAX_HISTORY = 100;
|
|
5
12
|
export const Input = ({ onSubmit, placeholder = 'Type a message...', prefix = '>', disabled = false, }) => {
|
|
6
13
|
const [value, setValue] = useState('');
|
|
7
14
|
const [cursorPosition, setCursorPosition] = useState(0);
|
|
15
|
+
const [historyIndex, setHistoryIndex] = useState(-1);
|
|
16
|
+
const [tempValue, setTempValue] = useState(''); // Store current input when browsing history
|
|
8
17
|
useInput((input, key) => {
|
|
9
18
|
if (disabled)
|
|
10
19
|
return;
|
|
11
20
|
if (key.return) {
|
|
12
21
|
if (value.trim()) {
|
|
22
|
+
// Add to history (avoid duplicates at the end)
|
|
23
|
+
if (commandHistory.length === 0 || commandHistory[commandHistory.length - 1] !== value) {
|
|
24
|
+
commandHistory.push(value);
|
|
25
|
+
if (commandHistory.length > MAX_HISTORY) {
|
|
26
|
+
commandHistory.shift();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
13
29
|
onSubmit(value);
|
|
14
30
|
setValue('');
|
|
15
31
|
setCursorPosition(0);
|
|
32
|
+
setHistoryIndex(-1);
|
|
33
|
+
setTempValue('');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
else if (key.upArrow) {
|
|
37
|
+
// Navigate history backwards
|
|
38
|
+
if (commandHistory.length > 0) {
|
|
39
|
+
if (historyIndex === -1) {
|
|
40
|
+
// Save current input before browsing history
|
|
41
|
+
setTempValue(value);
|
|
42
|
+
const newIndex = commandHistory.length - 1;
|
|
43
|
+
setHistoryIndex(newIndex);
|
|
44
|
+
setValue(commandHistory[newIndex]);
|
|
45
|
+
setCursorPosition(commandHistory[newIndex].length);
|
|
46
|
+
}
|
|
47
|
+
else if (historyIndex > 0) {
|
|
48
|
+
const newIndex = historyIndex - 1;
|
|
49
|
+
setHistoryIndex(newIndex);
|
|
50
|
+
setValue(commandHistory[newIndex]);
|
|
51
|
+
setCursorPosition(commandHistory[newIndex].length);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
else if (key.downArrow) {
|
|
56
|
+
// Navigate history forwards
|
|
57
|
+
if (historyIndex !== -1) {
|
|
58
|
+
if (historyIndex < commandHistory.length - 1) {
|
|
59
|
+
const newIndex = historyIndex + 1;
|
|
60
|
+
setHistoryIndex(newIndex);
|
|
61
|
+
setValue(commandHistory[newIndex]);
|
|
62
|
+
setCursorPosition(commandHistory[newIndex].length);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// Return to the original input
|
|
66
|
+
setHistoryIndex(-1);
|
|
67
|
+
setValue(tempValue);
|
|
68
|
+
setCursorPosition(tempValue.length);
|
|
69
|
+
}
|
|
16
70
|
}
|
|
17
71
|
}
|
|
18
72
|
else if (key.backspace || key.delete) {
|
|
19
73
|
if (cursorPosition > 0) {
|
|
20
74
|
setValue(prev => prev.slice(0, cursorPosition - 1) + prev.slice(cursorPosition));
|
|
21
75
|
setCursorPosition(pos => pos - 1);
|
|
76
|
+
setHistoryIndex(-1); // Reset history navigation on edit
|
|
22
77
|
}
|
|
23
78
|
}
|
|
24
79
|
else if (key.leftArrow) {
|
|
@@ -34,16 +89,26 @@ export const Input = ({ onSubmit, placeholder = 'Type a message...', prefix = '>
|
|
|
34
89
|
// Clear line
|
|
35
90
|
setValue('');
|
|
36
91
|
setCursorPosition(0);
|
|
92
|
+
setHistoryIndex(-1);
|
|
93
|
+
}
|
|
94
|
+
else if (key.ctrl && input === 'a') {
|
|
95
|
+
// Go to beginning
|
|
96
|
+
setCursorPosition(0);
|
|
97
|
+
}
|
|
98
|
+
else if (key.ctrl && input === 'e') {
|
|
99
|
+
// Go to end
|
|
100
|
+
setCursorPosition(value.length);
|
|
37
101
|
}
|
|
38
102
|
else if (!key.ctrl && !key.meta && input) {
|
|
39
103
|
setValue(prev => prev.slice(0, cursorPosition) + input + prev.slice(cursorPosition));
|
|
40
104
|
setCursorPosition(pos => pos + input.length);
|
|
105
|
+
setHistoryIndex(-1); // Reset history navigation on edit
|
|
41
106
|
}
|
|
42
107
|
});
|
|
43
108
|
// Render input with cursor
|
|
44
109
|
const beforeCursor = value.slice(0, cursorPosition);
|
|
45
110
|
const atCursor = value[cursorPosition] || ' ';
|
|
46
111
|
const afterCursor = value.slice(cursorPosition + 1);
|
|
47
|
-
return (_jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color:
|
|
112
|
+
return (_jsxs(Box, { marginTop: 1, children: [_jsxs(Text, { color: theme.accent, bold: true, children: [prefix, " "] }), value.length === 0 && !disabled ? (_jsx(Text, { color: theme.dim, children: placeholder })) : (_jsxs(_Fragment, { children: [_jsx(Text, { children: beforeCursor }), _jsx(Text, { inverse: true, children: atCursor }), _jsx(Text, { children: afterCursor })] })), disabled && _jsx(Text, { color: theme.dim, children: " processing..." })] }));
|
|
48
113
|
};
|
|
49
114
|
export default Input;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { Box, Text } from 'ink';
|
|
4
|
-
import {
|
|
4
|
+
import { icons } from '../themes/retro.js';
|
|
5
|
+
// Matching sophisticated theme
|
|
6
|
+
const theme = {
|
|
7
|
+
border: '#2d3748',
|
|
8
|
+
accent: '#4fd1c5',
|
|
9
|
+
highlight: '#81e6d9',
|
|
10
|
+
dim: '#4a5568',
|
|
11
|
+
glow: '#319795',
|
|
12
|
+
};
|
|
5
13
|
export const StatusBar = ({ mode, tokens, startTime, isProcessing = false, }) => {
|
|
6
14
|
const [elapsed, setElapsed] = useState('0s');
|
|
7
15
|
const [spinnerFrame, setSpinnerFrame] = useState(0);
|
|
8
|
-
// Update elapsed time every second
|
|
9
16
|
useEffect(() => {
|
|
10
17
|
const interval = setInterval(() => {
|
|
11
18
|
const secs = Math.floor((Date.now() - startTime.getTime()) / 1000);
|
|
@@ -15,7 +22,6 @@ export const StatusBar = ({ mode, tokens, startTime, isProcessing = false, }) =>
|
|
|
15
22
|
}, 1000);
|
|
16
23
|
return () => clearInterval(interval);
|
|
17
24
|
}, [startTime]);
|
|
18
|
-
// Spinner animation
|
|
19
25
|
useEffect(() => {
|
|
20
26
|
if (!isProcessing)
|
|
21
27
|
return;
|
|
@@ -31,10 +37,8 @@ export const StatusBar = ({ mode, tokens, startTime, isProcessing = false, }) =>
|
|
|
31
37
|
return `${(t / 1000).toFixed(1)}k`;
|
|
32
38
|
return t.toString();
|
|
33
39
|
};
|
|
34
|
-
const
|
|
35
|
-
const modeLabel = mode === 'dev' ? 'Development' : 'ML Research';
|
|
40
|
+
const modeLabel = mode === 'dev' ? 'DEV' : 'ML';
|
|
36
41
|
const termWidth = process.stdout.columns || 80;
|
|
37
|
-
|
|
38
|
-
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.dim, children: box.horizontal.repeat(barWidth) }), _jsxs(Box, { justifyContent: "space-between", width: barWidth, children: [_jsxs(Text, { children: [_jsxs(Text, { color: colors.secondary, children: [modeIcon, " ", modeLabel] }), _jsx(Text, { dimColor: true, children: " \u2502 " }), _jsx(Text, { dimColor: true, children: "/help for commands" })] }), _jsxs(Text, { children: [isProcessing && (_jsxs(Text, { color: colors.warning, children: [icons.spinner[spinnerFrame], " "] })), _jsxs(Text, { dimColor: true, children: [elapsed, " \u2502 "] }), _jsxs(Text, { color: colors.primary, children: ["\u2191 ", formatTokens(tokens), " tokens"] })] })] })] }));
|
|
42
|
+
return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: theme.border, children: '─'.repeat(termWidth) }), _jsxs(Box, { justifyContent: "space-between", width: termWidth, children: [_jsxs(Box, { children: [_jsx(Text, { color: theme.dim, children: ' ◇ ' }), _jsx(Text, { color: theme.accent, children: modeLabel }), _jsx(Text, { color: theme.border, children: ' │ ' }), _jsx(Text, { color: theme.dim, children: "/help" }), isProcessing && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.border, children: ' │ ' }), _jsx(Text, { color: theme.highlight, children: icons.spinner[spinnerFrame] })] }))] }), _jsxs(Box, { children: [_jsx(Text, { color: theme.dim, children: elapsed }), _jsx(Text, { color: theme.border, children: ' │ ' }), _jsxs(Text, { color: theme.accent, children: ["\u2191 ", formatTokens(tokens)] }), _jsx(Text, { color: theme.dim, children: ' tokens ' })] })] })] }));
|
|
39
43
|
};
|
|
40
44
|
export default StatusBar;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from 'react';
|
|
3
|
+
import { Box, Text } from 'ink';
|
|
4
|
+
// Sophisticated theme
|
|
5
|
+
const theme = {
|
|
6
|
+
accent: '#4fd1c5',
|
|
7
|
+
highlight: '#81e6d9',
|
|
8
|
+
dim: '#4a5568',
|
|
9
|
+
purple: '#9f7aea',
|
|
10
|
+
};
|
|
11
|
+
// Fun processing verbs
|
|
12
|
+
const verbs = [
|
|
13
|
+
'Contemplating',
|
|
14
|
+
'Synthesizing',
|
|
15
|
+
'Analyzing',
|
|
16
|
+
'Processing',
|
|
17
|
+
'Computing',
|
|
18
|
+
'Reasoning',
|
|
19
|
+
'Deliberating',
|
|
20
|
+
'Pondering',
|
|
21
|
+
'Evaluating',
|
|
22
|
+
'Formulating',
|
|
23
|
+
];
|
|
24
|
+
// Smooth braille spinner - the classic elegant choice
|
|
25
|
+
const symbols = ['⣾', '⣽', '⣻', '⢿', '⡿', '⣟', '⣯', '⣷'];
|
|
26
|
+
export const ThinkingIndicator = ({ startTime, tokens = 0, }) => {
|
|
27
|
+
const [elapsed, setElapsed] = useState('0s');
|
|
28
|
+
const [frame, setFrame] = useState(0);
|
|
29
|
+
const [verb] = useState(() => verbs[Math.floor(Math.random() * verbs.length)]);
|
|
30
|
+
// Update elapsed time
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const interval = setInterval(() => {
|
|
33
|
+
const secs = Math.floor((Date.now() - startTime.getTime()) / 1000);
|
|
34
|
+
const mins = Math.floor(secs / 60);
|
|
35
|
+
const remainingSecs = secs % 60;
|
|
36
|
+
if (mins > 0) {
|
|
37
|
+
setElapsed(`${mins}m ${remainingSecs}s`);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
setElapsed(`${secs}s`);
|
|
41
|
+
}
|
|
42
|
+
}, 1000);
|
|
43
|
+
return () => clearInterval(interval);
|
|
44
|
+
}, [startTime]);
|
|
45
|
+
// Animate symbol
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const interval = setInterval(() => {
|
|
48
|
+
setFrame(f => (f + 1) % symbols.length);
|
|
49
|
+
}, 120);
|
|
50
|
+
return () => clearInterval(interval);
|
|
51
|
+
}, []);
|
|
52
|
+
const formatTokens = (t) => {
|
|
53
|
+
if (t >= 1000)
|
|
54
|
+
return `${(t / 1000).toFixed(1)}k`;
|
|
55
|
+
return t.toString();
|
|
56
|
+
};
|
|
57
|
+
return (_jsxs(Box, { marginY: 1, marginLeft: 1, children: [_jsxs(Text, { color: theme.purple, bold: true, children: [symbols[frame], " "] }), _jsxs(Text, { color: theme.highlight, italic: true, children: [verb, "\u2026"] }), _jsx(Text, { color: theme.dim, children: " (" }), _jsx(Text, { color: theme.dim, children: "ctrl+c to interrupt" }), _jsx(Text, { color: theme.dim, children: " \u00B7 " }), _jsx(Text, { color: theme.accent, children: elapsed }), tokens > 0 && (_jsxs(_Fragment, { children: [_jsx(Text, { color: theme.dim, children: " \u00B7 " }), _jsxs(Text, { color: theme.accent, children: ["\u2193 ", formatTokens(tokens)] }), _jsx(Text, { color: theme.dim, children: " tokens" })] })), _jsx(Text, { color: theme.dim, children: " \u00B7 " }), _jsx(Text, { color: theme.purple, children: "thinking" }), _jsx(Text, { color: theme.dim, children: ")" })] }));
|
|
58
|
+
};
|
|
59
|
+
export default ThinkingIndicator;
|
package/dist/components/index.js
CHANGED
package/dist/lib/claude.js
CHANGED
|
@@ -1,44 +1,63 @@
|
|
|
1
1
|
import { spawn } from 'child_process';
|
|
2
2
|
export async function runClaude(prompt, mode) {
|
|
3
|
+
const systemPrompt = getSystemPrompt(mode);
|
|
3
4
|
return new Promise((resolve, reject) => {
|
|
4
|
-
const systemPrompt = getSystemPrompt(mode);
|
|
5
|
-
// Run claude with JSON output to capture tokens
|
|
6
5
|
const args = [
|
|
7
6
|
'--print',
|
|
8
7
|
'--output-format', 'json',
|
|
9
8
|
'--system-prompt', systemPrompt,
|
|
10
|
-
prompt
|
|
9
|
+
prompt,
|
|
11
10
|
];
|
|
11
|
+
// Critical: Use 'inherit' for stdin and set ANTHROPIC_API_KEY to empty
|
|
12
|
+
// Fixes hanging issue when spawning Claude from Node.js
|
|
13
|
+
// See: https://github.com/anthropics/claude-code/issues/771
|
|
12
14
|
const claude = spawn('claude', args, {
|
|
13
|
-
stdio: ['
|
|
15
|
+
stdio: ['inherit', 'pipe', 'pipe'],
|
|
16
|
+
env: {
|
|
17
|
+
...process.env,
|
|
18
|
+
ANTHROPIC_API_KEY: '',
|
|
19
|
+
},
|
|
14
20
|
});
|
|
15
21
|
let stdout = '';
|
|
16
22
|
let stderr = '';
|
|
17
|
-
|
|
23
|
+
let resolved = false;
|
|
24
|
+
const timeout = setTimeout(() => {
|
|
25
|
+
if (!resolved) {
|
|
26
|
+
resolved = true;
|
|
27
|
+
claude.kill();
|
|
28
|
+
reject(new Error('Claude request timed out after 2 minutes'));
|
|
29
|
+
}
|
|
30
|
+
}, 120000);
|
|
31
|
+
claude.stdout?.on('data', (data) => {
|
|
18
32
|
stdout += data.toString();
|
|
19
33
|
});
|
|
20
|
-
claude.stderr
|
|
34
|
+
claude.stderr?.on('data', (data) => {
|
|
21
35
|
stderr += data.toString();
|
|
22
36
|
});
|
|
23
37
|
claude.on('close', (code) => {
|
|
24
|
-
|
|
38
|
+
clearTimeout(timeout);
|
|
39
|
+
if (resolved)
|
|
40
|
+
return;
|
|
41
|
+
resolved = true;
|
|
42
|
+
if (code !== 0 && !stdout) {
|
|
25
43
|
reject(new Error(stderr || `Claude exited with code ${code}`));
|
|
26
44
|
return;
|
|
27
45
|
}
|
|
28
46
|
try {
|
|
29
|
-
|
|
30
|
-
const result = parseClaudeOutput(stdout);
|
|
31
|
-
resolve(result);
|
|
47
|
+
resolve(parseClaudeOutput(stdout));
|
|
32
48
|
}
|
|
33
|
-
catch
|
|
34
|
-
// If not JSON, return as plain text
|
|
49
|
+
catch {
|
|
35
50
|
resolve({
|
|
36
|
-
response: stdout.trim(),
|
|
51
|
+
response: stdout.trim() || 'No response from Claude',
|
|
37
52
|
tokens: { input: 0, output: 0 },
|
|
38
53
|
});
|
|
39
54
|
}
|
|
40
55
|
});
|
|
41
56
|
claude.on('error', (err) => {
|
|
57
|
+
clearTimeout(timeout);
|
|
58
|
+
if (resolved)
|
|
59
|
+
return;
|
|
60
|
+
resolved = true;
|
|
42
61
|
reject(new Error(`Failed to start Claude: ${err.message}`));
|
|
43
62
|
});
|
|
44
63
|
});
|
|
@@ -46,7 +65,6 @@ export async function runClaude(prompt, mode) {
|
|
|
46
65
|
function parseClaudeOutput(output) {
|
|
47
66
|
try {
|
|
48
67
|
const json = JSON.parse(output);
|
|
49
|
-
// Extract response text
|
|
50
68
|
let response = '';
|
|
51
69
|
if (json.result) {
|
|
52
70
|
response = json.result;
|
|
@@ -65,7 +83,6 @@ function parseClaudeOutput(output) {
|
|
|
65
83
|
else {
|
|
66
84
|
response = output;
|
|
67
85
|
}
|
|
68
|
-
// Extract tokens
|
|
69
86
|
const tokens = {
|
|
70
87
|
input: json.usage?.input_tokens || json.inputTokens || json.stats?.input_tokens || 0,
|
|
71
88
|
output: json.usage?.output_tokens || json.outputTokens || json.stats?.output_tokens || 0,
|
|
@@ -79,30 +96,145 @@ function parseClaudeOutput(output) {
|
|
|
79
96
|
};
|
|
80
97
|
}
|
|
81
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* ORCHESTRATOR SYSTEM PROMPT
|
|
101
|
+
*
|
|
102
|
+
* Based on comparative analysis of:
|
|
103
|
+
* - Anthropic's Multi-Agent Research System (orchestrator-worker pattern)
|
|
104
|
+
* - CrewAI Framework (role-goal-backstory)
|
|
105
|
+
* - Microsoft Azure AI Agent Patterns (task decomposition)
|
|
106
|
+
* - Claude Chain-of-Thought best practices
|
|
107
|
+
*
|
|
108
|
+
* Sources:
|
|
109
|
+
* - https://www.anthropic.com/engineering/multi-agent-research-system
|
|
110
|
+
* - https://github.com/crewAIInc/crewAI
|
|
111
|
+
* - https://learn.microsoft.com/en-us/azure/architecture/ai-ml/guide/ai-agent-design-patterns
|
|
112
|
+
* - https://docs.claude.com/en/docs/build-with-claude/prompt-engineering/chain-of-thought
|
|
113
|
+
*/
|
|
82
114
|
function getSystemPrompt(mode) {
|
|
83
115
|
const today = new Date().toISOString().split('T')[0];
|
|
116
|
+
const orchestratorCore = `# AGENT-K ORCHESTRATOR
|
|
117
|
+
Date: ${today}
|
|
118
|
+
|
|
119
|
+
## ROLE
|
|
120
|
+
You are the Orchestrator—the central intelligence coordinator in AGENT-K, a multi-agent system. You analyze requests, decompose complex tasks, and coordinate specialized agents.
|
|
121
|
+
|
|
122
|
+
## CORE PRINCIPLES
|
|
123
|
+
1. **Analyze First**: Before responding, assess task complexity and scope
|
|
124
|
+
2. **Decompose Intelligently**: Break complex tasks into clear subtasks
|
|
125
|
+
3. **Delegate Strategically**: Identify which agent(s) should handle each part
|
|
126
|
+
4. **Think Transparently**: Show your reasoning process
|
|
127
|
+
5. **Synthesize Results**: Provide cohesive, actionable outputs
|
|
128
|
+
|
|
129
|
+
## RESPONSE PROTOCOL
|
|
130
|
+
|
|
131
|
+
<thinking>
|
|
132
|
+
For each request, analyze:
|
|
133
|
+
- Task type and complexity (Simple | Moderate | Complex)
|
|
134
|
+
- Required expertise areas
|
|
135
|
+
- Dependencies between subtasks
|
|
136
|
+
- Potential challenges or ambiguities
|
|
137
|
+
</thinking>
|
|
138
|
+
|
|
139
|
+
<task_analysis>
|
|
140
|
+
┌─────────────────────────────────────────────────────────
|
|
141
|
+
│ COMPLEXITY: [Simple|Moderate|Complex]
|
|
142
|
+
│ AGENTS: [List involved agents]
|
|
143
|
+
│ SUBTASKS: [If complex, list decomposed tasks]
|
|
144
|
+
└─────────────────────────────────────────────────────────
|
|
145
|
+
</task_analysis>
|
|
146
|
+
|
|
147
|
+
<response>
|
|
148
|
+
[Your comprehensive response here]
|
|
149
|
+
</response>
|
|
150
|
+
|
|
151
|
+
## COMPLEXITY SCALING
|
|
152
|
+
- **Simple** (1 agent, direct response): Factual questions, single-file changes, explanations
|
|
153
|
+
- **Moderate** (2-3 agents, coordinated): Feature implementation, debugging, code review
|
|
154
|
+
- **Complex** (3+ agents, parallel): Architecture design, full features, multi-file refactors`;
|
|
84
155
|
if (mode === 'ml') {
|
|
85
|
-
return
|
|
86
|
-
|
|
156
|
+
return `${orchestratorCore}
|
|
157
|
+
|
|
158
|
+
## MODE: ML Research & Training
|
|
87
159
|
|
|
88
|
-
|
|
89
|
-
1. Analyze ML tasks and break them into subtasks
|
|
90
|
-
2. Coordinate between Researcher, ML Engineer, Data Engineer, and Evaluator
|
|
91
|
-
3. Ensure best practices in ML development
|
|
92
|
-
4. Provide clear, actionable responses
|
|
160
|
+
## SPECIALIST AGENTS
|
|
93
161
|
|
|
94
|
-
|
|
162
|
+
### ◆ Researcher
|
|
163
|
+
- **Role**: Scientific literature specialist
|
|
164
|
+
- **Goal**: Find and synthesize relevant research, identify SOTA approaches
|
|
165
|
+
- **Capabilities**: Paper analysis, benchmark comparisons, methodology review
|
|
166
|
+
- **Triggers**: "What's the best approach for...", architecture decisions, SOTA queries
|
|
167
|
+
|
|
168
|
+
### ◆ ML Engineer
|
|
169
|
+
- **Role**: Model implementation specialist
|
|
170
|
+
- **Goal**: Build robust, efficient ML systems
|
|
171
|
+
- **Capabilities**: PyTorch/JAX/TensorFlow, training loops, custom layers, distributed training
|
|
172
|
+
- **Triggers**: Model building, training issues, optimization, architecture implementation
|
|
173
|
+
|
|
174
|
+
### ◆ Data Engineer
|
|
175
|
+
- **Role**: Data pipeline specialist
|
|
176
|
+
- **Goal**: Ensure clean, efficient data flow
|
|
177
|
+
- **Capabilities**: Preprocessing, augmentation, data loading, format conversion
|
|
178
|
+
- **Triggers**: Data issues, pipeline optimization, dataset preparation
|
|
179
|
+
|
|
180
|
+
### ◆ Evaluator
|
|
181
|
+
- **Role**: Metrics and benchmarking specialist
|
|
182
|
+
- **Goal**: Rigorous model assessment and experiment tracking
|
|
183
|
+
- **Capabilities**: Metric implementation, benchmark setup, W&B/MLflow integration
|
|
184
|
+
- **Triggers**: Model evaluation, experiment comparison, performance analysis
|
|
185
|
+
|
|
186
|
+
### ◆ Scout
|
|
187
|
+
- **Role**: External research specialist
|
|
188
|
+
- **Goal**: Find latest implementations, papers, and resources
|
|
189
|
+
- **Capabilities**: arXiv search, HuggingFace Hub, GitHub implementations
|
|
190
|
+
- **Triggers**: "Find papers on...", implementation search, dataset discovery
|
|
191
|
+
|
|
192
|
+
## ML-SPECIFIC CONSIDERATIONS
|
|
193
|
+
When analyzing ML tasks, consider:
|
|
194
|
+
- Model architecture trade-offs (accuracy vs. efficiency)
|
|
195
|
+
- Data requirements and preprocessing complexity
|
|
196
|
+
- Training resources (GPU memory, compute time)
|
|
197
|
+
- Evaluation methodology and baselines
|
|
198
|
+
- Reproducibility and experiment tracking`;
|
|
95
199
|
}
|
|
96
|
-
return
|
|
97
|
-
|
|
200
|
+
return `${orchestratorCore}
|
|
201
|
+
|
|
202
|
+
## MODE: Software Development
|
|
203
|
+
|
|
204
|
+
## SPECIALIST AGENTS
|
|
205
|
+
|
|
206
|
+
### ◆ Engineer
|
|
207
|
+
- **Role**: Code implementation specialist
|
|
208
|
+
- **Goal**: Write clean, efficient, maintainable code
|
|
209
|
+
- **Capabilities**: Feature development, debugging, refactoring, optimization
|
|
210
|
+
- **Triggers**: "Implement...", "Fix...", "Build...", code changes
|
|
211
|
+
|
|
212
|
+
### ◆ Tester
|
|
213
|
+
- **Role**: Quality assurance specialist
|
|
214
|
+
- **Goal**: Ensure code reliability through comprehensive testing
|
|
215
|
+
- **Capabilities**: Unit tests, integration tests, coverage analysis, edge cases
|
|
216
|
+
- **Triggers**: "Test...", "Verify...", after implementations, quality checks
|
|
217
|
+
|
|
218
|
+
### ◆ Security
|
|
219
|
+
- **Role**: Security analysis specialist
|
|
220
|
+
- **Goal**: Identify and prevent vulnerabilities
|
|
221
|
+
- **Capabilities**: OWASP review, secrets detection, input validation, auth patterns
|
|
222
|
+
- **Triggers**: Auth code, user input handling, API security, before deployments
|
|
98
223
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
224
|
+
### ◆ Scout
|
|
225
|
+
- **Role**: External research specialist
|
|
226
|
+
- **Goal**: Find current best practices and solutions
|
|
227
|
+
- **Capabilities**: Documentation search, library comparison, Stack Overflow, GitHub
|
|
228
|
+
- **Triggers**: Library selection, unfamiliar patterns, error investigation
|
|
104
229
|
|
|
105
|
-
|
|
230
|
+
## DEV-SPECIFIC CONSIDERATIONS
|
|
231
|
+
When analyzing development tasks, consider:
|
|
232
|
+
- Code architecture and design patterns
|
|
233
|
+
- Testing strategy and coverage requirements
|
|
234
|
+
- Security implications (OWASP Top 10)
|
|
235
|
+
- Performance and scalability
|
|
236
|
+
- Dependencies and compatibility
|
|
237
|
+
- Error handling and edge cases`;
|
|
106
238
|
}
|
|
107
239
|
export async function checkClaudeInstalled() {
|
|
108
240
|
return new Promise((resolve) => {
|
package/dist/themes/retro.d.ts
CHANGED
package/dist/themes/retro.js
CHANGED