Mercurial
diff infinite_canvas/run_orchestration_dev.sh @ 280:49e9e591c9bb
Add persistent dictation, prewarmed WebRTC speech input, Copilot SDK routing, animated conversation lifecycle controls, parking, and architecture coverage.
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 18 Aug 2026 19:14:53 -0700 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/infinite_canvas/run_orchestration_dev.sh Tue Aug 18 19:14:53 2026 -0700 @@ -0,0 +1,179 @@ +#!/usr/bin/env bash +set -euo pipefail + +RUNFILES_ROOT="${RUNFILES_DIR:-$0.runfiles}" +export RUNFILES_DIR="$RUNFILES_ROOT" + +find_runfile() { + local pattern="$1" + local path + path="$(find -L "$RUNFILES_ROOT" -path "$pattern" -print -quit)" + if [[ -z "$path" ]]; then + echo "Could not locate orchestration runtime file: $pattern" >&2 + exit 1 + fi + realpath "$path" +} + +find_config() { + local candidate + for candidate in \ + "${BUILD_WORKSPACE_DIRECTORY:-}/mrjunejune/.config" \ + "$PWD/mrjunejune/.config" \ + "${HOME:-}/.config/mrjunejune/.config"; do + [[ "$candidate" != /mrjunejune/.config ]] || continue + [[ "$candidate" != /.config/mrjunejune/.config ]] || continue + if [[ -f "$candidate" ]]; then + realpath "$candidate" + return 0 + fi + done + return 1 +} + +load_config() { + local config_path="$1" + local line key value + while IFS= read -r line || [[ -n "$line" ]]; do + line="${line%$'\r'}" + [[ "$line" =~ ^[[:space:]]*$ ]] && continue + [[ "$line" =~ ^[[:space:]]*# ]] && continue + if [[ "$line" != *=* ]]; then + echo "Invalid config line in $config_path" >&2 + exit 1 + fi + key="${line%%=*}" + value="${line#*=}" + key="${key#"${key%%[![:space:]]*}"}" + key="${key%"${key##*[![:space:]]}"}" + case "$key" in + LITELLM_MASTER_KEY|LITELLM_HOST|LITELLM_PORT|LITELLM_MODEL|\ + LITELLM_WIRE_API|GITHUB_COPILOT_TOKEN_DIR|\ + MRJUNEJUNE_INFERENCE_STATE|COPILOT_SESSION_IDLE_SECONDS|\ + COPILOT_MAX_SESSIONS) + printf -v "$key" '%s' "$value" + ;; + esac + done < "$config_path" +} + +dictation="$(find_runfile '*/dictation/server')" +dictation_bin="$(find_runfile '*/dictation/dictation_bin')" +canvas="$(find_runfile '*/infinite_canvas/dev_linux')" +sidecar_launcher="$(find_runfile '*/mrjunejune/inference_sidecar_launcher.sh')" +sidecar_zip="$(find_runfile '*/mrjunejune/inference/copilot_sidecar.zip')" +litellm_zip="$(find_runfile '*/mrjunejune/inference/litellm_proxy.zip')" +litellm_config="$(find_runfile '*/mrjunejune/inference/litellm_config.yaml')" +copilot_cli="$(find_runfile '*copilot_cli_linux_x86_64/copilot')" +python="$(find_runfile '*python_3_11_x86_64-unknown-linux-gnu/bin/python3')" + +config_file="$(find_config || true)" +if [[ -z "$config_file" ]]; then + echo "Missing mrjunejune/.config." >&2 + echo "Copy mrjunejune/.config.development to mrjunejune/.config." >&2 + exit 1 +fi +load_config "$config_file" + +state_root="${MRJUNEJUNE_INFERENCE_STATE:-${XDG_STATE_HOME:-$HOME/.local/state}/mrjunejune/inference}" +token_dir="${GITHUB_COPILOT_TOKEN_DIR:-$state_root/litellm-copilot}" +cache_root="$state_root/cache" +mkdir -p "$state_root/copilot" "$token_dir" "$cache_root" +chmod 700 "$state_root" "$state_root/copilot" "$token_dir" "$cache_root" + +if [[ ! -s "$token_dir/access-token" ]]; then + echo "GitHub Copilot is not authenticated." >&2 + echo "Run: bazel run //mrjunejune:run_inference_stack -- --authenticate" >&2 + exit 1 +fi + +if [[ -z "${LITELLM_MASTER_KEY:-}" ]]; then + umask 077 + LITELLM_MASTER_KEY="sk-$("$python" -c 'import secrets; print(secrets.token_hex(24))')" +fi + +litellm_host="${LITELLM_HOST:-127.0.0.1}" +litellm_port="${LITELLM_PORT:-4000}" +service_pids=() + +cleanup() { + local status=$? + trap - EXIT INT TERM + for pid in "${service_pids[@]}"; do + kill -- "-$pid" 2>/dev/null || kill "$pid" 2>/dev/null || true + done + for pid in "${service_pids[@]}"; do + wait "$pid" 2>/dev/null || true + done + exit "$status" +} + +trap cleanup EXIT +trap 'exit 130' INT +trap 'exit 143' TERM + +export GITHUB_COPILOT_TOKEN_DIR="$token_dir" +export XDG_CACHE_HOME="$cache_root" +export DICTATION_MODEL_DIR="${DICTATION_MODEL_DIR:-$HOME/.cache/zenbu/faster-whisper-small}" +export LITELLM_MASTER_KEY +setsid "$python" "$litellm_zip" \ + --config "$litellm_config" \ + --host "$litellm_host" \ + --port "$litellm_port" & +service_pids+=("$!") + +setsid "$dictation" "$dictation_bin" server & +service_pids+=("$!") + +for _ in {1..150}; do + if curl --fail --silent \ + --connect-timeout 1 \ + --max-time 2 \ + "http://${litellm_host}:${litellm_port}/health/readiness" \ + >/dev/null; then + break + fi + if ! kill -0 "${service_pids[0]}" 2>/dev/null; then + echo "Copilot LiteLLM gateway exited before becoming ready." >&2 + exit 1 + fi + sleep 0.1 +done +if ! curl --fail --silent \ + --connect-timeout 1 \ + --max-time 2 \ + "http://${litellm_host}:${litellm_port}/health/readiness" \ + >/dev/null; then + echo "Copilot LiteLLM readiness timed out." >&2 + exit 1 +fi + +for _ in {1..120}; do + if curl --silent --fail --output /dev/null http://127.0.0.1:8090/; then + break + fi + if ! kill -0 "${service_pids[1]}" 2>/dev/null; then + echo "The dictation service exited before becoming ready." >&2 + exit 1 + fi + sleep 0.25 +done +if ! curl --silent --fail --output /dev/null http://127.0.0.1:8090/; then + echo "Timed out waiting for dictation at http://127.0.0.1:8090." >&2 + exit 1 +fi + +export MRJUNEJUNE_PYTHON_PATH="$python" +export MRJUNEJUNE_SIDECAR_ZIP="$sidecar_zip" +export COPILOT_SIDECAR_HOME="$state_root/copilot" +export LITELLM_BASE_URL="http://${litellm_host}:${litellm_port}/v1" +export LITELLM_MODEL="${LITELLM_MODEL:-jrpg-copilot}" +export LITELLM_WIRE_API="${LITELLM_WIRE_API:-completions}" +export LITELLM_API_KEY="$LITELLM_MASTER_KEY" +export INFINITE_CANVAS_COPILOT_SIDECAR_PATH="$sidecar_launcher" +export INFINITE_CANVAS_COPILOT_CLI_PATH="$copilot_cli" + +echo "Copilot orchestration is ready. Starting Infinite Canvas." +canvas_status=0 +"$canvas" "$@" || canvas_status=$? +exit "$canvas_status"