Spaces:
				
			
			
	
			
			
					
		Running
		
	
	
	
			
			
	
	
	
	
		
		
					
		Running
		
	| set -eu | |
| # Default to voice_agent_webrtc_langgraph if EXAMPLE_NAME is not set | |
| EXAMPLE_NAME="${EXAMPLE_NAME:-voice_agent_webrtc_langgraph}" | |
| EXAMPLE_PATH="/app/examples/${EXAMPLE_NAME}" | |
| # Optionally load a local .env next to this example if present | |
| if [ -f "${EXAMPLE_PATH}/.env" ]; then | |
| # shellcheck disable=SC1091 | |
| set -a | |
| . "${EXAMPLE_PATH}/.env" | |
| set +a | |
| fi | |
| # If a remote prompt URL is provided, download it and export ZERO_SHOT_AUDIO_PROMPT | |
| if [ -n "${ZERO_SHOT_AUDIO_PROMPT_URL:-}" ]; then | |
| case "$ZERO_SHOT_AUDIO_PROMPT_URL" in | |
| *"github.com"*"/blob"*) | |
| ZERO_SHOT_AUDIO_PROMPT_URL="${ZERO_SHOT_AUDIO_PROMPT_URL}?raw=1" | |
| ;; | |
| esac | |
| PROMPT_TARGET="${ZERO_SHOT_AUDIO_PROMPT:-${EXAMPLE_PATH}/audio_prompt.wav}" | |
| mkdir -p "$(dirname "$PROMPT_TARGET")" | |
| if [ ! -f "$PROMPT_TARGET" ]; then | |
| echo "Downloading ZERO_SHOT_AUDIO_PROMPT from $ZERO_SHOT_AUDIO_PROMPT_URL" | |
| if ! curl -fsSL "$ZERO_SHOT_AUDIO_PROMPT_URL" -o "$PROMPT_TARGET"; then | |
| echo "Failed to download audio prompt from URL: $ZERO_SHOT_AUDIO_PROMPT_URL" >&2 | |
| fi | |
| fi | |
| export ZERO_SHOT_AUDIO_PROMPT="$PROMPT_TARGET" | |
| fi | |
| # All dependencies and langgraph CLI are installed at build time | |
| # Start langgraph dev from within the internal agents directory (background) | |
| LANGGRAPH_DIR="${EXAMPLE_PATH}/agents" | |
| LANGGRAPH_PID="" | |
| if [ -d "$LANGGRAPH_DIR" ]; then | |
| LG_HOST="${LANGGRAPH_HOST:-0.0.0.0}" | |
| LANGGRAPH_PORT="${LANGGRAPH_PORT:-2024}" | |
| sh -c "cd \"$LANGGRAPH_DIR\" && exec uv run langgraph dev --no-browser --host \"$LG_HOST\" --port \"$LANGGRAPH_PORT\"" & | |
| LANGGRAPH_PID=$! | |
| fi | |
| # Run the voice agent app in background | |
| cd "${EXAMPLE_PATH}" | |
| uv run pipeline.py & | |
| PIPELINE_PID=$! | |
| # Wait until the pipeline HTTP endpoint is ready | |
| ATTEMPTS=0 | |
| MAX_ATTEMPTS=30 | |
| until curl -fsS http://127.0.0.1:7860/get_prompt >/dev/null 2>&1; do | |
| ATTEMPTS=$((ATTEMPTS + 1)) | |
| if [ "$ATTEMPTS" -ge "$MAX_ATTEMPTS" ]; then | |
| echo "Pipeline failed to become ready in time" >&2 | |
| wait "$PIPELINE_PID" 2>/dev/null || true | |
| exit 1 | |
| fi | |
| sleep 1 | |
| done | |
| # Ensure children are terminated when this script exits | |
| cleanup() { | |
| for p in $PIPELINE_PID $LANGGRAPH_PID; do | |
| if [ -n "$p" ] && kill -0 "$p" 2>/dev/null; then | |
| kill "$p" 2>/dev/null || true | |
| fi | |
| done | |
| } | |
| trap cleanup EXIT INT TERM | |
| # Monitor background jobs and exit if any of them exits | |
| while :; do | |
| for p in $PIPELINE_PID $LANGGRAPH_PID; do | |
| [ -z "$p" ] && continue | |
| if ! kill -0 "$p" 2>/dev/null; then | |
| wait "$p" 2>/dev/null || true | |
| exit 1 | |
| fi | |
| done | |
| sleep 1 | |
| done | |

