119 lines
3.8 KiB
Bash
Executable File
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"
|