OpenClaw-Setup/openclaw-setup-copilot/scripts/model_schedule_guard.sh

119 lines
3.8 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_SCHEDULE_CONFIG:-$ROOT_DIR/config/model-schedule.config.json}"
if ! command -v jq >/dev/null 2>&1; then
echo "[model-schedule] jq is required" >&2
exit 1
fi
if ! command -v openclaw >/dev/null 2>&1; then
echo "[model-schedule] openclaw CLI is required" >&2
exit 1
fi
expand_tilde() {
local p="$1"
if [[ "$p" == "~" ]]; then
echo "$HOME"
elif [[ "$p" == "~/"* ]]; then
echo "$HOME/${p#~/}"
else
echo "$p"
fi
}
if [[ ! -f "$CONFIG_PATH" ]]; then
echo "[model-schedule] missing config: $CONFIG_PATH" >&2
exit 1
fi
enabled="$(jq -r '.enabled // false' "$CONFIG_PATH")"
if [[ "$enabled" != "true" ]]; then
exit 0
fi
day_profile="$(jq -r '.dayProfile // "paid"' "$CONFIG_PATH")"
night_profile="$(jq -r '.nightProfile // "free"' "$CONFIG_PATH")"
day_start_hour="$(jq -r '.dayStartHour // 8' "$CONFIG_PATH")"
night_start_hour="$(jq -r '.nightStartHour // 18' "$CONFIG_PATH")"
session_key="$(jq -r '.sessionKey // "agent:main:main"' "$CONFIG_PATH")"
switch_script_raw="$(jq -r '.switchScript // "./scripts/model_profile_switch.sh"' "$CONFIG_PATH")"
state_file_raw="$(jq -r '.stateFile // "~/.openclaw/model-schedule-state.json"' "$CONFIG_PATH")"
state_file="$(expand_tilde "$state_file_raw")"
profiles_config="${MODEL_PROFILES_CONFIG:-$ROOT_DIR/config/model-profiles.config.json}"
if [[ "$switch_script_raw" = /* ]]; then
switch_script="$switch_script_raw"
else
switch_script="$ROOT_DIR/${switch_script_raw#./}"
fi
if [[ ! -x "$switch_script" ]]; then
echo "[model-schedule] switch script is not executable: $switch_script" >&2
exit 1
fi
if ! [[ "$day_start_hour" =~ ^[0-9]+$ && "$night_start_hour" =~ ^[0-9]+$ ]]; then
echo "[model-schedule] dayStartHour/nightStartHour must be integers (0-23)" >&2
exit 1
fi
if (( day_start_hour < 0 || day_start_hour > 23 || night_start_hour < 0 || night_start_hour > 23 )); then
echo "[model-schedule] dayStartHour/nightStartHour must be in 0..23" >&2
exit 1
fi
if (( day_start_hour == night_start_hour )); then
echo "[model-schedule] dayStartHour and nightStartHour cannot be equal" >&2
exit 1
fi
current_hour="$(date +%H)"
current_hour=$((10#$current_hour))
is_night="false"
if (( night_start_hour > day_start_hour )); then
if (( current_hour >= night_start_hour || current_hour < day_start_hour )); then
is_night="true"
fi
else
if (( current_hour >= night_start_hour && current_hour < day_start_hour )); then
is_night="true"
fi
fi
desired_profile="$day_profile"
if [[ "$is_night" == "true" ]]; then
desired_profile="$night_profile"
fi
mkdir -p "$(dirname "$state_file")"
if [[ ! -f "$state_file" ]]; then
printf '{}\n' > "$state_file"
fi
last_profile="$(jq -r '.lastAppliedProfile // empty' "$state_file")"
desired_primary=""
if [[ -f "$profiles_config" ]]; then
desired_primary="$(jq -r --arg p "$desired_profile" '.profiles[$p].primary // empty' "$profiles_config")"
fi
current_primary="$(openclaw models status --json 2>/dev/null | jq -r '.defaultModel // empty')"
if [[ "$last_profile" == "$desired_profile" ]]; then
if [[ -n "$desired_primary" && "$current_primary" == "$desired_primary" ]]; then
exit 0
fi
fi
echo "[model-schedule] hour=$current_hour desired_profile=$desired_profile last_profile=${last_profile:-none} current_primary=${current_primary:-unknown}"
MODEL_SWITCH_SESSION_KEY="$session_key" bash "$switch_script" "$desired_profile" --no-live --no-status
tmp_file="$state_file.tmp"
jq \
--arg profile "$desired_profile" \
--arg when "$(date -u +"%Y-%m-%dT%H:%M:%SZ")" \
--arg session "$session_key" \
'.lastAppliedProfile=$profile | .lastAppliedAt=$when | .sessionKey=$session' \
"$state_file" > "$tmp_file" && mv "$tmp_file" "$state_file"