comparison mrjunejune/inference_stack.sh @ 265:056790c4fb0d

add role-aware Epi assistant prompts Add verified June knowledge, guest/member/admin Copilot profiles, profile-isolated session recovery, animated Epi greetings, and a single authoritative runtime config workflow for inference. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 10:50:30 -0700
parents 04fee26ecce0
children 13d61401c57d
comparison
equal deleted inserted replaced
264:04fee26ecce0 265:056790c4fb0d
17 17
18 mode=live 18 mode=live
19 if [[ "${1:-}" == "--mock" ]]; then 19 if [[ "${1:-}" == "--mock" ]]; then
20 mode=mock 20 mode=mock
21 shift 21 shift
22 elif [[ "${1:-}" == "--authenticate" ]]; then
23 mode=authenticate
24 shift
25 elif [[ "${1:-}" == "--check-config" ]]; then
26 mode=check-config
27 shift
22 fi 28 fi
23 if (( $# != 0 )); then 29 if (( $# != 0 )); then
24 echo "Usage: bazel run //mrjunejune:run_inference_stack -- [--mock]" >&2 30 echo "Usage: bazel run //mrjunejune:run_inference_stack -- [--mock|--authenticate|--check-config]" >&2
25 exit 2 31 exit 2
26 fi 32 fi
33
34 find_config() {
35 local candidate
36 for candidate in \
37 "${BUILD_WORKSPACE_DIRECTORY:-}/mrjunejune/.config" \
38 "$PWD/mrjunejune/.config" \
39 "/etc/mrjunejune/.config" \
40 "${HOME:-}/.config/mrjunejune/.config"; do
41 [[ "$candidate" != /mrjunejune/.config ]] || continue
42 [[ "$candidate" != /.config/mrjunejune/.config ]] || continue
43 if [[ -f "$candidate" ]]; then
44 realpath "$candidate"
45 return 0
46 fi
47 done
48 return 1
49 }
50
51 is_supported_config_key() {
52 case "$1" in
53 UPLOAD_AUTH_TOKEN|S3_REGION|S3_BUCKET|S3_URL_EXPIRES|S3_CLOUDFRONT_URL|\
54 DB_PATH|MRJUNEJUNE_DB_PATH|AWS_MRJUNEJUNE_ACCESS_KEY|\
55 AWS_MRJUNEJUNE_SECRET_ACCESS_KEY|AUTH_COOKIE_SECRET|\
56 AUTH_BOOTSTRAP_USERNAME|AUTH_BOOTSTRAP_PASSWORD_HASH|AUTH_TRUSTED_PROXY|\
57 AUTH_SESSION_IDLE_TTL|AUTH_SESSION_ABS_TTL|AUTH_GUEST_TTL|\
58 AUTH_DEV_INSECURE_COOKIE|AUTH_GUEST_DAILY_TURNS|\
59 AUTH_GUEST_DAILY_OUTPUT_TOKENS|AUTH_GUEST_REQUEST_OUTPUT_TOKENS|\
60 SERVER_HOST|MRJUNEJUNE_PORT|MRJUNEJUNE_ALLOW_GUEST_INFERENCE|\
61 MRJUNEJUNE_INFERENCE_STATE|MRJUNEJUNE_MOCK_STATE|\
62 GITHUB_COPILOT_TOKEN_DIR|LITELLM_MASTER_KEY|LITELLM_HOST|LITELLM_PORT|\
63 LITELLM_MODEL|LITELLM_WIRE_API|COPILOT_SESSION_IDLE_SECONDS|\
64 COPILOT_MAX_SESSIONS)
65 return 0
66 ;;
67 esac
68 return 1
69 }
70
71 load_config() {
72 local config_path="$1"
73 local line key value
74 while IFS= read -r line || [[ -n "$line" ]]; do
75 line="${line%$'\r'}"
76 [[ "$line" =~ ^[[:space:]]*$ ]] && continue
77 [[ "$line" =~ ^[[:space:]]*# ]] && continue
78 if [[ "$line" != *=* ]]; then
79 echo "Invalid config line in $config_path" >&2
80 exit 1
81 fi
82 key="${line%%=*}"
83 value="${line#*=}"
84 key="${key#"${key%%[![:space:]]*}"}"
85 key="${key%"${key##*[![:space:]]}"}"
86 if ! [[ "$key" =~ ^[A-Z][A-Z0-9_]*$ ]] ||
87 ! is_supported_config_key "$key"; then
88 echo "Unsupported config key in $config_path: $key" >&2
89 exit 1
90 fi
91 printf -v "$key" '%s' "$value"
92 export -n "$key" 2>/dev/null || true
93 done < "$config_path"
94 }
95
96 config_file="$(find_config || true)"
97 if [[ -z "$config_file" ]]; then
98 echo "Missing mrjunejune/.config." >&2
99 echo "Copy mrjunejune/.config.development to mrjunejune/.config." >&2
100 exit 1
101 fi
102 load_config "$config_file"
103 : "${MRJUNEJUNE_ALLOW_GUEST_INFERENCE:?MRJUNEJUNE_ALLOW_GUEST_INFERENCE must be set in $config_file}"
27 104
28 litellm_host="${LITELLM_HOST:-127.0.0.1}" 105 litellm_host="${LITELLM_HOST:-127.0.0.1}"
29 litellm_port="${LITELLM_PORT:-4000}" 106 litellm_port="${LITELLM_PORT:-4000}"
30 default_state_root="${XDG_STATE_HOME:-$HOME/.local/state}/mrjunejune/inference" 107 default_state_root="${XDG_STATE_HOME:-$HOME/.local/state}/mrjunejune/inference"
31 state_root="${MRJUNEJUNE_INFERENCE_STATE:-$default_state_root}" 108 state_root="${MRJUNEJUNE_INFERENCE_STATE:-$default_state_root}"
32 litellm_pid= 109 litellm_pid=
33 server_pid= 110 server_pid=
111
112 if [[ "$mode" == "check-config" ]]; then
113 printf 'config=%s\n' "$config_file"
114 if [[ -n "${LITELLM_MASTER_KEY:-}" ]]; then
115 echo 'litellm_master_key=set'
116 else
117 echo 'litellm_master_key=missing (generated on first local live run)'
118 fi
119 printf 'copilot_token_dir=%s\n' \
120 "${GITHUB_COPILOT_TOKEN_DIR:-$state_root/litellm-copilot}"
121 printf 'guest_inference=%s\n' \
122 "${MRJUNEJUNE_ALLOW_GUEST_INFERENCE:-false}"
123 exit 0
124 fi
125
126 if [[ "$mode" == "authenticate" ]]; then
127 token_dir="${GITHUB_COPILOT_TOKEN_DIR:-$state_root/litellm-copilot}"
128 mkdir -p "$token_dir"
129 chmod 700 "$token_dir"
130 exec "$python" "$litellm_zip" --authenticate --token-dir "$token_dir"
131 fi
34 132
35 cleanup() { 133 cleanup() {
36 for pid in "$server_pid" "$litellm_pid"; do 134 for pid in "$server_pid" "$litellm_pid"; do
37 if [[ -n "$pid" ]]; then 135 if [[ -n "$pid" ]]; then
38 kill -- "-$pid" 2>/dev/null || true 136 kill -- "-$pid" 2>/dev/null || true
67 export MRJUNEJUNE_INFERENCE_SIDECAR_PATH="$mock_sidecar" 165 export MRJUNEJUNE_INFERENCE_SIDECAR_PATH="$mock_sidecar"
68 else 166 else
69 export MRJUNEJUNE_INFERENCE_SIDECAR_PATH="$PWD/$mock_sidecar" 167 export MRJUNEJUNE_INFERENCE_SIDECAR_PATH="$PWD/$mock_sidecar"
70 fi 168 fi
71 export MRJUNEJUNE_COPILOT_CLI_PATH="$MRJUNEJUNE_INFERENCE_SIDECAR_PATH" 169 export MRJUNEJUNE_COPILOT_CLI_PATH="$MRJUNEJUNE_INFERENCE_SIDECAR_PATH"
72 export MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE=1 170 export MRJUNEJUNE_ALLOW_GUEST_INFERENCE
73 # Bind to loopback for local dev; insecure cookies are only allowed here. 171 # Bind to loopback for local dev; insecure cookies are only allowed here.
74 export SERVER_HOST="${SERVER_HOST:-127.0.0.1}" 172 export SERVER_HOST="${SERVER_HOST:-127.0.0.1}"
75 export AUTH_DEV_INSECURE_COOKIE="${AUTH_DEV_INSECURE_COOKIE:-true}" 173 export AUTH_DEV_INSECURE_COOKIE="${AUTH_DEV_INSECURE_COOKIE:-true}"
76 echo "Starting mock inference at http://${SERVER_HOST}:${MRJUNEJUNE_PORT:-6969}/jrpg" 174 echo "Starting mock inference at http://${SERVER_HOST}:${MRJUNEJUNE_PORT:-6969}/jrpg"
77 else 175 else
78 : "${LITELLM_MASTER_KEY:?LITELLM_MASTER_KEY must be set}" 176 if [[ -z "${LITELLM_MASTER_KEY:-}" ]]; then
177 if [[ -n "${BUILD_WORKSPACE_DIRECTORY:-}" &&
178 "$config_file" == "$BUILD_WORKSPACE_DIRECTORY/"* &&
179 -w "$config_file" ]]; then
180 umask 077
181 LITELLM_MASTER_KEY="sk-$(
182 "$python" -c 'import secrets; print(secrets.token_hex(24))'
183 )"
184 printf '\n# Generated once for the local LiteLLM proxy.\nLITELLM_MASTER_KEY=%s\n' \
185 "$LITELLM_MASTER_KEY" >> "$config_file"
186 chmod 600 "$config_file"
187 export LITELLM_MASTER_KEY
188 echo "Generated LITELLM_MASTER_KEY in $config_file"
189 else
190 echo "LITELLM_MASTER_KEY is missing from $config_file" >&2
191 exit 1
192 fi
193 fi
194 export LITELLM_MASTER_KEY
79 token_dir="${GITHUB_COPILOT_TOKEN_DIR:-$state_root/litellm-copilot}" 195 token_dir="${GITHUB_COPILOT_TOKEN_DIR:-$state_root/litellm-copilot}"
80 mkdir -p "$state_root/copilot" "$token_dir" 196 mkdir -p "$state_root/copilot" "$token_dir"
81 chmod 700 "$state_root" "$state_root/copilot" "$token_dir" 197 chmod 700 "$state_root" "$state_root/copilot" "$token_dir"
82 198
83 export GITHUB_COPILOT_TOKEN_DIR="$token_dir" 199 export GITHUB_COPILOT_TOKEN_DIR="$token_dir"
84 if [[ ! -s "$GITHUB_COPILOT_TOKEN_DIR/access-token" ]]; then 200 if [[ ! -s "$GITHUB_COPILOT_TOKEN_DIR/access-token" ]]; then
85 echo "GitHub Copilot is not authenticated for LiteLLM." >&2 201 echo "GitHub Copilot is not authenticated for LiteLLM." >&2
86 echo "Run: bazel run //mrjunejune/inference:litellm_proxy -- --authenticate --token-dir \"$GITHUB_COPILOT_TOKEN_DIR\"" >&2 202 echo "Run: bazel run //mrjunejune:run_inference_stack -- --authenticate" >&2
87 exit 1 203 exit 1
88 fi 204 fi
89 205
90 setsid "$python" "$litellm_zip" \ 206 setsid "$python" "$litellm_zip" \
91 --config "$litellm_config" \ 207 --config "$litellm_config" \
124 export COPILOT_SIDECAR_HOME="$state_root/copilot" 240 export COPILOT_SIDECAR_HOME="$state_root/copilot"
125 export LITELLM_BASE_URL="http://${litellm_host}:${litellm_port}/v1" 241 export LITELLM_BASE_URL="http://${litellm_host}:${litellm_port}/v1"
126 export LITELLM_MODEL="${LITELLM_MODEL:-jrpg-copilot}" 242 export LITELLM_MODEL="${LITELLM_MODEL:-jrpg-copilot}"
127 export LITELLM_WIRE_API="${LITELLM_WIRE_API:-completions}" 243 export LITELLM_WIRE_API="${LITELLM_WIRE_API:-completions}"
128 export LITELLM_API_KEY="$LITELLM_MASTER_KEY" 244 export LITELLM_API_KEY="$LITELLM_MASTER_KEY"
129 export MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE="${MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE:-0}" 245 export MRJUNEJUNE_ALLOW_GUEST_INFERENCE
130 # run_inference_stack is a local dev command; bind to loopback. 246 # run_inference_stack is a local dev command; bind to loopback.
131 export SERVER_HOST="${SERVER_HOST:-127.0.0.1}" 247 export SERVER_HOST="${SERVER_HOST:-127.0.0.1}"
132 export AUTH_DEV_INSECURE_COOKIE="${AUTH_DEV_INSECURE_COOKIE:-true}" 248 export AUTH_DEV_INSECURE_COOKIE="${AUTH_DEV_INSECURE_COOKIE:-true}"
133 fi 249 fi
134 250
251 export MRJUNEJUNE_CONFIG_PATH="$config_file"
135 setsid "$server" & 252 setsid "$server" &
136 server_pid=$! 253 server_pid=$!
137 while true; do 254 while true; do
138 if ! kill -0 "$server_pid" 2>/dev/null; then 255 if ! kill -0 "$server_pid" 2>/dev/null; then
139 set +e 256 set +e