-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagent
More file actions
executable file
·539 lines (452 loc) · 16.2 KB
/
agent
File metadata and controls
executable file
·539 lines (452 loc) · 16.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
#!/bin/bash
# Simplified agent manager for parallel development with named agents
COMMAND=${1}
AGENT_NAME=${2}
# Load agent config
CONFIG_FILE="config/agents.json"
# Get agents workspace path
if command -v jq &> /dev/null && [ -f "$CONFIG_FILE" ]; then
AGENTS_WORKSPACE_PATH=$(jq -r ".agentsWorkspacePath" "$CONFIG_FILE" | sed "s|~|$HOME|g")
else
AGENTS_WORKSPACE_PATH="$HOME/Developer/agent54-agents"
fi
# Colors for agents
COLORS=("#00ff00" "#ff00ff" "#00ffff" "#ff8c00" "#ff0000" "#ffff00" "#9400d3" "#0000ff" "#7fff00" "#ff1493" "#40e0d0" "#ffd700")
NAMES=("Lime Green" "Hot Pink" "Cyan" "Dark Orange" "Bright Red" "Yellow" "Violet" "Blue" "Chartreuse" "Deep Pink" "Turquoise" "Gold")
# Hash agent name to get consistent color
hash_to_color_index() {
local name=$1
local hash=0
for (( i=0; i<${#name}; i++ )); do
hash=$(( (hash * 31 + $(printf "%d" "'${name:$i:1}")) % ${#COLORS[@]} ))
done
echo $hash
}
# Get agent color info based on name
get_agent_color() {
local name=$1
local color_index=$(hash_to_color_index "$name")
echo "COLOR=${COLORS[$color_index]}"
echo "COLOR_NAME=\"${NAMES[$color_index]}\""
}
# Calculate ports based on agent name hash
calculate_ports() {
local name=$1
local hash=$(hash_to_color_index "$name")
# Ensure unique ports by using hash and name length
local port_offset=$(( (hash * 10 + ${#name}) % 20 ))
echo "VITE_PORT=$((1430 + (port_offset * 10)))"
echo "MCP_PORT=$((3457 + port_offset))"
}
# Normalize agent name (handle shortcuts like "podman" -> find "plugin-podman")
normalize_agent_name() {
local input=$1
# If already has a type prefix, use as-is
if [[ "$input" =~ ^(plugin|docs|feature|fix)- ]]; then
echo "$input"
return
fi
# Look for existing agents that match the shorthand
if [ -d "$AGENTS_WORKSPACE_PATH" ]; then
for dir in "$AGENTS_WORKSPACE_PATH"/agent-*; do
if [ -d "$dir" ]; then
local full_name=$(basename "$dir" | sed 's/^agent-//')
# Check if the full name ends with the input
if [[ "$full_name" == *"-$input" ]]; then
echo "$full_name"
return
fi
fi
done
fi
# No match found, return as-is
echo "$input"
}
# Get agent type from name
get_agent_type() {
local name=$1
if [[ "$name" =~ ^plugin- ]]; then
echo "plugin"
elif [[ "$name" =~ ^docs- ]]; then
echo "docs"
elif [[ "$name" =~ ^feature- ]]; then
echo "feature"
elif [[ "$name" =~ ^fix- ]]; then
echo "fix"
else
echo "general"
fi
}
# Get agent task from task file
get_agent_task() {
local workspace_dir=$1
local task_file="$workspace_dir/.agent/task.md"
if [ -f "$task_file" ]; then
task=$(cat "$task_file")
if [ -n "$task" ] && [ "$task" != "[No task assigned yet]" ]; then
echo "$task"
fi
fi
}
case $COMMAND in
start)
if [ -z "$AGENT_NAME" ]; then
echo "Usage: ./agent start <name> [task]"
echo "Examples:"
echo " ./agent start plugin-podman"
echo " ./agent start docs-review \"Review API documentation\""
echo " ./agent start feature-auth"
exit 1
fi
# Get optional task from remaining arguments
TASK="${@:3}"
# Normalize the name
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
WORKSPACE_DIR="$AGENTS_WORKSPACE_PATH/agent-$AGENT_NAME"
# Create workspace if it doesn't exist
if [ ! -d "$WORKSPACE_DIR" ]; then
echo "🔧 Creating Agent '$AGENT_NAME' workspace..."
./scripts/agents/create-agent-workspace.sh "$AGENT_NAME"
fi
# Navigate to workspace and start
cd "$WORKSPACE_DIR" || exit 1
# Set task if provided
if [ -n "$TASK" ]; then
mkdir -p "$WORKSPACE_DIR/.agent"
echo "$TASK" > "$WORKSPACE_DIR/.agent/task.md"
echo "✅ Task set: $TASK"
echo ""
fi
# Get ports and color info
eval $(calculate_ports "$AGENT_NAME")
export VITE_PORT MCP_PORT
# Get color info
eval $(get_agent_color "$AGENT_NAME")
echo "🚀 Starting Agent '$AGENT_NAME'"
echo "🎨 Color: $COLOR_NAME"
echo "📁 Type: $(get_agent_type "$AGENT_NAME")"
echo "📡 Vite: http://localhost:$VITE_PORT"
echo "🔌 MCP: http://localhost:$MCP_PORT/sse"
# Show current task if set
STORED_TASK=$(get_agent_task "$WORKSPACE_DIR")
if [ -n "$STORED_TASK" ]; then
echo "📋 Task: $STORED_TASK"
fi
echo ""
echo "💡 Run 'claude' in your editor to start planning"
echo "🚀 Start dev server with: bun tauri dev"
;;
stop)
if [ -z "$AGENT_NAME" ]; then
echo "Usage: ./agent stop <name>"
exit 1
fi
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
# Just stop the running processes, keep workspace
eval $(calculate_ports "$AGENT_NAME")
if lsof -ti:$VITE_PORT >/dev/null 2>&1; then
lsof -ti:$VITE_PORT | xargs kill -9 2>/dev/null || true
lsof -ti:$MCP_PORT | xargs kill -9 2>/dev/null || true
echo "✅ Agent '$AGENT_NAME' stopped"
else
echo "⚠️ Agent '$AGENT_NAME' was not running"
fi
;;
kill)
if [ -z "$AGENT_NAME" ]; then
echo "Usage: ./agent kill <name>"
exit 1
fi
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
WORKSPACE_DIR="$AGENTS_WORKSPACE_PATH/agent-$AGENT_NAME"
# Kill any running processes for this agent
eval $(calculate_ports "$AGENT_NAME")
lsof -ti:$VITE_PORT | xargs kill -9 2>/dev/null || true
lsof -ti:$MCP_PORT | xargs kill -9 2>/dev/null || true
# Remove workspace
git worktree remove "$WORKSPACE_DIR" --force 2>/dev/null || true
rm -rf "$WORKSPACE_DIR"
# Clean up branches
git branch -D "agent-$AGENT_NAME-main" 2>/dev/null || true
echo "✅ Agent '$AGENT_NAME' killed and cleaned up"
;;
task)
if [ -z "$AGENT_NAME" ] || [ -z "$3" ]; then
echo "Usage: ./agent task <name> \"task description\""
exit 1
fi
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
TASK="${@:3}"
WORKSPACE_DIR="$AGENTS_WORKSPACE_PATH/agent-$AGENT_NAME"
if [ ! -d "$WORKSPACE_DIR" ]; then
echo "❌ Agent '$AGENT_NAME' workspace doesn't exist"
echo "Create it with: ./agent start $AGENT_NAME"
exit 1
fi
# Simply write to task file
mkdir -p "$WORKSPACE_DIR/.agent"
echo "$TASK" > "$WORKSPACE_DIR/.agent/task.md"
echo "✅ Agent '$AGENT_NAME' task set: $TASK"
;;
status)
echo "🤖 Agent Status"
echo "=============="
echo ""
# List active agents with details
if [ -d "$AGENTS_WORKSPACE_PATH" ]; then
for dir in "$AGENTS_WORKSPACE_PATH"/agent-*; do
if [ -d "$dir" ]; then
AGENT_NAME=$(basename "$dir" | sed 's/^agent-//')
eval $(calculate_ports "$AGENT_NAME")
eval $(get_agent_color "$AGENT_NAME")
# Check if running
if lsof -ti:$VITE_PORT >/dev/null 2>&1; then
STATUS="🟢 Running"
else
STATUS="⭕ Stopped"
fi
# Get current branch
BRANCH=$(cd "$dir" && git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
# Get task
TASK=$(get_agent_task "$dir")
if [ -z "$TASK" ]; then
TASK="No task set"
fi
echo "Agent '$AGENT_NAME' ($COLOR_NAME)"
echo " Type: $(get_agent_type "$AGENT_NAME")"
echo " Status: $STATUS"
echo " Ports: Vite=$VITE_PORT, MCP=$MCP_PORT"
echo " Branch: $BRANCH"
echo " Task: $TASK"
echo ""
fi
done
else
echo "No agent workspaces found"
echo ""
echo "Create your first agent with: ./agent start plugin-example"
fi
;;
open)
if [ -z "$AGENT_NAME" ]; then
echo "Usage: ./agent open <name>"
exit 1
fi
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
WORKSPACE_DIR="$AGENTS_WORKSPACE_PATH/agent-$AGENT_NAME"
if [ ! -d "$WORKSPACE_DIR" ]; then
echo "❌ Agent '$AGENT_NAME' workspace doesn't exist"
echo "Create it with: ./agent start $AGENT_NAME"
exit 1
fi
# Get agent info
eval $(get_agent_color "$AGENT_NAME")
eval $(calculate_ports "$AGENT_NAME")
# Open in Cursor/VSCode
if command -v cursor &> /dev/null; then
echo "🚀 Opening Agent '$AGENT_NAME' ($COLOR_NAME) in Cursor..."
cursor "$WORKSPACE_DIR/xe-launcher-v2-agent-$AGENT_NAME.code-workspace"
echo ""
echo "📝 To start Claude in plan mode:"
echo " 1. Open terminal in Cursor (Cmd+J)"
echo " 2. Run: claude"
echo ""
echo "Agent '$AGENT_NAME' is configured with:"
echo " - Type: $(get_agent_type "$AGENT_NAME")"
echo " - Ports: Vite=$VITE_PORT, MCP=$MCP_PORT"
echo " - Task: Check .agent/task.md"
elif command -v code &> /dev/null; then
echo "🚀 Opening Agent '$AGENT_NAME' in VSCode..."
code "$WORKSPACE_DIR/xe-launcher-v2-agent-$AGENT_NAME.code-workspace"
else
echo "❌ Neither Cursor nor VSCode found"
fi
;;
list)
# Simple list of available agents
echo "Available agents:"
if [ -d "$AGENTS_WORKSPACE_PATH" ]; then
for dir in "$AGENTS_WORKSPACE_PATH"/agent-*; do
if [ -d "$dir" ]; then
AGENT_NAME=$(basename "$dir" | sed 's/^agent-//')
eval $(get_agent_color "$AGENT_NAME")
echo " $AGENT_NAME - $COLOR_NAME ($(get_agent_type "$AGENT_NAME"))"
fi
done
else
echo " None"
fi
;;
pr)
if [ -z "$AGENT_NAME" ]; then
echo "Usage: ./agent pr <name> [title]"
exit 1
fi
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
WORKSPACE_DIR="$AGENTS_WORKSPACE_PATH/agent-$AGENT_NAME"
if [ ! -d "$WORKSPACE_DIR" ]; then
echo "❌ Agent '$AGENT_NAME' workspace doesn't exist"
exit 1
fi
# Get agent color
eval $(get_agent_color "$AGENT_NAME")
cd "$WORKSPACE_DIR" || exit 1
# Get current branch
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
# Get task for default title
TASK=$(get_agent_task "$WORKSPACE_DIR")
# Map color names to emojis
case "$COLOR_NAME" in
"Lime Green") COLOR_EMOJI="🟢" ;;
"Hot Pink") COLOR_EMOJI="🩷" ;;
"Cyan") COLOR_EMOJI="🔵" ;;
"Dark Orange") COLOR_EMOJI="🟠" ;;
"Bright Red") COLOR_EMOJI="🔴" ;;
"Yellow") COLOR_EMOJI="🟡" ;;
"Violet") COLOR_EMOJI="🟣" ;;
"Blue") COLOR_EMOJI="🔷" ;;
"Chartreuse") COLOR_EMOJI="💚" ;;
"Deep Pink") COLOR_EMOJI="💖" ;;
"Turquoise") COLOR_EMOJI="🟦" ;;
"Gold") COLOR_EMOJI="🟨" ;;
*) COLOR_EMOJI="⚪" ;;
esac
DEFAULT_TITLE="$COLOR_EMOJI [$COLOR_NAME] ${TASK:-$AGENT_NAME changes}"
TITLE="${3:-$DEFAULT_TITLE}"
# Push current branch
echo "📤 Pushing $CURRENT_BRANCH..."
git push -u origin "$CURRENT_BRANCH"
# Create PR with color in title
echo "🔄 Creating pull request..."
gh pr create --title "$TITLE" --body "Changes from Agent '$AGENT_NAME' ($COLOR_NAME)
Task: ${TASK:-No specific task assigned}
Branch: $CURRENT_BRANCH
Type: $(get_agent_type "$AGENT_NAME")
---
Created by $COLOR_NAME Agent ($AGENT_NAME)"
;;
claude)
if [ -z "$AGENT_NAME" ]; then
echo "Usage: ./agent claude <name>"
echo "Example: ./agent claude podman"
exit 1
fi
AGENT_NAME=$(normalize_agent_name "$AGENT_NAME")
WORKSPACE_DIR="$AGENTS_WORKSPACE_PATH/agent-$AGENT_NAME"
if [ ! -d "$WORKSPACE_DIR" ]; then
echo "❌ Agent '$AGENT_NAME' workspace doesn't exist"
echo "Create it with: ./agent start $AGENT_NAME"
exit 1
fi
# Get agent info for context
eval $(get_agent_color "$AGENT_NAME")
eval $(calculate_ports "$AGENT_NAME")
TASK=$(get_agent_task "$WORKSPACE_DIR")
# Change to workspace directory
cd "$WORKSPACE_DIR" || exit 1
echo "🤖 Starting Claude Code for Agent '$AGENT_NAME' ($COLOR_NAME)"
echo "📋 Task: ${TASK:-No task assigned}"
echo ""
# Start Claude with agent context
$HOME/.claude/local/claude --permission-mode plan "You are Agent '$AGENT_NAME' ($COLOR_NAME).
Your mission: ${TASK:-Check .agent/task.md}
⚡ WORKFLOW REMINDER:
1. Research thoroughly before exiting plan mode
2. Stay focused on your assigned scope
3. Keep your branch rebased with main
4. Test before marking complete
5. You're part of a team - respect boundaries
Key info:
- Type: $(get_agent_type "$AGENT_NAME")
- Vite port: $VITE_PORT
- MCP port: $MCP_PORT
- Branch: agent-$AGENT_NAME-main
Read docs/AGENT_WORKFLOW.md for your complete workflow guide."
;;
reset-all)
echo "🔥 WARNING: This will remove ALL agent workspaces and branches!"
echo ""
# List what will be removed
if [ -d "$AGENTS_WORKSPACE_PATH" ]; then
echo "Workspaces to remove:"
for dir in "$AGENTS_WORKSPACE_PATH"/agent-*; do
if [ -d "$dir" ]; then
AGENT_NAME=$(basename "$dir" | sed 's/^agent-//')
eval $(get_agent_color "$AGENT_NAME")
echo " - Agent '$AGENT_NAME' ($COLOR_NAME)"
fi
done
echo ""
fi
# Check for --yes flag
if [[ "$2" == "--yes" || "$2" == "-y" ]]; then
REPLY="yes"
else
read -p "Are you sure? Type 'yes' to confirm: " -r
fi
if [[ $REPLY == "yes" ]]; then
echo ""
echo "🧹 Cleaning up all agents..."
# Stop all running agents
for port in $(seq 1430 10 1630); do
lsof -ti:$port | xargs kill -9 2>/dev/null || true
done
# Remove all agent workspaces
if [ -d "$AGENTS_WORKSPACE_PATH" ]; then
for dir in "$AGENTS_WORKSPACE_PATH"/agent-*; do
if [ -d "$dir" ]; then
AGENT_NAME=$(basename "$dir" | sed 's/^agent-//')
echo "Removing Agent '$AGENT_NAME'..."
git worktree remove "$dir" --force 2>/dev/null || true
rm -rf "$dir"
fi
done
fi
# Clean up all agent branches
echo "🔧 Cleaning up agent branches..."
git branch | grep -E "agent-.*-main" | xargs -n 1 git branch -D 2>/dev/null || true
# Clear agent registry
echo '{"agents": {}, "lastUpdated": ""}' > .agent-registry.json
# Prune worktree list
git worktree prune
echo "✅ All agents have been reset!"
else
echo "❌ Reset cancelled"
fi
;;
*)
echo "🤖 Agent Manager - Named Agents"
echo "==============================="
echo ""
echo "Commands:"
echo " ./agent start <name> [task] Start agent with optional task"
echo " ./agent stop <name> Stop agent (keeps workspace)"
echo " ./agent kill <name> Remove agent and workspace"
echo " ./agent task <name> \"desc\" Set agent task"
echo " ./agent open <name> Open in editor (shortcuts work: podman → plugin-podman)"
echo " ./agent claude <name> Start Claude Code in agent workspace"
echo " ./agent pr <name> [title] Create PR with color emoji + label"
echo " ./agent status Show all agents"
echo " ./agent list List agent names"
echo " ./agent reset-all [-y] Remove ALL agents"
echo ""
echo "Agent Types:"
echo " plugin-* Plugin development (e.g. plugin-podman, plugin-ollama)"
echo " docs-* Documentation (e.g. docs-review, docs-api)"
echo " feature-* Feature development (e.g. feature-auth, feature-ui)"
echo " fix-* Bug fixes (e.g. fix-build-loop)"
echo ""
echo "Example workflow:"
echo " ./agent start plugin-podman \"Implement Podman container management\""
echo " ./agent open podman # shortcut works!"
echo " ./agent claude podman # start Claude in agent context"
echo " # ... make changes ..."
echo " ./agent pr podman"
echo ""
echo "Or set task separately:"
echo " ./agent start docs-api"
echo " ./agent task docs-api \"Document all API endpoints\""
echo ""
echo "Agents start in plan mode - run 'claude' in editor terminal"
;;
esac