view 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 source

#!/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"