1+ #! /bin/bash
2+
3+ # AgentEx Tutorial Launcher
4+ # This script helps you easily launch and test all tutorials in the repository
5+ #
6+ # Usage:
7+ # ./launch-tutorials.sh # Show interactive menu
8+ # ./launch-tutorials.sh 1 # Launch tutorial #1 directly
9+ # ./launch-tutorials.sh a # Launch all tutorials with confirmations
10+ # ./launch-tutorials.sh c # Clean up orphaned tutorial processes
11+ #
12+ # Note: Excludes 90_multi_agent_non_temporal (use its own start-agents.sh)
13+
14+ # Simple cleanup function for orphaned processes
15+ cleanup () {
16+ # Kill any remaining agentex or uvicorn processes from tutorials
17+ local agentex_pids=$( pgrep -f " agentex agents run.*tutorials" 2> /dev/null || true)
18+ if [[ -n " $agentex_pids " ]]; then
19+ echo " $agentex_pids " | xargs kill -TERM 2> /dev/null || true
20+ sleep 1
21+ echo " $agentex_pids " | xargs kill -KILL 2> /dev/null || true
22+ fi
23+
24+ local uvicorn_pids=$( pgrep -f " uvicorn.*project\." 2> /dev/null || true)
25+ if [[ -n " $uvicorn_pids " ]]; then
26+ echo " $uvicorn_pids " | xargs kill -TERM 2> /dev/null || true
27+ sleep 1
28+ echo " $uvicorn_pids " | xargs kill -KILL 2> /dev/null || true
29+ fi
30+ }
31+
32+ # Color codes for output
33+ RED=' \033[0;31m'
34+ GREEN=' \033[0;32m'
35+ YELLOW=' \033[1;33m'
36+ BLUE=' \033[0;34m'
37+ NC=' \033[0m' # No Color
38+
39+ # Tutorial definitions
40+ declare -a TUTORIALS=(
41+ " tutorials/00_sync/000_hello_acp|Basic Hello ACP (Sync)"
42+ " tutorials/00_sync/010_multiturn|Multi-turn Chat (Sync)"
43+ " tutorials/00_sync/020_streaming|Streaming Response (Sync)"
44+ " tutorials/10_agentic/00_base/000_hello_acp|Basic Hello ACP (Agentic)"
45+ " tutorials/10_agentic/00_base/010_multiturn|Multi-turn Chat (Agentic)"
46+ " tutorials/10_agentic/00_base/020_streaming|Streaming Response (Agentic)"
47+ " tutorials/10_agentic/00_base/030_tracing|Tracing Example (Agentic)"
48+ " tutorials/10_agentic/00_base/040_other_sdks|Other SDKs Integration (Agentic)"
49+ " tutorials/10_agentic/00_base/080_batch_events|Batch Events (Agentic)"
50+ " tutorials/10_agentic/10_temporal/000_hello_acp|Basic Hello ACP (Temporal)"
51+ " tutorials/10_agentic/10_temporal/010_agent_chat|Agent Chat (Temporal)"
52+ " tutorials/10_agentic/10_temporal/020_state_machine|State Machine (Temporal)"
53+ )
54+
55+ # Function to print colored output
56+ print_colored () {
57+ local color=$1
58+ local message=$2
59+ # Check if terminal supports colors
60+ if [[ -t 1 ]] && command -v tput > /dev/null 2>&1 ; then
61+ printf " ${color} %s${NC} \n" " $message "
62+ else
63+ printf " %s\n" " $message "
64+ fi
65+ }
66+
67+ # Function to display the menu
68+ show_menu () {
69+ print_colored $BLUE " ╔════════════════════════════════════════════════════════════════╗"
70+ print_colored $BLUE " ║ AgentEx Tutorial Launcher ║"
71+ print_colored $BLUE " ╚════════════════════════════════════════════════════════════════╝"
72+ echo " "
73+ print_colored $YELLOW " Available tutorials:"
74+ echo " "
75+
76+ local index=1
77+ for tutorial in " ${TUTORIALS[@]} " ; do
78+ IFS=' |' read -r path description <<< " $tutorial"
79+ if [[ -t 1 ]] && command -v tput > /dev/null 2>&1 ; then
80+ printf " ${GREEN} %2d.${NC} %s\n" $index " $description "
81+ else
82+ printf " %2d. %s\n" $index " $description "
83+ fi
84+ index=$(( index + 1 ))
85+ done
86+
87+ echo " "
88+ print_colored $BLUE " Other options:"
89+ print_colored $GREEN " a. Run all tutorials sequentially (with confirmations)"
90+ print_colored $GREEN " c. Clean up any orphaned tutorial processes"
91+ print_colored $GREEN " q. Quit"
92+ echo " "
93+ print_colored $YELLOW " 📌 Note: The multi-agent system tutorial (tutorials/10_agentic/90_multi_agent_non_temporal) is excluded"
94+ print_colored $YELLOW " as it has a special launch process. Use its own start-agents.sh script."
95+ echo " "
96+ }
97+
98+ # Function to run a specific tutorial
99+ run_tutorial () {
100+ local tutorial_index=$1
101+ local tutorial_info=" ${TUTORIALS[$((tutorial_index - 1))]} "
102+ IFS=' |' read -r path description <<< " $tutorial_info"
103+
104+ local manifest_path=" ${path} /manifest.yaml"
105+
106+ print_colored $BLUE " ╔════════════════════════════════════════════════════════════════╗"
107+ printf " ║ Running: %-54s ║\n" " $description "
108+ print_colored $BLUE " ╚════════════════════════════════════════════════════════════════╝"
109+
110+ if [[ ! -f " $manifest_path " ]]; then
111+ print_colored $RED " ❌ Error: Manifest file not found at $manifest_path "
112+ return 1
113+ fi
114+
115+ print_colored $YELLOW " 📂 Tutorial path: $path "
116+ print_colored $YELLOW " 📄 Manifest: $manifest_path "
117+ echo " "
118+ print_colored $GREEN " 🚀 Executing: cd .. && uv run agentex agents run --manifest examples/$manifest_path "
119+ print_colored $YELLOW " 💡 Press Ctrl+C to stop the tutorial"
120+ echo " "
121+
122+ # Run the tutorial directly (need to go to parent dir where uv project is)
123+ (cd .. && uv run agentex agents run --manifest " examples/$manifest_path " )
124+
125+ local exit_code=$?
126+ if [[ $exit_code -eq 0 ]]; then
127+ print_colored $GREEN " ✅ Tutorial completed successfully!"
128+ elif [[ $exit_code -eq 130 ]]; then
129+ print_colored $YELLOW " 🛑 Tutorial was interrupted by user"
130+ else
131+ print_colored $RED " ❌ Tutorial failed with exit code: $exit_code "
132+ fi
133+
134+ return $exit_code
135+ }
136+
137+ # Function to run all tutorials
138+ run_all_tutorials () {
139+ print_colored $BLUE " 🎯 Running all tutorials sequentially..."
140+ echo " "
141+
142+ local success_count=0
143+ local total_count=${# TUTORIALS[@]}
144+
145+ for i in $( seq 1 $total_count ) ; do
146+ local tutorial_info=" ${TUTORIALS[$((i - 1))]} "
147+ IFS=' |' read -r path description <<< " $tutorial_info"
148+
149+ print_colored $YELLOW " ┌─ Tutorial $i /$total_count : $description "
150+ echo " "
151+
152+ # Ask for confirmation
153+ while true ; do
154+ print_colored $BLUE " Run this tutorial? (y/n/q to quit): "
155+ read -r response
156+ case $response in
157+ [Yy]* )
158+ if run_tutorial $i ; then
159+ success_count=$(( success_count + 1 ))
160+ fi
161+ break
162+ ;;
163+ [Nn]* )
164+ print_colored $YELLOW " ⏭️ Skipping tutorial $i "
165+ break
166+ ;;
167+ [Qq]* )
168+ print_colored $YELLOW " 🛑 Stopping tutorial run"
169+ echo " "
170+ print_colored $BLUE " 📊 Summary: $success_count /$(( i- 1 )) tutorials completed successfully"
171+ return 0
172+ ;;
173+ * )
174+ print_colored $RED " Please answer y, n, or q."
175+ ;;
176+ esac
177+ done
178+
179+ if [[ $i -lt $total_count ]]; then
180+ echo " "
181+ print_colored $BLUE " ────────────────────────────────────────────────────────────────"
182+ echo " "
183+ fi
184+ done
185+
186+ echo " "
187+ print_colored $BLUE " 🎉 All tutorials completed!"
188+ print_colored $BLUE " 📊 Summary: $success_count /$total_count tutorials completed successfully"
189+ }
190+
191+ # Function to manually clean up tutorial processes
192+ manual_cleanup () {
193+ print_colored $BLUE " 🧹 Manual cleanup of tutorial processes..."
194+ echo " "
195+
196+ # Check for running tutorial processes
197+ local found_processes=false
198+
199+ # Check for agentex processes
200+ local agentex_pids=$( pgrep -f " agentex agents run.*tutorials" 2> /dev/null || true)
201+ if [[ -n " $agentex_pids " ]]; then
202+ found_processes=true
203+ print_colored $YELLOW " 🔍 Found agentex tutorial processes:"
204+ ps -p $agentex_pids -o pid,command 2> /dev/null || true
205+ echo " "
206+ fi
207+
208+ # Check for uvicorn processes
209+ local uvicorn_pids=$( pgrep -f " uvicorn.*project\." 2> /dev/null || true)
210+ if [[ -n " $uvicorn_pids " ]]; then
211+ found_processes=true
212+ print_colored $YELLOW " 🔍 Found uvicorn tutorial processes:"
213+ ps -p $uvicorn_pids -o pid,command 2> /dev/null || true
214+ echo " "
215+ fi
216+
217+ # Check for occupied ports
218+ print_colored $YELLOW " 🔍 Checking common tutorial ports (8000-8003)..."
219+ local port_check=$( lsof -i :8000 -i :8001 -i :8002 -i :8003 2> /dev/null || true)
220+ if [[ -n " $port_check " ]]; then
221+ found_processes=true
222+ echo " $port_check "
223+ echo " "
224+ fi
225+
226+ if [[ " $found_processes " == " false" ]]; then
227+ print_colored $GREEN " ✅ No tutorial processes found - system is clean!"
228+ return 0
229+ fi
230+
231+ # Ask for confirmation before cleaning
232+ while true ; do
233+ print_colored $BLUE " Kill these processes? (y/n): "
234+ read -r response
235+ case $response in
236+ [Yy]* )
237+ print_colored $YELLOW " 🧹 Cleaning up..."
238+ cleanup
239+ print_colored $GREEN " ✅ Manual cleanup completed!"
240+ break
241+ ;;
242+ [Nn]* )
243+ print_colored $YELLOW " ⏭️ Cleanup cancelled"
244+ break
245+ ;;
246+ * )
247+ print_colored $RED " Please answer y or n."
248+ ;;
249+ esac
250+ done
251+ }
252+
253+ # Function to validate tutorial number
254+ validate_tutorial_number () {
255+ local num=$1
256+ if [[ ! " $num " =~ ^[0-9]+$ ]] || [[ $num -lt 1 ]] || [[ $num -gt ${# TUTORIALS[@]} ]]; then
257+ return 1
258+ fi
259+ return 0
260+ }
261+
262+ # Main script logic
263+ main () {
264+ # Check if we're in the right directory
265+ if [[ ! -f " ../pyproject.toml" ]] || [[ ! -d " tutorials" ]]; then
266+ print_colored $RED " ❌ Error: This script must be run from the examples directory"
267+ print_colored $YELLOW " 💡 Current directory: $( pwd) "
268+ print_colored $YELLOW " 💡 Expected files: ../pyproject.toml, tutorials/"
269+ exit 1
270+ fi
271+
272+ # If a tutorial number is provided as argument
273+ if [[ $# -eq 1 ]]; then
274+ local tutorial_num=$1
275+
276+ if [[ " $tutorial_num " == " a" ]] || [[ " $tutorial_num " == " all" ]]; then
277+ run_all_tutorials
278+ exit 0
279+ elif [[ " $tutorial_num " == " c" ]] || [[ " $tutorial_num " == " cleanup" ]]; then
280+ manual_cleanup
281+ exit 0
282+ fi
283+
284+ if validate_tutorial_number " $tutorial_num " ; then
285+ run_tutorial " $tutorial_num "
286+ exit $?
287+ else
288+ print_colored $RED " ❌ Error: Invalid tutorial number '$tutorial_num '"
289+ print_colored $YELLOW " 💡 Valid range: 1-${# TUTORIALS[@]} "
290+ exit 1
291+ fi
292+ fi
293+
294+ # Interactive mode
295+ while true ; do
296+ show_menu
297+ print_colored $BLUE " Enter your choice (1-${# TUTORIALS[@]} , a, c, or q): "
298+ read -r choice
299+
300+ case $choice in
301+ [Qq]* )
302+ print_colored $YELLOW " 👋 Goodbye!"
303+ exit 0
304+ ;;
305+ [Aa]* )
306+ echo " "
307+ run_all_tutorials
308+ echo " "
309+ ;;
310+ [Cc]* )
311+ echo " "
312+ manual_cleanup
313+ echo " "
314+ print_colored $BLUE " Press Enter to continue..."
315+ read -r
316+ ;;
317+ * )
318+ if validate_tutorial_number " $choice " ; then
319+ echo " "
320+ run_tutorial " $choice "
321+ echo " "
322+ print_colored $BLUE " Press Enter to continue..."
323+ read -r
324+ else
325+ print_colored $RED " ❌ Invalid choice: '$choice '"
326+ print_colored $YELLOW " 💡 Please enter a number between 1 and ${# TUTORIALS[@]} , 'a' for all, 'c' for cleanup, or 'q' to quit"
327+ fi
328+ ;;
329+ esac
330+
331+ echo " "
332+ done
333+ }
334+
335+ # Run the main function
336+ main " $@ "
0 commit comments