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

294 lines
8.7 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)"
POLICY_CONFIG="$ROOT_DIR/config/copilot-policy-guard.config.json"
BUDGET_CONFIG="$ROOT_DIR/config/model-budget-guard.config.json"
AUTH_CONFIG="$ROOT_DIR/config/copilot-auth-watchdog.config.json"
MODEL_PROFILES_CONFIG="$ROOT_DIR/config/model-profiles.config.json"
MODEL_SCHEDULE_CONFIG="$ROOT_DIR/config/model-schedule.config.json"
if ! command -v openclaw >/dev/null 2>&1; then
echo "[configure-guardrails] openclaw CLI is required" >&2
exit 1
fi
if ! command -v jq >/dev/null 2>&1; then
echo "[configure-guardrails] jq is required" >&2
exit 1
fi
if [[ ! -f "$MODEL_PROFILES_CONFIG" ]]; then
cat > "$MODEL_PROFILES_CONFIG" <<'JSON'
{
"profiles": {
"paid": {
"description": "Work-hours higher-quality Copilot model",
"primary": "",
"fallbacks": []
},
"free": {
"description": "Off-hours low-cost/free Copilot model stack",
"primary": "",
"fallbacks": []
}
}
}
JSON
fi
if [[ ! -f "$MODEL_SCHEDULE_CONFIG" ]]; then
cat > "$MODEL_SCHEDULE_CONFIG" <<'JSON'
{
"enabled": true,
"dayProfile": "paid",
"nightProfile": "free",
"dayStartHour": 8,
"nightStartHour": 18,
"sessionKey": "agent:main:main",
"switchScript": "./scripts/model_profile_switch.sh",
"stateFile": "~/.openclaw/model-schedule-state.json"
}
JSON
fi
is_cheap_model() {
local m
m="$(printf '%s' "$1" | tr '[:upper:]' '[:lower:]')"
[[ "$m" =~ (haiku|mini|flash|fast|nano|small|lite|economy) ]]
}
copilot_models=()
while IFS= read -r model; do
[[ -z "$model" ]] && continue
copilot_models+=("$model")
done < <(
openclaw models list 2>/dev/null \
| awk 'NR>1 {print $1}' \
| grep '^github-copilot/' \
| awk '!seen[$0]++'
)
if [[ ${#copilot_models[@]} -eq 0 ]]; then
cat >&2 <<MSG
[configure-guardrails] No github-copilot models found.
Do this first on the target machine:
1) copilot auth login
2) openclaw models refresh || true
3) openclaw models list
Then re-run:
bash ./scripts/configure_copilot_guardrails_defaults.sh
MSG
exit 1
fi
primary_model=""
for m in "${copilot_models[@]}"; do
if is_cheap_model "$m"; then
primary_model="$m"
break
fi
done
if [[ -z "$primary_model" ]]; then
primary_model="${copilot_models[0]}"
fi
# Build free/low-cost fallback candidates (excluding primary)
declare -a cheap_candidates=()
for m in "${copilot_models[@]}"; do
[[ "$m" == "$primary_model" ]] && continue
if is_cheap_model "$m"; then
cheap_candidates+=("$m")
fi
done
# If none matched cheap pattern, pick up to 2 non-primary models as fallback
if [[ ${#cheap_candidates[@]} -eq 0 ]]; then
for m in "${copilot_models[@]}"; do
[[ "$m" == "$primary_model" ]] && continue
cheap_candidates+=("$m")
[[ ${#cheap_candidates[@]} -ge 2 ]] && break
done
fi
# Keep at most 2 fallbacks
if [[ ${#cheap_candidates[@]} -gt 2 ]]; then
cheap_candidates=("${cheap_candidates[@]:0:2}")
fi
# High models: anything non-cheap and non-primary
declare -a high_models=()
for m in "${copilot_models[@]}"; do
[[ "$m" == "$primary_model" ]] && continue
if ! is_cheap_model "$m"; then
high_models+=("$m")
fi
done
# Ensure at least one high model if multiple exist
if [[ ${#high_models[@]} -eq 0 && ${#copilot_models[@]} -gt 1 ]]; then
for m in "${copilot_models[@]}"; do
[[ "$m" == "$primary_model" ]] && continue
high_models+=("$m")
break
done
fi
paid_model=""
if [[ ${#high_models[@]} -gt 0 ]]; then
paid_model="${high_models[0]}"
fi
if [[ -z "$paid_model" ]]; then
for m in "${copilot_models[@]}"; do
[[ "$m" == "$primary_model" ]] && continue
paid_model="$m"
break
done
fi
if [[ -z "$paid_model" ]]; then
paid_model="$primary_model"
fi
# free profile = lowest-cost primary + lowest-cost fallbacks
declare -a free_fallbacks=("${cheap_candidates[@]}")
# paid profile = strongest available model + cheap fallback chain
declare -a paid_fallbacks=()
if [[ "$primary_model" != "$paid_model" ]]; then
paid_fallbacks+=("$primary_model")
fi
for m in "${cheap_candidates[@]}"; do
[[ "$m" == "$paid_model" ]] && continue
skip="false"
for cur in "${paid_fallbacks[@]}"; do
if [[ "$cur" == "$m" ]]; then
skip="true"
break
fi
done
[[ "$skip" == "true" ]] && continue
paid_fallbacks+=("$m")
done
active_profile="paid"
current_hour="$(date +%H)"
current_hour=$((10#$current_hour))
if (( current_hour >= 18 || current_hour < 8 )); then
active_profile="free"
fi
active_primary="$paid_model"
active_fallbacks=("${paid_fallbacks[@]}")
if [[ "$active_profile" == "free" ]]; then
active_primary="$primary_model"
active_fallbacks=("${free_fallbacks[@]}")
fi
fallbacks_json="$(printf '%s\n' "${active_fallbacks[@]}" | jq -R . | jq -s .)"
high_json="$(printf '%s\n' "${high_models[@]}" | jq -R . | jq -s .)"
free_fallbacks_json="$(printf '%s\n' "${free_fallbacks[@]}" | jq -R . | jq -s .)"
paid_fallbacks_json="$(printf '%s\n' "${paid_fallbacks[@]}" | jq -R . | jq -s .)"
# Update configs
jq \
--arg primary "$active_primary" \
--argjson fallbacks "$fallbacks_json" \
'.enabled=true
| .autoFix=true
| .desiredPrimaryModel=$primary
| .enforceFallbackAllowlist=true
| .allowedFallbacks=$fallbacks
| .providerPolicy["github-copilot"]=true
| .providerPolicy["openai"]=false
| .providerPolicy["anthropic"]=false
| .providerPolicy["openrouter"]=false' \
"$POLICY_CONFIG" > "$POLICY_CONFIG.tmp" && mv "$POLICY_CONFIG.tmp" "$POLICY_CONFIG"
jq \
--arg low "$primary_model" \
--argjson highs "$high_json" \
'.enabled=true
| .lowModel=$low
| .highModels=$highs
| .warnAfterMinutes=2
| .revertAfterMinutes=45
| .minWarnIntervalMinutes=20' \
"$BUDGET_CONFIG" > "$BUDGET_CONFIG.tmp" && mv "$BUDGET_CONFIG.tmp" "$BUDGET_CONFIG"
jq '.enabled=true | .minAlertIntervalMinutes=30 | .checkOpenClawModelStatus=true' \
"$AUTH_CONFIG" > "$AUTH_CONFIG.tmp" && mv "$AUTH_CONFIG.tmp" "$AUTH_CONFIG"
jq \
--arg paid "$paid_model" \
--arg free "$primary_model" \
--argjson paid_fallbacks "$paid_fallbacks_json" \
--argjson free_fallbacks "$free_fallbacks_json" \
'.profiles.paid.description="Work-hours higher-quality Copilot model"
| .profiles.paid.primary=$paid
| .profiles.paid.fallbacks=$paid_fallbacks
| .profiles.paid.providerPolicy["github-copilot"]=true
| .profiles.paid.providerPolicy["openai"]=false
| .profiles.paid.providerPolicy["anthropic"]=false
| .profiles.paid.providerPolicy["openrouter"]=false
| .profiles.free.description="Off-hours low-cost/free Copilot model stack"
| .profiles.free.primary=$free
| .profiles.free.fallbacks=$free_fallbacks
| .profiles.free.providerPolicy["github-copilot"]=true
| .profiles.free.providerPolicy["openai"]=false
| .profiles.free.providerPolicy["anthropic"]=false
| .profiles.free.providerPolicy["openrouter"]=false' \
"$MODEL_PROFILES_CONFIG" > "$MODEL_PROFILES_CONFIG.tmp" && mv "$MODEL_PROFILES_CONFIG.tmp" "$MODEL_PROFILES_CONFIG"
jq \
'.enabled=true
| .dayProfile="paid"
| .nightProfile="free"
| .dayStartHour=(.dayStartHour // 8)
| .nightStartHour=(.nightStartHour // 18)
| .sessionKey=(.sessionKey // "agent:main:main")
| .switchScript=(.switchScript // "./scripts/model_profile_switch.sh")
| .stateFile=(.stateFile // "~/.openclaw/model-schedule-state.json")' \
"$MODEL_SCHEDULE_CONFIG" > "$MODEL_SCHEDULE_CONFIG.tmp" && mv "$MODEL_SCHEDULE_CONFIG.tmp" "$MODEL_SCHEDULE_CONFIG"
# Apply live policy/routing on target machine
openclaw models set "$active_primary" >/dev/null
openclaw models fallbacks clear >/dev/null
for fb in "${active_fallbacks[@]}"; do
openclaw models fallbacks add "$fb" >/dev/null
done
openclaw config set --json providers.github-copilot.enabled true >/dev/null
openclaw config set --json providers.openai.enabled false >/dev/null
openclaw config set --json providers.anthropic.enabled false >/dev/null
openclaw config set --json providers.openrouter.enabled false >/dev/null
echo "Configured Copilot guardrails defaults:"
echo " active_profile_now: $active_profile"
echo " active_primary_model: $active_primary"
if [[ ${#active_fallbacks[@]} -gt 0 ]]; then
echo " active_fallbacks: ${active_fallbacks[*]}"
else
echo " active_fallbacks: (none)"
fi
echo " paid_profile_primary: $paid_model"
if [[ ${#paid_fallbacks[@]} -gt 0 ]]; then
echo " paid_profile_fallbacks: ${paid_fallbacks[*]}"
else
echo " paid_profile_fallbacks: (none)"
fi
echo " free_profile_primary: $primary_model"
if [[ ${#free_fallbacks[@]} -gt 0 ]]; then
echo " free_profile_fallbacks: ${free_fallbacks[*]}"
else
echo " free_profile_fallbacks: (none)"
fi
echo ""
echo "Applied live routing/provider policy and updated config files:"
echo " $POLICY_CONFIG"
echo " $BUDGET_CONFIG"
echo " $AUTH_CONFIG"
echo " $MODEL_PROFILES_CONFIG"
echo " $MODEL_SCHEDULE_CONFIG"