159 lines
4.1 KiB
Bash
Executable File
159 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
CONFIG_PATH="${MODEL_PROFILES_CONFIG:-$ROOT_DIR/config/model-profiles.config.json}"
|
|
SESSION_KEY="${MODEL_SWITCH_SESSION_KEY:-agent:main:main}"
|
|
|
|
if ! command -v jq >/dev/null 2>&1; then
|
|
echo "[model-switch] jq is required" >&2
|
|
exit 1
|
|
fi
|
|
if ! command -v openclaw >/dev/null 2>&1; then
|
|
echo "[model-switch] openclaw CLI is required" >&2
|
|
exit 1
|
|
fi
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage:
|
|
bash ./scripts/model_profile_switch.sh status
|
|
bash ./scripts/model_profile_switch.sh <profile> [--no-live] [--no-status]
|
|
|
|
Examples:
|
|
bash ./scripts/model_profile_switch.sh free
|
|
bash ./scripts/model_profile_switch.sh paid --no-live
|
|
USAGE
|
|
}
|
|
|
|
get_session_id() {
|
|
local session_key="$1"
|
|
local state_dir="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
|
|
local sessions_file="$state_dir/agents/main/sessions/sessions.json"
|
|
if [[ ! -f "$sessions_file" ]]; then
|
|
return 0
|
|
fi
|
|
jq -r --arg key "$session_key" '.[$key].sessionId // empty' "$sessions_file"
|
|
}
|
|
|
|
if [[ ! -f "$CONFIG_PATH" ]]; then
|
|
echo "[model-switch] missing config: $CONFIG_PATH" >&2
|
|
exit 1
|
|
fi
|
|
|
|
profile="${1:-}"
|
|
if [[ -z "$profile" ]]; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
shift || true
|
|
|
|
apply_live="true"
|
|
show_status="true"
|
|
while (( "$#" )); do
|
|
case "$1" in
|
|
--no-live) apply_live="false" ;;
|
|
--no-status) show_status="false" ;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "[model-switch] unknown argument: $1" >&2
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
if [[ "$profile" == "status" ]]; then
|
|
echo "Available profiles:"
|
|
jq -r '.profiles | to_entries[] | "- \(.key): \(.value.primary) (\(.value.description // "no description"))"' "$CONFIG_PATH"
|
|
echo ""
|
|
openclaw models status
|
|
exit 0
|
|
fi
|
|
|
|
profile_exists="$(jq -r --arg p "$profile" '.profiles[$p] != null' "$CONFIG_PATH")"
|
|
if [[ "$profile_exists" != "true" ]]; then
|
|
echo "[model-switch] unknown profile '$profile' in $CONFIG_PATH" >&2
|
|
jq -r '.profiles | keys[]' "$CONFIG_PATH" | sed 's/^/ - /'
|
|
exit 1
|
|
fi
|
|
|
|
primary="$(jq -r --arg p "$profile" '.profiles[$p].primary // empty' "$CONFIG_PATH")"
|
|
if [[ -z "$primary" ]]; then
|
|
echo "[model-switch] profile '$profile' has no primary model" >&2
|
|
exit 1
|
|
fi
|
|
fallbacks=()
|
|
while IFS= read -r fb; do
|
|
[[ -z "$fb" ]] && continue
|
|
fallbacks+=("$fb")
|
|
done < <(jq -r --arg p "$profile" '.profiles[$p].fallbacks[]? // empty' "$CONFIG_PATH")
|
|
|
|
echo "[model-switch] Applying profile: $profile"
|
|
echo "[model-switch] primary: $primary"
|
|
if [[ ${#fallbacks[@]} -gt 0 ]]; then
|
|
echo "[model-switch] fallbacks: ${fallbacks[*]}"
|
|
else
|
|
echo "[model-switch] fallbacks: (none)"
|
|
fi
|
|
|
|
openclaw models set "$primary" >/dev/null
|
|
openclaw models fallbacks clear >/dev/null
|
|
for fb in "${fallbacks[@]}"; do
|
|
[[ -z "$fb" ]] && continue
|
|
openclaw models fallbacks add "$fb" >/dev/null
|
|
done
|
|
|
|
provider_policy_len="$(jq -r --arg p "$profile" '.profiles[$p].providerPolicy // {} | length' "$CONFIG_PATH")"
|
|
if [[ "$provider_policy_len" != "0" ]]; then
|
|
while IFS=$'\t' read -r provider enabled; do
|
|
if [[ -z "$provider" || -z "$enabled" ]]; then
|
|
continue
|
|
fi
|
|
openclaw config set --json "providers.$provider.enabled" "$enabled" >/dev/null || true
|
|
done < <(jq -r --arg p "$profile" '.profiles[$p].providerPolicy // {} | to_entries[] | "\(.key)\t\(.value)"' "$CONFIG_PATH")
|
|
fi
|
|
|
|
if [[ "$apply_live" == "true" ]]; then
|
|
session_id="$(get_session_id "$SESSION_KEY")"
|
|
if [[ -n "$session_id" ]]; then
|
|
python3 - "$session_id" "$primary" <<'PY'
|
|
import subprocess
|
|
import sys
|
|
|
|
session_id = sys.argv[1]
|
|
primary = sys.argv[2]
|
|
cmd = [
|
|
"openclaw",
|
|
"agent",
|
|
"--session-id", session_id,
|
|
"--channel", "last",
|
|
"--message", f"/model {primary}",
|
|
]
|
|
try:
|
|
subprocess.run(
|
|
cmd,
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.DEVNULL,
|
|
check=False,
|
|
timeout=20,
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
pass
|
|
PY
|
|
echo "[model-switch] live session updated: $session_id"
|
|
else
|
|
echo "[model-switch] no active session found for key $SESSION_KEY"
|
|
fi
|
|
fi
|
|
|
|
if [[ "$show_status" == "true" ]]; then
|
|
echo ""
|
|
openclaw models status
|
|
fi
|