oh-my-ag 1.2.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/.agent/skills/_shared/api-contracts/README.md +56 -0
- package/.agent/skills/_shared/api-contracts/template.md +88 -0
- package/.agent/skills/_shared/clarification-protocol.md +217 -0
- package/.agent/skills/_shared/common-checklist.md +31 -0
- package/.agent/skills/_shared/context-budget.md +118 -0
- package/.agent/skills/_shared/context-loading.md +105 -0
- package/.agent/skills/_shared/difficulty-guide.md +55 -0
- package/.agent/skills/_shared/lessons-learned.md +113 -0
- package/.agent/skills/_shared/memory-protocol.md +79 -0
- package/.agent/skills/_shared/reasoning-templates.md +161 -0
- package/.agent/skills/_shared/skill-routing.md +80 -0
- package/.agent/skills/_shared/verify.sh +252 -0
- package/.agent/skills/backend-agent/SKILL.md +47 -0
- package/.agent/skills/backend-agent/resources/api-template.py +326 -0
- package/.agent/skills/backend-agent/resources/checklist.md +36 -0
- package/.agent/skills/backend-agent/resources/error-playbook.md +98 -0
- package/.agent/skills/backend-agent/resources/examples.md +85 -0
- package/.agent/skills/backend-agent/resources/execution-protocol.md +45 -0
- package/.agent/skills/backend-agent/resources/snippets.md +197 -0
- package/.agent/skills/backend-agent/resources/tech-stack.md +39 -0
- package/.agent/skills/commit/SKILL.md +121 -0
- package/.agent/skills/commit/config/commit-config.yaml +55 -0
- package/.agent/skills/commit/resources/conventional-commits.md +166 -0
- package/.agent/skills/debug-agent/SKILL.md +51 -0
- package/.agent/skills/debug-agent/resources/bug-report-template.md +332 -0
- package/.agent/skills/debug-agent/resources/checklist.md +30 -0
- package/.agent/skills/debug-agent/resources/common-patterns.md +734 -0
- package/.agent/skills/debug-agent/resources/debugging-checklist.md +362 -0
- package/.agent/skills/debug-agent/resources/error-playbook.md +94 -0
- package/.agent/skills/debug-agent/resources/examples.md +87 -0
- package/.agent/skills/debug-agent/resources/execution-protocol.md +51 -0
- package/.agent/skills/frontend-agent/SKILL.md +48 -0
- package/.agent/skills/frontend-agent/resources/checklist.md +38 -0
- package/.agent/skills/frontend-agent/resources/component-template.tsx +92 -0
- package/.agent/skills/frontend-agent/resources/error-playbook.md +108 -0
- package/.agent/skills/frontend-agent/resources/examples.md +77 -0
- package/.agent/skills/frontend-agent/resources/execution-protocol.md +49 -0
- package/.agent/skills/frontend-agent/resources/snippets.md +205 -0
- package/.agent/skills/frontend-agent/resources/tailwind-rules.md +343 -0
- package/.agent/skills/frontend-agent/resources/tech-stack.md +36 -0
- package/.agent/skills/mobile-agent/SKILL.md +46 -0
- package/.agent/skills/mobile-agent/resources/checklist.md +35 -0
- package/.agent/skills/mobile-agent/resources/error-playbook.md +106 -0
- package/.agent/skills/mobile-agent/resources/examples.md +79 -0
- package/.agent/skills/mobile-agent/resources/execution-protocol.md +49 -0
- package/.agent/skills/mobile-agent/resources/screen-template.dart +298 -0
- package/.agent/skills/mobile-agent/resources/snippets.md +235 -0
- package/.agent/skills/mobile-agent/resources/tech-stack.md +45 -0
- package/.agent/skills/orchestrator/SKILL.md +99 -0
- package/.agent/skills/orchestrator/config/cli-config.yaml +78 -0
- package/.agent/skills/orchestrator/resources/memory-schema.md +212 -0
- package/.agent/skills/orchestrator/resources/subagent-prompt-template.md +153 -0
- package/.agent/skills/orchestrator/scripts/parallel-run.sh +330 -0
- package/.agent/skills/orchestrator/scripts/spawn-agent.sh +263 -0
- package/.agent/skills/orchestrator/templates/backend-task.md +18 -0
- package/.agent/skills/orchestrator/templates/debug-task.md +16 -0
- package/.agent/skills/orchestrator/templates/frontend-task.md +17 -0
- package/.agent/skills/orchestrator/templates/mobile-task.md +17 -0
- package/.agent/skills/orchestrator/templates/qa-task.md +16 -0
- package/.agent/skills/orchestrator/templates/tasks-example.yaml +15 -0
- package/.agent/skills/pm-agent/SKILL.md +47 -0
- package/.agent/skills/pm-agent/resources/error-playbook.md +75 -0
- package/.agent/skills/pm-agent/resources/examples.md +121 -0
- package/.agent/skills/pm-agent/resources/execution-protocol.md +46 -0
- package/.agent/skills/pm-agent/resources/task-template.json +57 -0
- package/.agent/skills/qa-agent/SKILL.md +43 -0
- package/.agent/skills/qa-agent/resources/checklist.md +294 -0
- package/.agent/skills/qa-agent/resources/error-playbook.md +95 -0
- package/.agent/skills/qa-agent/resources/examples.md +100 -0
- package/.agent/skills/qa-agent/resources/execution-protocol.md +50 -0
- package/.agent/skills/qa-agent/resources/self-check.md +27 -0
- package/.agent/skills/workflow-guide/SKILL.md +57 -0
- package/.agent/skills/workflow-guide/resources/examples.md +68 -0
- package/README.ko.md +459 -0
- package/README.md +563 -0
- package/bin/cli.js +205 -0
- package/package.json +75 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# parallel-run.sh - Run multiple sub-agents in parallel
|
|
3
|
+
# Usage: ./parallel-run.sh <tasks-file.yaml> [--vendor <vendor>]
|
|
4
|
+
# ./parallel-run.sh --inline "backend:task1" "frontend:task2" ...
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
9
|
+
SPAWN_SCRIPT="${SCRIPT_DIR}/spawn-agent.sh"
|
|
10
|
+
RESULTS_DIR=".agent/results"
|
|
11
|
+
|
|
12
|
+
# Colors
|
|
13
|
+
RED='\033[0;31m'
|
|
14
|
+
GREEN='\033[0;32m'
|
|
15
|
+
YELLOW='\033[1;33m'
|
|
16
|
+
BLUE='\033[0;34m'
|
|
17
|
+
CYAN='\033[0;36m'
|
|
18
|
+
NC='\033[0m'
|
|
19
|
+
|
|
20
|
+
# Parse arguments
|
|
21
|
+
TASKS_FILE=""
|
|
22
|
+
VENDOR=""
|
|
23
|
+
INLINE_MODE=false
|
|
24
|
+
INLINE_TASKS=()
|
|
25
|
+
WAIT_MODE=true
|
|
26
|
+
|
|
27
|
+
show_help() {
|
|
28
|
+
echo "Usage: parallel-run.sh [options] <tasks-file.yaml>"
|
|
29
|
+
echo " parallel-run.sh --inline \"agent:task\" \"agent:task\" ..."
|
|
30
|
+
echo ""
|
|
31
|
+
echo "Options:"
|
|
32
|
+
echo " --vendor, -v CLI vendor (gemini, claude, codex, qwen)"
|
|
33
|
+
echo " --inline, -i Inline mode: specify tasks as arguments"
|
|
34
|
+
echo " --no-wait Don't wait for completion (background mode)"
|
|
35
|
+
echo " --help, -h Show this help message"
|
|
36
|
+
echo ""
|
|
37
|
+
echo "Tasks file format (YAML):"
|
|
38
|
+
echo " tasks:"
|
|
39
|
+
echo " - agent: backend"
|
|
40
|
+
echo " task: \"Implement auth API\""
|
|
41
|
+
echo " workspace: ./backend"
|
|
42
|
+
echo " - agent: frontend"
|
|
43
|
+
echo " task: \"Create login UI\""
|
|
44
|
+
echo " workspace: ./frontend"
|
|
45
|
+
echo ""
|
|
46
|
+
echo "Inline format:"
|
|
47
|
+
echo " parallel-run.sh --inline \"backend:Implement auth\" \"frontend:Create login\""
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
while [[ $# -gt 0 ]]; do
|
|
51
|
+
case $1 in
|
|
52
|
+
--vendor|-v)
|
|
53
|
+
VENDOR="$2"
|
|
54
|
+
shift 2
|
|
55
|
+
;;
|
|
56
|
+
--inline|-i)
|
|
57
|
+
INLINE_MODE=true
|
|
58
|
+
shift
|
|
59
|
+
;;
|
|
60
|
+
--no-wait)
|
|
61
|
+
WAIT_MODE=false
|
|
62
|
+
shift
|
|
63
|
+
;;
|
|
64
|
+
--help|-h)
|
|
65
|
+
show_help
|
|
66
|
+
exit 0
|
|
67
|
+
;;
|
|
68
|
+
*)
|
|
69
|
+
if [[ "$INLINE_MODE" == true ]]; then
|
|
70
|
+
INLINE_TASKS+=("$1")
|
|
71
|
+
else
|
|
72
|
+
TASKS_FILE="$1"
|
|
73
|
+
fi
|
|
74
|
+
shift
|
|
75
|
+
;;
|
|
76
|
+
esac
|
|
77
|
+
done
|
|
78
|
+
|
|
79
|
+
# Create results directory
|
|
80
|
+
mkdir -p "$RESULTS_DIR"
|
|
81
|
+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
82
|
+
RUN_DIR="${RESULTS_DIR}/parallel-${TIMESTAMP}"
|
|
83
|
+
mkdir -p "$RUN_DIR"
|
|
84
|
+
|
|
85
|
+
# PID list file for cleanup (especially useful for --no-wait mode)
|
|
86
|
+
PID_LIST_FILE="${RUN_DIR}/pids.txt"
|
|
87
|
+
|
|
88
|
+
# Track PIDs and results
|
|
89
|
+
declare -A PIDS
|
|
90
|
+
declare -A AGENT_NAMES
|
|
91
|
+
|
|
92
|
+
# Cleanup: kill all child processes on exit
|
|
93
|
+
cleanup() {
|
|
94
|
+
echo -e "\n${YELLOW}[Parallel]${NC} Cleaning up child processes..."
|
|
95
|
+
for pid in "${!PIDS[@]}"; do
|
|
96
|
+
if kill -0 "$pid" 2>/dev/null; then
|
|
97
|
+
kill "$pid" 2>/dev/null
|
|
98
|
+
echo -e "${YELLOW}[Parallel]${NC} Killed PID $pid (${AGENT_NAMES[$pid]:-unknown})"
|
|
99
|
+
fi
|
|
100
|
+
done
|
|
101
|
+
wait 2>/dev/null
|
|
102
|
+
# Remove PID list file if all processes are done
|
|
103
|
+
rm -f "$PID_LIST_FILE"
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
trap cleanup EXIT SIGINT SIGTERM
|
|
107
|
+
|
|
108
|
+
echo -e "${CYAN}======================================${NC}"
|
|
109
|
+
echo -e "${CYAN} Parallel SubAgent Execution${NC}"
|
|
110
|
+
echo -e "${CYAN}======================================${NC}"
|
|
111
|
+
echo ""
|
|
112
|
+
|
|
113
|
+
# Parse inline tasks
|
|
114
|
+
parse_inline_tasks() {
|
|
115
|
+
local idx=0
|
|
116
|
+
for task_spec in "${INLINE_TASKS[@]}"; do
|
|
117
|
+
# Format: "agent:task" or "agent:task:workspace"
|
|
118
|
+
IFS=':' read -r agent task workspace <<< "$task_spec"
|
|
119
|
+
workspace="${workspace:-.}"
|
|
120
|
+
|
|
121
|
+
echo -e "${BLUE}[${idx}]${NC} Spawning ${YELLOW}${agent}${NC} agent..."
|
|
122
|
+
|
|
123
|
+
# Build vendor flag
|
|
124
|
+
VENDOR_FLAG=""
|
|
125
|
+
[[ -n "$VENDOR" ]] && VENDOR_FLAG="--vendor $VENDOR"
|
|
126
|
+
|
|
127
|
+
# Spawn in background
|
|
128
|
+
(
|
|
129
|
+
"$SPAWN_SCRIPT" "$agent" "$task" "$workspace" $VENDOR_FLAG \
|
|
130
|
+
> "${RUN_DIR}/${agent}-${idx}.log" 2>&1
|
|
131
|
+
) &
|
|
132
|
+
|
|
133
|
+
PIDS[$!]=$idx
|
|
134
|
+
AGENT_NAMES[$!]=$agent
|
|
135
|
+
echo "$!:$agent" >> "$PID_LIST_FILE"
|
|
136
|
+
((idx++))
|
|
137
|
+
done
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
# Parse YAML tasks file
|
|
141
|
+
parse_yaml_tasks() {
|
|
142
|
+
if [[ ! -f "$TASKS_FILE" ]]; then
|
|
143
|
+
echo -e "${RED}Error: Tasks file not found: ${TASKS_FILE}${NC}"
|
|
144
|
+
exit 1
|
|
145
|
+
fi
|
|
146
|
+
|
|
147
|
+
local idx=0
|
|
148
|
+
local current_agent=""
|
|
149
|
+
local current_task=""
|
|
150
|
+
local current_workspace="."
|
|
151
|
+
|
|
152
|
+
while IFS= read -r line; do
|
|
153
|
+
# Skip empty lines and comments
|
|
154
|
+
[[ -z "$line" ]] && continue
|
|
155
|
+
[[ "$line" =~ ^[[:space:]]*# ]] && continue
|
|
156
|
+
|
|
157
|
+
# Parse agent
|
|
158
|
+
if [[ "$line" =~ agent:[[:space:]]*(.+) ]]; then
|
|
159
|
+
current_agent="${BASH_REMATCH[1]}"
|
|
160
|
+
current_agent=$(echo "$current_agent" | tr -d '"' | xargs)
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
# Parse task
|
|
164
|
+
if [[ "$line" =~ task:[[:space:]]*(.+) ]]; then
|
|
165
|
+
current_task="${BASH_REMATCH[1]}"
|
|
166
|
+
current_task=$(echo "$current_task" | tr -d '"' | xargs)
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
# Parse workspace
|
|
170
|
+
if [[ "$line" =~ workspace:[[:space:]]*(.+) ]]; then
|
|
171
|
+
current_workspace="${BASH_REMATCH[1]}"
|
|
172
|
+
current_workspace=$(echo "$current_workspace" | tr -d '"' | xargs)
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
# Start of new task block (next - agent:)
|
|
176
|
+
if [[ "$line" =~ ^[[:space:]]*-[[:space:]]*agent: ]] && [[ -n "$current_task" ]] && [[ $idx -gt 0 ]]; then
|
|
177
|
+
# Spawn previous task
|
|
178
|
+
spawn_task "$idx" "$current_agent" "$current_task" "$current_workspace"
|
|
179
|
+
current_workspace="."
|
|
180
|
+
current_task=""
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
# Check if we have a complete task
|
|
184
|
+
if [[ -n "$current_agent" ]] && [[ -n "$current_task" ]]; then
|
|
185
|
+
if [[ "$line" =~ ^[[:space:]]*-[[:space:]]*agent: ]]; then
|
|
186
|
+
((idx++))
|
|
187
|
+
fi
|
|
188
|
+
fi
|
|
189
|
+
done < "$TASKS_FILE"
|
|
190
|
+
|
|
191
|
+
# Spawn last task
|
|
192
|
+
if [[ -n "$current_agent" ]] && [[ -n "$current_task" ]]; then
|
|
193
|
+
spawn_task "$idx" "$current_agent" "$current_task" "$current_workspace"
|
|
194
|
+
fi
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
spawn_task() {
|
|
198
|
+
local idx=$1
|
|
199
|
+
local agent=$2
|
|
200
|
+
local task=$3
|
|
201
|
+
local workspace=$4
|
|
202
|
+
|
|
203
|
+
echo -e "${BLUE}[${idx}]${NC} Spawning ${YELLOW}${agent}${NC} agent..."
|
|
204
|
+
echo -e " Task: ${task:0:60}..."
|
|
205
|
+
echo -e " Workspace: ${workspace}"
|
|
206
|
+
|
|
207
|
+
VENDOR_FLAG=""
|
|
208
|
+
[[ -n "$VENDOR" ]] && VENDOR_FLAG="--vendor $VENDOR"
|
|
209
|
+
|
|
210
|
+
(
|
|
211
|
+
"$SPAWN_SCRIPT" "$agent" "$task" "$workspace" $VENDOR_FLAG \
|
|
212
|
+
> "${RUN_DIR}/${agent}-${idx}.log" 2>&1
|
|
213
|
+
) &
|
|
214
|
+
|
|
215
|
+
PIDS[$!]=$idx
|
|
216
|
+
AGENT_NAMES[$!]=$agent
|
|
217
|
+
echo "$!:$agent" >> "$PID_LIST_FILE"
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
# Alternative simpler YAML parsing for common format
|
|
221
|
+
parse_yaml_simple() {
|
|
222
|
+
if [[ ! -f "$TASKS_FILE" ]]; then
|
|
223
|
+
echo -e "${RED}Error: Tasks file not found: ${TASKS_FILE}${NC}"
|
|
224
|
+
exit 1
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
local idx=0
|
|
228
|
+
|
|
229
|
+
# Use grep to find task blocks
|
|
230
|
+
while IFS= read -r block; do
|
|
231
|
+
local agent=$(echo "$block" | grep -oP 'agent:\s*\K[^\s]+' | tr -d '"')
|
|
232
|
+
local task=$(echo "$block" | grep -oP 'task:\s*"\K[^"]+')
|
|
233
|
+
local workspace=$(echo "$block" | grep -oP 'workspace:\s*\K[^\s]+' | tr -d '"')
|
|
234
|
+
|
|
235
|
+
[[ -z "$workspace" ]] && workspace="."
|
|
236
|
+
|
|
237
|
+
if [[ -n "$agent" ]] && [[ -n "$task" ]]; then
|
|
238
|
+
echo -e "${BLUE}[${idx}]${NC} Spawning ${YELLOW}${agent}${NC} agent..."
|
|
239
|
+
echo -e " Task: ${task:0:60}..."
|
|
240
|
+
|
|
241
|
+
VENDOR_FLAG=""
|
|
242
|
+
[[ -n "$VENDOR" ]] && VENDOR_FLAG="--vendor $VENDOR"
|
|
243
|
+
|
|
244
|
+
(
|
|
245
|
+
"$SPAWN_SCRIPT" "$agent" "$task" "$workspace" $VENDOR_FLAG \
|
|
246
|
+
> "${RUN_DIR}/${agent}-${idx}.log" 2>&1
|
|
247
|
+
) &
|
|
248
|
+
|
|
249
|
+
PIDS[$!]=$idx
|
|
250
|
+
AGENT_NAMES[$!]=$agent
|
|
251
|
+
echo "$!:$agent" >> "$PID_LIST_FILE"
|
|
252
|
+
((idx++))
|
|
253
|
+
fi
|
|
254
|
+
done < <(awk '/^[[:space:]]*-[[:space:]]*agent:/{if(block)print block; block=$0; next} {block=block" "$0} END{print block}' "$TASKS_FILE")
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
# Execute tasks
|
|
258
|
+
echo -e "${BLUE}Starting parallel execution...${NC}"
|
|
259
|
+
echo ""
|
|
260
|
+
|
|
261
|
+
if [[ "$INLINE_MODE" == true ]]; then
|
|
262
|
+
if [[ ${#INLINE_TASKS[@]} -eq 0 ]]; then
|
|
263
|
+
echo -e "${RED}Error: No tasks specified${NC}"
|
|
264
|
+
show_help
|
|
265
|
+
exit 1
|
|
266
|
+
fi
|
|
267
|
+
parse_inline_tasks
|
|
268
|
+
else
|
|
269
|
+
if [[ -z "$TASKS_FILE" ]]; then
|
|
270
|
+
echo -e "${RED}Error: No tasks file specified${NC}"
|
|
271
|
+
show_help
|
|
272
|
+
exit 1
|
|
273
|
+
fi
|
|
274
|
+
parse_yaml_simple
|
|
275
|
+
fi
|
|
276
|
+
|
|
277
|
+
TOTAL_TASKS=${#PIDS[@]}
|
|
278
|
+
echo ""
|
|
279
|
+
echo -e "${BLUE}[Parallel]${NC} Started ${YELLOW}${TOTAL_TASKS}${NC} agents"
|
|
280
|
+
|
|
281
|
+
if [[ "$WAIT_MODE" == false ]]; then
|
|
282
|
+
echo -e "${BLUE}[Parallel]${NC} Running in background mode"
|
|
283
|
+
echo -e "${BLUE}[Parallel]${NC} Results will be in: ${RUN_DIR}"
|
|
284
|
+
echo -e "${BLUE}[Parallel]${NC} PID list: ${PID_LIST_FILE}"
|
|
285
|
+
# Disable the cleanup trap so background processes keep running
|
|
286
|
+
trap - EXIT SIGINT SIGTERM
|
|
287
|
+
exit 0
|
|
288
|
+
fi
|
|
289
|
+
|
|
290
|
+
# Wait for all tasks and collect results
|
|
291
|
+
echo -e "${BLUE}[Parallel]${NC} Waiting for completion..."
|
|
292
|
+
echo ""
|
|
293
|
+
|
|
294
|
+
COMPLETED=0
|
|
295
|
+
FAILED=0
|
|
296
|
+
|
|
297
|
+
for pid in "${!PIDS[@]}"; do
|
|
298
|
+
idx=${PIDS[$pid]}
|
|
299
|
+
agent=${AGENT_NAMES[$pid]}
|
|
300
|
+
|
|
301
|
+
if wait $pid; then
|
|
302
|
+
echo -e "${GREEN}[DONE]${NC} ${agent} agent (${idx}) completed"
|
|
303
|
+
((COMPLETED++))
|
|
304
|
+
else
|
|
305
|
+
echo -e "${RED}[FAIL]${NC} ${agent} agent (${idx}) failed"
|
|
306
|
+
((FAILED++))
|
|
307
|
+
fi
|
|
308
|
+
done
|
|
309
|
+
|
|
310
|
+
# Summary
|
|
311
|
+
echo ""
|
|
312
|
+
echo -e "${CYAN}======================================${NC}"
|
|
313
|
+
echo -e "${CYAN} Execution Summary${NC}"
|
|
314
|
+
echo -e "${CYAN}======================================${NC}"
|
|
315
|
+
echo -e "Total: ${TOTAL_TASKS}"
|
|
316
|
+
echo -e "Completed: ${GREEN}${COMPLETED}${NC}"
|
|
317
|
+
echo -e "Failed: ${RED}${FAILED}${NC}"
|
|
318
|
+
echo -e "Results: ${RUN_DIR}"
|
|
319
|
+
echo -e "${CYAN}======================================${NC}"
|
|
320
|
+
|
|
321
|
+
# List result files
|
|
322
|
+
echo ""
|
|
323
|
+
echo -e "${BLUE}Result files:${NC}"
|
|
324
|
+
for f in "${RUN_DIR}"/*.log; do
|
|
325
|
+
[[ -f "$f" ]] && echo " - $f"
|
|
326
|
+
done
|
|
327
|
+
|
|
328
|
+
# Exit with error if any failed
|
|
329
|
+
[[ $FAILED -gt 0 ]] && exit 1
|
|
330
|
+
exit 0
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# spawn-agent.sh - Spawn a sub-agent using configured CLI vendor
|
|
3
|
+
# Usage: ./spawn-agent.sh <agent-type> <task-description> [workspace] [--vendor <vendor>]
|
|
4
|
+
|
|
5
|
+
set -e
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
CONFIG_FILE="${SCRIPT_DIR}/../config/cli-config.yaml"
|
|
9
|
+
RESULTS_DIR=".agent/results"
|
|
10
|
+
|
|
11
|
+
# Colors for output
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
GREEN='\033[0;32m'
|
|
14
|
+
YELLOW='\033[1;33m'
|
|
15
|
+
BLUE='\033[0;34m'
|
|
16
|
+
NC='\033[0m' # No Color
|
|
17
|
+
|
|
18
|
+
# Parse arguments
|
|
19
|
+
AGENT_TYPE=""
|
|
20
|
+
TASK=""
|
|
21
|
+
WORKSPACE="."
|
|
22
|
+
VENDOR=""
|
|
23
|
+
|
|
24
|
+
while [[ $# -gt 0 ]]; do
|
|
25
|
+
case $1 in
|
|
26
|
+
--vendor|-v)
|
|
27
|
+
VENDOR="$2"
|
|
28
|
+
shift 2
|
|
29
|
+
;;
|
|
30
|
+
--help|-h)
|
|
31
|
+
echo "Usage: spawn-agent.sh <agent-type> <task> [workspace] [--vendor <vendor>]"
|
|
32
|
+
echo ""
|
|
33
|
+
echo "Arguments:"
|
|
34
|
+
echo " agent-type Type of agent (backend, frontend, mobile, qa, debug)"
|
|
35
|
+
echo " task Task description or path to task file"
|
|
36
|
+
echo " workspace Working directory for the agent (default: current)"
|
|
37
|
+
echo ""
|
|
38
|
+
echo "Options:"
|
|
39
|
+
echo " --vendor, -v CLI vendor (gemini, claude, codex, qwen)"
|
|
40
|
+
echo " --help, -h Show this help message"
|
|
41
|
+
exit 0
|
|
42
|
+
;;
|
|
43
|
+
*)
|
|
44
|
+
if [[ -z "$AGENT_TYPE" ]]; then
|
|
45
|
+
AGENT_TYPE="$1"
|
|
46
|
+
elif [[ -z "$TASK" ]]; then
|
|
47
|
+
TASK="$1"
|
|
48
|
+
else
|
|
49
|
+
WORKSPACE="$1"
|
|
50
|
+
fi
|
|
51
|
+
shift
|
|
52
|
+
;;
|
|
53
|
+
esac
|
|
54
|
+
done
|
|
55
|
+
|
|
56
|
+
# Validate arguments
|
|
57
|
+
if [[ -z "$AGENT_TYPE" ]] || [[ -z "$TASK" ]]; then
|
|
58
|
+
echo -e "${RED}Error: agent-type and task are required${NC}"
|
|
59
|
+
echo "Usage: spawn-agent.sh <agent-type> <task> [workspace] [--vendor <vendor>]"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# Read config using grep/sed (no yq dependency)
|
|
64
|
+
get_config() {
|
|
65
|
+
local key="$1"
|
|
66
|
+
grep -E "^${key}:" "$CONFIG_FILE" 2>/dev/null | sed 's/^[^:]*: *//' | tr -d '"'
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get_vendor_config() {
|
|
70
|
+
local vendor="$1"
|
|
71
|
+
local key="$2"
|
|
72
|
+
# Simple YAML parsing for nested values
|
|
73
|
+
awk -v vendor="$vendor" -v key="$key" '
|
|
74
|
+
/^ [a-z]+:$/ { current_vendor = $1; gsub(/:/, "", current_vendor) }
|
|
75
|
+
current_vendor == vendor && $1 == key":" { gsub(/^[^:]*: */, ""); gsub(/"/, ""); print }
|
|
76
|
+
' "$CONFIG_FILE"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# Get CLI for specific agent type from user-preferences.yaml
|
|
80
|
+
get_agent_cli() {
|
|
81
|
+
local agent_type="$1"
|
|
82
|
+
local prefs="${SCRIPT_DIR}/../../config/user-preferences.yaml"
|
|
83
|
+
if [[ -f "$prefs" ]]; then
|
|
84
|
+
grep -A10 "^agent_cli_mapping:" "$prefs" 2>/dev/null | \
|
|
85
|
+
grep "^ ${agent_type}:" | \
|
|
86
|
+
sed 's/^[^:]*: *//' | tr -d '"' | xargs
|
|
87
|
+
fi
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Get default CLI from user-preferences.yaml
|
|
91
|
+
get_default_cli() {
|
|
92
|
+
local prefs="${SCRIPT_DIR}/../../config/user-preferences.yaml"
|
|
93
|
+
if [[ -f "$prefs" ]]; then
|
|
94
|
+
grep "^default_cli:" "$prefs" 2>/dev/null | sed 's/^[^:]*: *//' | tr -d '"' | xargs
|
|
95
|
+
fi
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Get vendor from (in priority order):
|
|
99
|
+
# 1) command line arg (--vendor)
|
|
100
|
+
# 2) agent_cli_mapping from user-preferences.yaml
|
|
101
|
+
# 3) default_cli from user-preferences.yaml
|
|
102
|
+
# 4) active_vendor from cli-config.yaml (legacy/fallback)
|
|
103
|
+
# 5) hardcoded "gemini"
|
|
104
|
+
if [[ -z "$VENDOR" ]]; then
|
|
105
|
+
VENDOR=$(get_agent_cli "$AGENT_TYPE")
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
if [[ -z "$VENDOR" ]]; then
|
|
109
|
+
VENDOR=$(get_default_cli)
|
|
110
|
+
fi
|
|
111
|
+
|
|
112
|
+
if [[ -z "$VENDOR" ]]; then
|
|
113
|
+
VENDOR=$(get_config "active_vendor")
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
if [[ -z "$VENDOR" ]]; then
|
|
117
|
+
VENDOR="gemini"
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
echo -e "${BLUE}[SubAgent]${NC} Spawning ${YELLOW}${AGENT_TYPE}${NC} agent with ${GREEN}${VENDOR}${NC} CLI"
|
|
121
|
+
|
|
122
|
+
# Get vendor-specific configuration
|
|
123
|
+
CLI_CMD=$(get_vendor_config "$VENDOR" "command")
|
|
124
|
+
PROMPT_FLAG=$(get_vendor_config "$VENDOR" "prompt_flag")
|
|
125
|
+
OUTPUT_FLAG=$(get_vendor_config "$VENDOR" "output_format_flag")
|
|
126
|
+
OUTPUT_FORMAT=$(get_vendor_config "$VENDOR" "output_format")
|
|
127
|
+
AUTO_FLAG=$(get_vendor_config "$VENDOR" "auto_approve_flag")
|
|
128
|
+
RESPONSE_JQ=$(get_vendor_config "$VENDOR" "response_jq")
|
|
129
|
+
|
|
130
|
+
# Fallback defaults
|
|
131
|
+
CLI_CMD="${CLI_CMD:-$VENDOR}"
|
|
132
|
+
PROMPT_FLAG="${PROMPT_FLAG:--p}"
|
|
133
|
+
OUTPUT_FORMAT="${OUTPUT_FORMAT:-json}"
|
|
134
|
+
RESPONSE_JQ="${RESPONSE_JQ:-.response}"
|
|
135
|
+
|
|
136
|
+
# Check if CLI is available
|
|
137
|
+
if ! command -v "$CLI_CMD" &> /dev/null; then
|
|
138
|
+
echo -e "${RED}Error: ${CLI_CMD} CLI not found in PATH${NC}"
|
|
139
|
+
echo "Please install ${VENDOR} CLI and ensure it's authenticated"
|
|
140
|
+
exit 1
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Create results directory
|
|
144
|
+
mkdir -p "$RESULTS_DIR"
|
|
145
|
+
|
|
146
|
+
# Generate unique result filename
|
|
147
|
+
TIMESTAMP=$(date +%Y%m%d-%H%M%S)
|
|
148
|
+
RESULT_FILE="${RESULTS_DIR}/${AGENT_TYPE}-${TIMESTAMP}.json"
|
|
149
|
+
OUTPUT_FILE="${RESULTS_DIR}/${AGENT_TYPE}-${TIMESTAMP}.md"
|
|
150
|
+
|
|
151
|
+
# If task is a file path, read its contents
|
|
152
|
+
if [[ -f "$TASK" ]]; then
|
|
153
|
+
TASK_CONTENT=$(cat "$TASK")
|
|
154
|
+
else
|
|
155
|
+
TASK_CONTENT="$TASK"
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
# Load agent-specific template if exists
|
|
159
|
+
TEMPLATE_FILE="${SCRIPT_DIR}/../templates/${AGENT_TYPE}-task.md"
|
|
160
|
+
if [[ -f "$TEMPLATE_FILE" ]]; then
|
|
161
|
+
TEMPLATE=$(cat "$TEMPLATE_FILE")
|
|
162
|
+
TASK_CONTENT="${TEMPLATE}
|
|
163
|
+
|
|
164
|
+
## Current Task
|
|
165
|
+
${TASK_CONTENT}"
|
|
166
|
+
fi
|
|
167
|
+
|
|
168
|
+
# Build command based on vendor
|
|
169
|
+
build_command() {
|
|
170
|
+
local cmd="$CLI_CMD"
|
|
171
|
+
|
|
172
|
+
case "$VENDOR" in
|
|
173
|
+
gemini)
|
|
174
|
+
cmd="$cmd $PROMPT_FLAG \"$TASK_CONTENT\""
|
|
175
|
+
[[ -n "$OUTPUT_FLAG" ]] && cmd="$cmd $OUTPUT_FLAG $OUTPUT_FORMAT"
|
|
176
|
+
[[ -n "$AUTO_FLAG" ]] && cmd="$cmd $AUTO_FLAG"
|
|
177
|
+
;;
|
|
178
|
+
claude)
|
|
179
|
+
cmd="$cmd $PROMPT_FLAG \"$TASK_CONTENT\""
|
|
180
|
+
[[ -n "$OUTPUT_FLAG" ]] && cmd="$cmd $OUTPUT_FLAG $OUTPUT_FORMAT"
|
|
181
|
+
[[ -n "$AUTO_FLAG" ]] && cmd="$cmd $AUTO_FLAG"
|
|
182
|
+
# Isolation flags
|
|
183
|
+
cmd="$cmd --setting-sources \"\""
|
|
184
|
+
;;
|
|
185
|
+
codex)
|
|
186
|
+
# Set isolation environment
|
|
187
|
+
export CODEX_HOME="/tmp/codex-subagent-$$"
|
|
188
|
+
mkdir -p "$CODEX_HOME"
|
|
189
|
+
cmd="$cmd $PROMPT_FLAG \"$TASK_CONTENT\""
|
|
190
|
+
[[ -n "$AUTO_FLAG" ]] && cmd="$cmd $AUTO_FLAG"
|
|
191
|
+
;;
|
|
192
|
+
qwen)
|
|
193
|
+
cmd="$cmd $PROMPT_FLAG \"$TASK_CONTENT\""
|
|
194
|
+
[[ -n "$OUTPUT_FLAG" ]] && cmd="$cmd $OUTPUT_FLAG $OUTPUT_FORMAT"
|
|
195
|
+
[[ -n "$AUTO_FLAG" ]] && cmd="$cmd $AUTO_FLAG"
|
|
196
|
+
;;
|
|
197
|
+
*)
|
|
198
|
+
# Generic fallback
|
|
199
|
+
cmd="$cmd $PROMPT_FLAG \"$TASK_CONTENT\""
|
|
200
|
+
;;
|
|
201
|
+
esac
|
|
202
|
+
|
|
203
|
+
echo "$cmd"
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
# Execute in workspace
|
|
207
|
+
echo -e "${BLUE}[SubAgent]${NC} Working directory: ${WORKSPACE}"
|
|
208
|
+
echo -e "${BLUE}[SubAgent]${NC} Task: ${TASK_CONTENT:0:100}..."
|
|
209
|
+
|
|
210
|
+
cd "$WORKSPACE"
|
|
211
|
+
|
|
212
|
+
# Build and execute command
|
|
213
|
+
CMD=$(build_command)
|
|
214
|
+
echo -e "${BLUE}[SubAgent]${NC} Executing: ${CLI_CMD} ..."
|
|
215
|
+
|
|
216
|
+
# Execute and capture output
|
|
217
|
+
set +e
|
|
218
|
+
if [[ "$OUTPUT_FORMAT" == "json" ]]; then
|
|
219
|
+
eval "$CMD" > "$RESULT_FILE" 2>&1
|
|
220
|
+
EXIT_CODE=$?
|
|
221
|
+
|
|
222
|
+
if [[ $EXIT_CODE -eq 0 ]] && [[ -s "$RESULT_FILE" ]]; then
|
|
223
|
+
# Extract response from JSON
|
|
224
|
+
if command -v jq &> /dev/null; then
|
|
225
|
+
jq -r "$RESPONSE_JQ" "$RESULT_FILE" > "$OUTPUT_FILE" 2>/dev/null || \
|
|
226
|
+
cat "$RESULT_FILE" > "$OUTPUT_FILE"
|
|
227
|
+
else
|
|
228
|
+
cat "$RESULT_FILE" > "$OUTPUT_FILE"
|
|
229
|
+
fi
|
|
230
|
+
echo -e "${GREEN}[SubAgent]${NC} Completed successfully"
|
|
231
|
+
echo -e "${GREEN}[SubAgent]${NC} Result: ${OUTPUT_FILE}"
|
|
232
|
+
else
|
|
233
|
+
echo -e "${RED}[SubAgent]${NC} Failed with exit code: ${EXIT_CODE}"
|
|
234
|
+
cat "$RESULT_FILE"
|
|
235
|
+
exit $EXIT_CODE
|
|
236
|
+
fi
|
|
237
|
+
else
|
|
238
|
+
eval "$CMD" > "$OUTPUT_FILE" 2>&1
|
|
239
|
+
EXIT_CODE=$?
|
|
240
|
+
|
|
241
|
+
if [[ $EXIT_CODE -eq 0 ]]; then
|
|
242
|
+
echo -e "${GREEN}[SubAgent]${NC} Completed successfully"
|
|
243
|
+
echo -e "${GREEN}[SubAgent]${NC} Result: ${OUTPUT_FILE}"
|
|
244
|
+
else
|
|
245
|
+
echo -e "${RED}[SubAgent]${NC} Failed with exit code: ${EXIT_CODE}"
|
|
246
|
+
exit $EXIT_CODE
|
|
247
|
+
fi
|
|
248
|
+
fi
|
|
249
|
+
set -e
|
|
250
|
+
|
|
251
|
+
# Output summary
|
|
252
|
+
echo ""
|
|
253
|
+
echo -e "${BLUE}========================================${NC}"
|
|
254
|
+
echo -e "${GREEN}SubAgent Execution Summary${NC}"
|
|
255
|
+
echo -e "${BLUE}========================================${NC}"
|
|
256
|
+
echo -e "Agent Type: ${YELLOW}${AGENT_TYPE}${NC}"
|
|
257
|
+
echo -e "Vendor: ${GREEN}${VENDOR}${NC}"
|
|
258
|
+
echo -e "Workspace: ${WORKSPACE}"
|
|
259
|
+
echo -e "Result: ${OUTPUT_FILE}"
|
|
260
|
+
echo -e "${BLUE}========================================${NC}"
|
|
261
|
+
|
|
262
|
+
# Return the output file path
|
|
263
|
+
echo "$OUTPUT_FILE"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Backend SubAgent Task
|
|
2
|
+
|
|
3
|
+
You are a Backend specialist. Focus only on the task below.
|
|
4
|
+
|
|
5
|
+
## Guidelines
|
|
6
|
+
- Use FastAPI with async/await
|
|
7
|
+
- SQLAlchemy for database operations
|
|
8
|
+
- Pydantic for validation
|
|
9
|
+
- JWT for authentication
|
|
10
|
+
- Follow REST conventions
|
|
11
|
+
- Include error handling
|
|
12
|
+
- Write tests for new code
|
|
13
|
+
|
|
14
|
+
## Output Requirements
|
|
15
|
+
- Implement the requested functionality
|
|
16
|
+
- Create/modify necessary files
|
|
17
|
+
- Add appropriate tests
|
|
18
|
+
- Document API endpoints if created
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Debug SubAgent Task
|
|
2
|
+
|
|
3
|
+
You are a Debug specialist. Focus only on fixing the bug below.
|
|
4
|
+
|
|
5
|
+
## Approach
|
|
6
|
+
1. Reproduce the issue
|
|
7
|
+
2. Identify root cause
|
|
8
|
+
3. Implement fix
|
|
9
|
+
4. Add regression test
|
|
10
|
+
5. Document the fix
|
|
11
|
+
|
|
12
|
+
## Output Requirements
|
|
13
|
+
- Explain the root cause
|
|
14
|
+
- Show before/after code
|
|
15
|
+
- Include regression test
|
|
16
|
+
- List related patterns to check
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Frontend SubAgent Task
|
|
2
|
+
|
|
3
|
+
You are a Frontend specialist. Focus only on the task below.
|
|
4
|
+
|
|
5
|
+
## Guidelines
|
|
6
|
+
- React with TypeScript
|
|
7
|
+
- TailwindCSS for styling
|
|
8
|
+
- React Query for data fetching
|
|
9
|
+
- Proper loading/error states
|
|
10
|
+
- Accessible components (WCAG 2.1 AA)
|
|
11
|
+
- Mobile-responsive design
|
|
12
|
+
|
|
13
|
+
## Output Requirements
|
|
14
|
+
- Implement the requested UI/feature
|
|
15
|
+
- Create/modify necessary components
|
|
16
|
+
- Add component tests if appropriate
|
|
17
|
+
- Ensure responsive behavior
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Mobile SubAgent Task
|
|
2
|
+
|
|
3
|
+
You are a Mobile specialist. Focus only on the task below.
|
|
4
|
+
|
|
5
|
+
## Guidelines
|
|
6
|
+
- Flutter with Dart
|
|
7
|
+
- Clean Architecture (presentation/domain/data)
|
|
8
|
+
- Riverpod for state management
|
|
9
|
+
- Platform-aware UI components
|
|
10
|
+
- Proper navigation handling
|
|
11
|
+
- Offline-first when applicable
|
|
12
|
+
|
|
13
|
+
## Output Requirements
|
|
14
|
+
- Implement the requested screen/feature
|
|
15
|
+
- Create/modify necessary files
|
|
16
|
+
- Handle both iOS and Android
|
|
17
|
+
- Test on multiple screen sizes
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# QA SubAgent Task
|
|
2
|
+
|
|
3
|
+
You are a QA specialist. Focus only on the review below.
|
|
4
|
+
|
|
5
|
+
## Review Checklist
|
|
6
|
+
- Security (OWASP Top 10)
|
|
7
|
+
- Performance (bundle size, API latency)
|
|
8
|
+
- Accessibility (WCAG 2.1 AA)
|
|
9
|
+
- Code quality (complexity, duplication)
|
|
10
|
+
- Test coverage
|
|
11
|
+
|
|
12
|
+
## Output Requirements
|
|
13
|
+
- List issues found with severity (CRITICAL/HIGH/MEDIUM/LOW)
|
|
14
|
+
- Provide specific file:line references
|
|
15
|
+
- Suggest fixes for each issue
|
|
16
|
+
- Prioritize actionable feedback
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Example parallel tasks file
|
|
2
|
+
# Usage: ./parallel-run.sh tasks-example.yaml
|
|
3
|
+
|
|
4
|
+
tasks:
|
|
5
|
+
- agent: backend
|
|
6
|
+
task: "Implement JWT authentication with register and login endpoints"
|
|
7
|
+
workspace: ./backend
|
|
8
|
+
|
|
9
|
+
- agent: frontend
|
|
10
|
+
task: "Create login and registration forms with validation"
|
|
11
|
+
workspace: ./frontend
|
|
12
|
+
|
|
13
|
+
- agent: mobile
|
|
14
|
+
task: "Build authentication screens for iOS and Android"
|
|
15
|
+
workspace: ./mobile
|