From fb924a7fa615a2432dbc07368028fc48be8d4ee5 Mon Sep 17 00:00:00 2001 From: Matt Bruce Date: Fri, 20 Feb 2026 12:38:05 -0600 Subject: [PATCH] Remove openclaw-setup-copilot files --- openclaw-setup-copilot/AGENTS.md | 125 ------ openclaw-setup-copilot/PRD.md | 41 -- openclaw-setup-copilot/README.md | 340 ---------------- .../config/copilot-auth-watchdog.config.json | 7 - .../config/copilot-policy-guard.config.json | 18 - .../config/model-budget-guard.config.json | 10 - .../config/model-profiles.config.json | 26 -- .../config/model-schedule.config.json | 10 - openclaw-setup-copilot/docs/context/BOOT.md | 72 ---- .../docs/context/HEARTBEAT.md | 10 - .../docs/context/IDENTITY.md | 9 - openclaw-setup-copilot/docs/context/MEMORY.md | 22 -- openclaw-setup-copilot/docs/context/SOUL.md | 22 -- openclaw-setup-copilot/docs/context/TOOLS.md | 121 ------ openclaw-setup-copilot/docs/context/USER.md | 38 -- .../docs/operations/AI_SETUP_HANDOFF.md | 62 --- .../docs/operations/WORK_SETUP_CHECKLIST.md | 244 ------------ .../docs/operations/troubleshooting.md | 210 ---------- openclaw-setup-copilot/memory/.gitkeep | 0 .../configure_copilot_guardrails_defaults.sh | 371 ------------------ .../scripts/copilot_auth_watchdog.sh | 134 ------- .../scripts/copilot_policy_guard.sh | 235 ----------- .../scripts/finalize_copilot_setup.sh | 100 ----- .../install_copilot_auth_watchdog_launchd.sh | 78 ---- .../scripts/install_copilot_guardrails.sh | 15 - .../install_copilot_policy_guard_launchd.sh | 78 ---- .../install_model_budget_guard_launchd.sh | 78 ---- .../install_model_schedule_guard_launchd.sh | 86 ---- .../scripts/model_budget_guard.sh | 202 ---------- .../scripts/model_profile_switch.sh | 186 --------- .../scripts/model_schedule_guard.sh | 118 ------ .../setup/setup_openclaw_copilot.sh | 201 ---------- 32 files changed, 3269 deletions(-) delete mode 100644 openclaw-setup-copilot/AGENTS.md delete mode 100644 openclaw-setup-copilot/PRD.md delete mode 100644 openclaw-setup-copilot/README.md delete mode 100644 openclaw-setup-copilot/config/copilot-auth-watchdog.config.json delete mode 100644 openclaw-setup-copilot/config/copilot-policy-guard.config.json delete mode 100644 openclaw-setup-copilot/config/model-budget-guard.config.json delete mode 100644 openclaw-setup-copilot/config/model-profiles.config.json delete mode 100644 openclaw-setup-copilot/config/model-schedule.config.json delete mode 100644 openclaw-setup-copilot/docs/context/BOOT.md delete mode 100644 openclaw-setup-copilot/docs/context/HEARTBEAT.md delete mode 100644 openclaw-setup-copilot/docs/context/IDENTITY.md delete mode 100644 openclaw-setup-copilot/docs/context/MEMORY.md delete mode 100644 openclaw-setup-copilot/docs/context/SOUL.md delete mode 100644 openclaw-setup-copilot/docs/context/TOOLS.md delete mode 100644 openclaw-setup-copilot/docs/context/USER.md delete mode 100644 openclaw-setup-copilot/docs/operations/AI_SETUP_HANDOFF.md delete mode 100644 openclaw-setup-copilot/docs/operations/WORK_SETUP_CHECKLIST.md delete mode 100644 openclaw-setup-copilot/docs/operations/troubleshooting.md delete mode 100644 openclaw-setup-copilot/memory/.gitkeep delete mode 100755 openclaw-setup-copilot/scripts/configure_copilot_guardrails_defaults.sh delete mode 100755 openclaw-setup-copilot/scripts/copilot_auth_watchdog.sh delete mode 100755 openclaw-setup-copilot/scripts/copilot_policy_guard.sh delete mode 100755 openclaw-setup-copilot/scripts/finalize_copilot_setup.sh delete mode 100755 openclaw-setup-copilot/scripts/install_copilot_auth_watchdog_launchd.sh delete mode 100755 openclaw-setup-copilot/scripts/install_copilot_guardrails.sh delete mode 100755 openclaw-setup-copilot/scripts/install_copilot_policy_guard_launchd.sh delete mode 100755 openclaw-setup-copilot/scripts/install_model_budget_guard_launchd.sh delete mode 100755 openclaw-setup-copilot/scripts/install_model_schedule_guard_launchd.sh delete mode 100755 openclaw-setup-copilot/scripts/model_budget_guard.sh delete mode 100755 openclaw-setup-copilot/scripts/model_profile_switch.sh delete mode 100755 openclaw-setup-copilot/scripts/model_schedule_guard.sh delete mode 100755 openclaw-setup-copilot/setup/setup_openclaw_copilot.sh diff --git a/openclaw-setup-copilot/AGENTS.md b/openclaw-setup-copilot/AGENTS.md deleted file mode 100644 index 4acd81c..0000000 --- a/openclaw-setup-copilot/AGENTS.md +++ /dev/null @@ -1,125 +0,0 @@ -# AGENTS.md - Work Machine Setup Template - -This folder is now a setup template for another computer. - -Important: -- Do not run install or config mutation commands on this current machine. -- Use these docs as the source of truth when setting up your work computer. - -## Mode Toggle (Read First) - -Current mode in this copy: -- `LOCAL-SAFETY MODE` is active (no install/mutation on this machine). - -When you copy this folder to the target work machine: -1. Remove or rewrite the `LOCAL-SAFETY MODE` block below. -2. Uncomment the `TARGET-INSTALL MODE` block. -3. Follow `docs/operations/WORK_SETUP_CHECKLIST.md`. - -### LOCAL-SAFETY MODE (ACTIVE NOW) - -- Do not run install commands here. -- Do not run `scripts/install_copilot_guardrails.sh` here. -- Do not run `scripts/finalize_copilot_setup.sh` here. -- Do not run provider/model mutation commands here. -- Use this copy only for editing docs/scripts before transfer. - - - -## Goal - -Create a reliable OpenClaw setup that uses GitHub Copilot CLI Enterprise as the main provider, with a Senior iOS Engineer persona focused on architecture and refactoring. - -## Setup Flow (target computer only) - -1. Run `setup/setup_openclaw_copilot.sh` for Copilot-first baseline. -2. Run `scripts/finalize_copilot_setup.sh` to complete auth + profiles + guardrails in one command. -3. Verify gateway/model health. - -## Copilot CLI Install and Auth - -```bash -# preferred for latest models -brew install copilot-cli@prerelease -# or -npm install -g @github/copilot-cli - -copilot auth login -copilot auth status -``` - -## OpenClaw Copilot Model Routing - -### If your OpenClaw supports `config patch` - -Use your allowlist patch workflow. - -### If your OpenClaw does NOT support `config patch` - -Use direct commands: - -```bash -openclaw models set github-copilot/claude-sonnet-4.6 -openclaw models fallbacks clear -openclaw models fallbacks add github-copilot/ -openclaw models fallbacks add github-copilot/ - -openclaw config set --json providers.github-copilot.enabled true -openclaw config set --json providers.openai.enabled false -openclaw config set --json providers.anthropic.enabled false -openclaw config set --json providers.openrouter.enabled false -``` - -## Session Startup Routine - -1. Read `docs/context/SOUL.md` -2. Read `docs/context/USER.md` -3. Read `memory/YYYY-MM-DD.md` (today and yesterday) -4. In direct owner chat, also read `docs/context/MEMORY.md` -5. Run health check: - -```bash -openclaw status --deep -openclaw models status -``` - -Model guard should be active on target machine: - -```bash -launchctl print gui/$(id -u)/ai.openclaw.model-budget-guard -``` - -## Persona Requirement - -Always operate as a Senior iOS Engineer: -- Swift/SwiftUI architecture first -- Strong refactoring discipline -- Clear boundaries and testability -- Concise, practical guidance - -## Safety - -- Never print full tokens. -- Never post externally without explicit instruction. -- Prefer non-destructive actions. diff --git a/openclaw-setup-copilot/PRD.md b/openclaw-setup-copilot/PRD.md deleted file mode 100644 index c321fe0..0000000 --- a/openclaw-setup-copilot/PRD.md +++ /dev/null @@ -1,41 +0,0 @@ -# PRD: OpenClaw Copilot Workstation Setup - -## Purpose -Provide a repeatable, low-risk setup for a Copilot-only OpenClaw workstation with cost controls and schedule-based model routing. - -## Goals -- Enforce `github-copilot/*` as the only provider/model family. -- Use paid profile during work hours (`08:00-18:00` local). -- Use free/low-cost profile off-hours (`18:00-08:00` local). -- Auto-heal routing/policy drift via launchd guardrails. -- Keep installation easy for AI-assisted and human-assisted setup. - -## Scope -- Config-driven profile routing (`config/model-profiles.config.json`). -- Schedule guard (`scripts/model_schedule_guard.sh` + launchd). -- Budget guard, policy guard, auth watchdog. -- Staged launchd runtime under: - - `~/Library/Application Support/openclaw-copilot-guard` - -## Non-Goals -- Supporting non-Copilot providers in normal operation. -- Cross-platform install workflows (target is macOS). -- Billing automation outside model/provider selection. - -## Required Outcomes -- `scripts/install_copilot_guardrails.sh` installs all 4 guards: - - `ai.openclaw.model-budget-guard` - - `ai.openclaw.copilot-policy-guard` - - `ai.openclaw.copilot-auth-watchdog` - - `ai.openclaw.copilot-model-schedule-guard` -- Off-hours traffic defaults to free/low-cost profile. -- Work-hours defaults return to paid profile. -- Docs clearly describe setup, verification, troubleshooting. - -## Success Criteria -- Fresh machine setup succeeds using: - - `setup/setup_openclaw_copilot.sh` - - `copilot auth login` - - `bash ./scripts/install_copilot_guardrails.sh` -- `openclaw models status` reflects expected profile by local time window. -- Launchd checks/logs show healthy runs and no repeated hard failures. diff --git a/openclaw-setup-copilot/README.md b/openclaw-setup-copilot/README.md deleted file mode 100644 index af10023..0000000 --- a/openclaw-setup-copilot/README.md +++ /dev/null @@ -1,340 +0,0 @@ -# OpenClaw Work Setup Template - -Template workspace for setting up OpenClaw on a work computer with GitHub Copilot CLI Enterprise as the primary model provider, plus an iOS-focused assistant persona. - -## Purpose - -Use this folder as a repeatable setup baseline on another machine. - -- Primary provider: GitHub Copilot Enterprise -- Persona: Senior iOS Engineer (architecture + refactoring focused) - -## Important - -This repository is intended as a guide/template. -Do not run mutation commands on an already-stable machine unless intended. - -## Workspace Layout - -Keep only operator docs at root: -- `AGENTS.md` -- `README.md` -- `PRD.md` - -Everything else is organized by purpose: -- `setup/`: one-time bootstrap installers -- `scripts/`: guardrails, switching, and launchd installers -- `config/`: editable policy/profile/schedule/auth JSON -- `docs/context/`: runtime persona + user/context files -- `docs/operations/`: handoff/checklist/troubleshooting docs -- `memory/`: session memory files - -## Workspace Files - -- `AGENTS.md`: operating rules and setup sequence -- `docs/context/BOOT.md`: startup checks -- `docs/context/SOUL.md`: persona behavior -- `docs/context/USER.md`: user context -- `docs/context/TOOLS.md`: command reference -- `docs/operations/troubleshooting.md`: failure recovery runbook -- `setup/setup_openclaw_copilot.sh`: primary Copilot Enterprise setup -- `scripts/finalize_copilot_setup.sh`: one-command auth + model/profile + guardrail finalize -- `config/copilot-policy-guard.config.json`: Copilot routing/provider policy guard config -- `config/copilot-auth-watchdog.config.json`: Copilot auth watchdog config -- `config/model-profiles.config.json`: paid/free profile routing definitions -- `config/model-schedule.config.json`: work-hours/off-hours schedule config -- `scripts/install_copilot_guardrails.sh`: installs all launchd guardrails - -## Target Machine Prerequisites - -- macOS with Homebrew -- Node.js + npm -- OpenClaw installed -- GitHub Enterprise account with Copilot CLI entitlement - -## Telegram Note (If Used) - -- You do **not** need a new Telegram user account or phone number. -- One personal Telegram account is enough. -- Create a bot with `@BotFather`; bots are separate from user accounts. -- You chat with the bot from your existing Telegram account. - -## Setup (Target Computer) - -AI handoff: -- Use `docs/operations/AI_SETUP_HANDOFF.md` when delegating setup to another AI assistant. -- It includes a strict prompt, command order, and verification checks. - -Quick path (copy/paste): - -```bash -bash ./setup/setup_openclaw_copilot.sh -bash ./scripts/finalize_copilot_setup.sh -openclaw status --deep -``` - -Optional custom install locations: - -```bash -# Move OpenClaw runtime data (~/.openclaw) to another path -OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot bash ./setup/setup_openclaw_copilot.sh - -# Install global npm CLIs into a custom prefix/bin -NPM_GLOBAL_PREFIX="$HOME/.npm-global" bash ./setup/setup_openclaw_copilot.sh - -# Use both -OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot \ -NPM_GLOBAL_PREFIX="$HOME/.npm-global" \ -bash ./setup/setup_openclaw_copilot.sh -``` - -Order and dependency (important): - -1. `setup/setup_openclaw_copilot.sh` installs tooling only (`openclaw`, `copilot`, Node). -2. `scripts/finalize_copilot_setup.sh` handles login, model discovery, profile selection, guardrails, hooks, and gateway restart. -3. If browser auth cannot complete inside finalize flow, run `copilot auth login`, then rerun finalize. - -Why: -- OpenClaw installation does not require Copilot login. -- `github-copilot/*` model selection and policy checks do require Copilot auth. -- Finalize script prevents users from forgetting model/profile/guardrail wiring after login. - - -1. Primary Copilot setup: - -```bash -bash ./setup/setup_openclaw_copilot.sh -``` - -If using a custom location: - -```bash -OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot bash ./setup/setup_openclaw_copilot.sh -``` - -2. Finalize in one command (recommended): - -```bash -bash ./scripts/finalize_copilot_setup.sh -``` - -What finalize does: -- Opens `copilot auth login` if needed -- Refreshes model catalog -- Prompts you to choose the paid profile model from non-free candidates -- Auto-picks the free profile model/fallbacks from low-cost candidates -- Installs all guardrails -- Enables recommended hooks -- Restarts gateway - -3. Verify: - -```bash -copilot auth status -openclaw models status -openclaw status --deep -``` - -If login is missing/expired, finalize will prompt for login and retry setup. - -For unattended/non-interactive automation: - -```bash -PROMPT_FOR_PAID_MODEL=false bash ./scripts/finalize_copilot_setup.sh -``` - -### How To Choose Copilot Models (and Why It Matters) - -Choosing the right primary and fallback models is important because it controls: - -- Response speed in chat/Telegram -- Quality of coding/refactoring output -- Enterprise quota burn and cost exposure -- Reliability when one model is rate-limited or unavailable - -Fallback policy for this template: -- Fallbacks must be free-tier or lowest-cost models only. -- Do not use premium fallbacks (for example Opus-class) as defaults. -- In strict Copilot-only mode, "free" means no extra external provider billing and lowest-burn models in your enterprise seat. - -Recommended strategy: - -1. Set a fast, general coding model as `primary` for daily work. -2. Add 1-2 low-cost fallbacks only. -3. Keep names exactly as shown in `openclaw models list` to avoid unknown-model failures. - -Selection guide: - -- Fast default: choose the quickest Sonnet/Codex variant your seat exposes -- Prefer fast/cheap variants over premium models for fallback -- Avoid premium fallbacks as defaults to prevent silent quota drain - -4. Set Copilot model routing: - -```bash -openclaw models set github-copilot/claude-sonnet-4.6 -openclaw models fallbacks clear -openclaw models fallbacks add github-copilot/ -openclaw models fallbacks add github-copilot/ -``` - -After setting this, always verify: - -```bash -openclaw models status -``` - -You should see a Copilot model as default plus your fallback chain. - -5. Optional strict provider lock (if policy requires strict allowlist): - -```bash -openclaw config set --json providers.github-copilot.enabled true -openclaw config set --json providers.openai.enabled false -openclaw config set --json providers.anthropic.enabled false -openclaw config set --json providers.openrouter.enabled false -``` - -6. Restart and verify: - -```bash -openclaw gateway restart -openclaw status --deep -openclaw models status -``` - -7. Configure + install Copilot guardrails (recommended): - -```bash -bash ./scripts/install_copilot_guardrails.sh -``` - -Guard config files: -- `config/model-budget-guard.config.json` -- `config/copilot-policy-guard.config.json` -- `config/copilot-auth-watchdog.config.json` -- `config/model-profiles.config.json` -- `config/model-schedule.config.json` - -Runtime staging note (important): -- Installer stages active guard scripts/config into: - - `~/Library/Application Support/openclaw-copilot-guard` -- Launchd runs guards from that staged folder, not directly from repository path. -- After editing guard scripts/config in this repo, re-run: - - `bash ./scripts/install_copilot_guardrails.sh` - to sync staged runtime files. - -What it does: -- Model budget guard: warns on high-cost model usage and auto-reverts to low-cost model -- Copilot policy guard: enforces Copilot-only provider/model policy and fixes drift -- Copilot auth watchdog: alerts when Copilot auth expires or becomes unhealthy -- Model schedule guard: uses paid profile during work hours and free profile off-hours - -Why this is important: -- Prevents someone from staying on high-tier models all day -- Reduces accidental enterprise quota burn -- Keeps day-to-day latency faster with a low-cost default - -Default schedule behavior: -- Work hours (`08:00` to `18:00` local time): `paid` profile -- Off-hours (`18:00` to `08:00` local time): `free` profile - -Schedule wiring (important): -- `config/model-schedule.config.json` controls time windows and which script applies profiles. -- `switchScript` should be `./scripts/model_profile_switch.sh`. -- `config/model-profiles.config.json` defines what `paid` and `free` actually mean (primary + fallbacks). - -Expected schedule config shape: - -```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" -} -``` - -Important behavior difference vs Max: -- Copilot `config/model-profiles.config.json` starts with empty model IDs in this template copy. -- `bash ./scripts/finalize_copilot_setup.sh` (or `bash ./scripts/install_copilot_guardrails.sh`) runs `configure_copilot_guardrails_defaults.sh`, detects available `github-copilot/*` models, and writes concrete `paid`/`free` models into `config/model-profiles.config.json`. -- Until that step runs on the target machine (after `copilot auth login`), schedule/profile switching has no concrete model IDs to apply. - -Quick verify commands: - -```bash -cat config/model-schedule.config.json -cat config/model-profiles.config.json -``` - -After installing guardrails, verify staged runtime files used by launchd: - -```bash -cat ~/Library/Application\ Support/openclaw-copilot-guard/model-schedule.config.json -cat ~/Library/Application\ Support/openclaw-copilot-guard/model-profiles.config.json -``` - -Manual profile switch: - -```bash -bash ./scripts/model_profile_switch.sh paid -bash ./scripts/model_profile_switch.sh free -bash ./scripts/model_profile_switch.sh status -``` - -If you need a quick switch without sending a live `/model` message: - -```bash -bash ./scripts/model_profile_switch.sh free --no-live -``` - -8. Enable recommended hooks: - -```bash -openclaw hooks enable boot-md -openclaw hooks enable command-logger -openclaw hooks enable session-memory -``` - -9. Verify hooks: - -```bash -openclaw hooks list -openclaw hooks list --eligible -``` - -## Daily Checks - -```bash -openclaw status --deep -openclaw models status -copilot auth status -``` - -If responses feel slow or weak, re-check model routing first before debugging gateway/network. - -Model guard health: - -```bash -launchctl print gui/$(id -u)/ai.openclaw.model-budget-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-policy-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-auth-watchdog -launchctl print gui/$(id -u)/ai.openclaw.copilot-model-schedule-guard -tail -n 30 /tmp/openclaw-model-budget-guard.log /tmp/openclaw-model-budget-guard.err.log -tail -n 30 /tmp/openclaw-copilot-policy-guard.log /tmp/openclaw-copilot-policy-guard.err.log -tail -n 30 /tmp/openclaw-copilot-auth-watchdog.log /tmp/openclaw-copilot-auth-watchdog.err.log -tail -n 30 /tmp/openclaw-copilot-model-schedule-guard.log /tmp/openclaw-copilot-model-schedule-guard.err.log -``` - -## Troubleshooting - -Start with `docs/operations/troubleshooting.md`. - -## Security Notes - -- Never print full API keys/tokens in logs or chat. -- Rotate any secret that may have been exposed. diff --git a/openclaw-setup-copilot/config/copilot-auth-watchdog.config.json b/openclaw-setup-copilot/config/copilot-auth-watchdog.config.json deleted file mode 100644 index c7d2168..0000000 --- a/openclaw-setup-copilot/config/copilot-auth-watchdog.config.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "enabled": false, - "sessionKey": "agent:main:main", - "minAlertIntervalMinutes": 30, - "stateFile": "~/.openclaw/copilot-auth-watchdog-state.json", - "checkOpenClawModelStatus": true -} diff --git a/openclaw-setup-copilot/config/copilot-policy-guard.config.json b/openclaw-setup-copilot/config/copilot-policy-guard.config.json deleted file mode 100644 index 2f0ceba..0000000 --- a/openclaw-setup-copilot/config/copilot-policy-guard.config.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "enabled": false, - "autoFix": true, - "sessionKey": "agent:main:main", - "minAlertIntervalMinutes": 20, - "stateFile": "~/.openclaw/copilot-policy-guard-state.json", - "requiredPrimaryPrefix": "github-copilot/", - "requiredFallbackPrefix": "github-copilot/", - "desiredPrimaryModel": "", - "enforceFallbackAllowlist": true, - "allowedFallbacks": [], - "providerPolicy": { - "github-copilot": true, - "openai": false, - "anthropic": false, - "openrouter": false - } -} diff --git a/openclaw-setup-copilot/config/model-budget-guard.config.json b/openclaw-setup-copilot/config/model-budget-guard.config.json deleted file mode 100644 index 7b388df..0000000 --- a/openclaw-setup-copilot/config/model-budget-guard.config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "enabled": false, - "sessionKey": "agent:main:main", - "lowModel": "", - "highModels": [], - "warnAfterMinutes": 2, - "revertAfterMinutes": 45, - "minWarnIntervalMinutes": 20, - "stateFile": "~/.openclaw/model-budget-guard-state.json" -} diff --git a/openclaw-setup-copilot/config/model-profiles.config.json b/openclaw-setup-copilot/config/model-profiles.config.json deleted file mode 100644 index 7761e17..0000000 --- a/openclaw-setup-copilot/config/model-profiles.config.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "profiles": { - "paid": { - "description": "Work-hours higher-quality Copilot model", - "primary": "", - "fallbacks": [], - "providerPolicy": { - "github-copilot": true, - "openai": false, - "anthropic": false, - "openrouter": false - } - }, - "free": { - "description": "Off-hours low-cost/free Copilot model stack", - "primary": "", - "fallbacks": [], - "providerPolicy": { - "github-copilot": true, - "openai": false, - "anthropic": false, - "openrouter": false - } - } - } -} diff --git a/openclaw-setup-copilot/config/model-schedule.config.json b/openclaw-setup-copilot/config/model-schedule.config.json deleted file mode 100644 index f96895b..0000000 --- a/openclaw-setup-copilot/config/model-schedule.config.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "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" -} diff --git a/openclaw-setup-copilot/docs/context/BOOT.md b/openclaw-setup-copilot/docs/context/BOOT.md deleted file mode 100644 index f68837a..0000000 --- a/openclaw-setup-copilot/docs/context/BOOT.md +++ /dev/null @@ -1,72 +0,0 @@ -# docs/context/BOOT.md - Target Computer Startup - -This boot file is for the work machine, not this machine. - -## 1) Verify services - -```bash -openclaw status --deep -``` - -## 2) Verify Copilot auth - -```bash -copilot auth status -``` - -If not authenticated: - -```bash -copilot auth login -``` - -## 3) Verify model routing - -```bash -openclaw models list -openclaw models status -``` - -Expected state: -- Active/default model is a `github-copilot/*` model. -- Fallbacks are `github-copilot/*` models only. - -## 4) Gateway and channels - -```bash -openclaw gateway restart -openclaw status --deep -``` - -Confirm channel health shows `OK`. - -## 5) Model budget guardrail - -```bash -launchctl print gui/$(id -u)/ai.openclaw.model-budget-guard -``` - -If missing, install on target machine: - -```bash -bash ./scripts/install_copilot_guardrails.sh -``` - -## 6) Copilot policy/auth guardrails - -```bash -launchctl print gui/$(id -u)/ai.openclaw.copilot-policy-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-auth-watchdog -launchctl print gui/$(id -u)/ai.openclaw.copilot-model-schedule-guard -``` - -Schedule expectation: -- `08:00-18:00` local: `paid` profile -- `18:00-08:00` local: `free` profile - -## 7) Hook status - -```bash -openclaw hooks list -openclaw hooks list --eligible -``` diff --git a/openclaw-setup-copilot/docs/context/HEARTBEAT.md b/openclaw-setup-copilot/docs/context/HEARTBEAT.md deleted file mode 100644 index 3d53d72..0000000 --- a/openclaw-setup-copilot/docs/context/HEARTBEAT.md +++ /dev/null @@ -1,10 +0,0 @@ -# docs/context/HEARTBEAT.md - -Run these checks only on the target work machine: - -- `openclaw status --deep` -- `openclaw models status` -- `copilot auth status` - -If all healthy and no action needed, reply: -`HEARTBEAT_OK` diff --git a/openclaw-setup-copilot/docs/context/IDENTITY.md b/openclaw-setup-copilot/docs/context/IDENTITY.md deleted file mode 100644 index 0c05dac..0000000 --- a/openclaw-setup-copilot/docs/context/IDENTITY.md +++ /dev/null @@ -1,9 +0,0 @@ -# docs/context/IDENTITY.md - Runtime Identity - -- Name: ClawCraft iOS -- Role: Senior iOS Engineer assistant -- Vibe: concise, pragmatic, architecture-first -- Focus: Swift, SwiftUI, refactoring, testing, clean architecture -- Signature: [ios-arch] - -Primary mission is engineering execution quality, not generic assistant chatter. diff --git a/openclaw-setup-copilot/docs/context/MEMORY.md b/openclaw-setup-copilot/docs/context/MEMORY.md deleted file mode 100644 index 5c63359..0000000 --- a/openclaw-setup-copilot/docs/context/MEMORY.md +++ /dev/null @@ -1,22 +0,0 @@ -# docs/context/MEMORY.md - Long-Term Context - -## User Context - -- Owner: Matt Bruce -- Prefers practical command-level guidance -- Wants local-first efficiency and provider flexibility - -## Technical Direction - -- Primary target: OpenClaw + GitHub Copilot CLI Enterprise on work machine -- Keep response quality tuned for iOS architecture and refactoring work - -## Known Lessons - -- Tool-capability mismatches can break Telegram/chat flows. -- Session resets (`/new`) reduce latency and token burn. -- Stable gateway launch settings and log paths matter on macOS. - -## Scope Guardrail - -This repository is now a setup guide template. Avoid changing runtime config on this current machine unless explicitly requested. diff --git a/openclaw-setup-copilot/docs/context/SOUL.md b/openclaw-setup-copilot/docs/context/SOUL.md deleted file mode 100644 index 127a2ed..0000000 --- a/openclaw-setup-copilot/docs/context/SOUL.md +++ /dev/null @@ -1,22 +0,0 @@ -# docs/context/SOUL.md - Operating Profile - -You are a Senior iOS Engineer assistant. - -## Standards - -- Be concrete and technically correct. -- Refactor toward clarity, maintainability, and testability. -- Prefer modern Swift and SwiftUI patterns. -- Keep explanations short unless deeper detail is requested. - -## Decision Style - -- Recommend practical paths. -- State tradeoffs clearly. -- Verify assumptions with evidence before advising. - -## Boundaries - -- Do not expose secrets. -- Ask before external actions. -- Avoid destructive operations without explicit approval. diff --git a/openclaw-setup-copilot/docs/context/TOOLS.md b/openclaw-setup-copilot/docs/context/TOOLS.md deleted file mode 100644 index cd8f234..0000000 --- a/openclaw-setup-copilot/docs/context/TOOLS.md +++ /dev/null @@ -1,121 +0,0 @@ -# docs/context/TOOLS.md - Command Reference (Target Work Machine) - -## GitHub Copilot CLI (Enterprise) - -Primary setup script: - -```bash -bash ./setup/setup_openclaw_copilot.sh -``` - -Custom locations (optional): - -```bash -OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot bash ./setup/setup_openclaw_copilot.sh -NPM_GLOBAL_PREFIX="$HOME/.npm-global" bash ./setup/setup_openclaw_copilot.sh -``` - -Install: - -```bash -brew install copilot-cli@prerelease -# or -npm install -g @github/copilot-cli -``` - -Authenticate: - -```bash -copilot auth login -copilot auth status -``` - -## OpenClaw Model Discovery and Routing - -```bash -openclaw models refresh -openclaw models list -openclaw models status -``` - -If `models refresh` is unavailable on your OpenClaw version, use `openclaw models list` and continue. - -## Lock to Copilot-only providers - -Preferred (if supported): -- `openclaw config patch '{...}'` - -Fallback command style: - -```bash -openclaw config set --json providers.github-copilot.enabled true -openclaw config set --json providers.openai.enabled false -openclaw config set --json providers.anthropic.enabled false -openclaw config set --json providers.openrouter.enabled false -``` - -## Health and Logs - -```bash -openclaw status --deep -openclaw logs --follow -openclaw gateway restart -``` - -## Model Budget Guardrail (Target Machine) - -Files: -- `config/model-budget-guard.config.json` -- `config/copilot-policy-guard.config.json` -- `config/copilot-auth-watchdog.config.json` -- `scripts/model_budget_guard.sh` -- `scripts/copilot_policy_guard.sh` -- `scripts/copilot_auth_watchdog.sh` -- `scripts/install_model_budget_guard_launchd.sh` -- `scripts/install_copilot_policy_guard_launchd.sh` -- `scripts/install_copilot_auth_watchdog_launchd.sh` -- `scripts/configure_copilot_guardrails_defaults.sh` -- `scripts/install_copilot_guardrails.sh` - -Configure + install: - -```bash -bash ./scripts/install_copilot_guardrails.sh -``` - -This command also runs: - -```bash -bash ./scripts/configure_copilot_guardrails_defaults.sh -``` - -Verify: - -```bash -launchctl print gui/$(id -u)/ai.openclaw.model-budget-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-policy-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-auth-watchdog -tail -n 30 /tmp/openclaw-model-budget-guard.log /tmp/openclaw-model-budget-guard.err.log -tail -n 30 /tmp/openclaw-copilot-policy-guard.log /tmp/openclaw-copilot-policy-guard.err.log -tail -n 30 /tmp/openclaw-copilot-auth-watchdog.log /tmp/openclaw-copilot-auth-watchdog.err.log -``` - -Behavior: -- warns when expensive model stays active -- auto-switches back to configured low model -- auto-fixes Copilot-only provider/model policy drift -- alerts on Copilot auth problems - -## Hooks (Recommended) - -```bash -openclaw hooks enable boot-md -openclaw hooks enable command-logger -openclaw hooks enable session-memory -openclaw hooks list -``` - -## Security - -- Never paste full API keys or bot tokens into chat/logs. -- Rotate secrets if exposed. diff --git a/openclaw-setup-copilot/docs/context/USER.md b/openclaw-setup-copilot/docs/context/USER.md deleted file mode 100644 index bb93a90..0000000 --- a/openclaw-setup-copilot/docs/context/USER.md +++ /dev/null @@ -1,38 +0,0 @@ -# docs/context/USER.md - Human Context - -- Name: `` -- Preferred name: `` -- Current objective: Copilot-only OpenClaw setup on work machine - -## Priorities - -- OpenClaw reliability -- Copilot Enterprise auth and model routing -- Senior iOS engineering persona quality -- Clear fallback strategy for provider/model issues - -## Working Style - -- Wants direct fixes and exact commands -- Comfortable in terminal workflows -- Values architecture/refactor quality over shortcuts - -## Secrets Inputs (Placeholders Only) - -Use this section for setup prompts. Do not commit real secrets. - -- `COPILOT_AUTH`: browser login required (`copilot auth login`) — no static token stored here -- `TELEGRAM_BOT_TOKEN`: `` -- `OPENCLAW_GATEWAY_TOKEN`: `` - -## Setup Prompt Checklist - -When assisting a new user, prompt for: - -1. Whether Telegram is needed (`yes/no`) -2. If yes, ask for `TELEGRAM_BOT_TOKEN` at runtime -3. Confirm Copilot browser login is completed - -Telegram clarification: -- Existing personal Telegram account is sufficient. -- No new phone number/user account is needed to run a bot. diff --git a/openclaw-setup-copilot/docs/operations/AI_SETUP_HANDOFF.md b/openclaw-setup-copilot/docs/operations/AI_SETUP_HANDOFF.md deleted file mode 100644 index b3914db..0000000 --- a/openclaw-setup-copilot/docs/operations/AI_SETUP_HANDOFF.md +++ /dev/null @@ -1,62 +0,0 @@ -# docs/operations/AI_SETUP_HANDOFF.md - -Give this file to an AI agent on the target machine. - -## Copy/Paste Prompt For AI - -```text -You are setting up this folder on this machine as a strict Copilot-only OpenClaw install. - -Follow docs/operations/WORK_SETUP_CHECKLIST.md exactly. -Also follow the constraints below: - -Constraints: -- Do NOT use Ollama. -- Do NOT enable non-Copilot providers. -- Use only github-copilot/* models. -- Fallbacks must be free/low-cost models only. -- Run commands in order and stop after each step to report status. -- If a step fails, provide exact fix and retry. - -Run in this order: -1) bash ./setup/setup_openclaw_copilot.sh -2) bash ./scripts/finalize_copilot_setup.sh - - if prompted, pause and wait for user to complete browser login - - if prompted for paid model, show model list to user and ask user to choose -3) openclaw status --deep - -After setup, verify and report: -- copilot auth status is healthy -- openclaw models status shows github-copilot/* primary -- fallbacks are low-cost only -- providers.github-copilot.enabled = true -- providers.openai.enabled = false -- providers.anthropic.enabled = false -- providers.openrouter.enabled = false -- launchd guards running: - - ai.openclaw.model-budget-guard - - ai.openclaw.copilot-policy-guard - - ai.openclaw.copilot-auth-watchdog - - ai.openclaw.copilot-model-schedule-guard -- schedule policy: - - paid profile during 08:00-18:00 local - - free profile during 18:00-08:00 local -- hooks enabled: - - boot-md - - command-logger - - session-memory - -If any check fails, fix it and rerun verification. -``` - -## Manual User Actions Expected - -- Complete enterprise login in browser when `finalize_copilot_setup.sh` opens `copilot auth login`. -- Approve enterprise/SSO/MFA prompts as required. - -## One-Line Start (for human) - -```bash -# open this file and copy the prompt to your AI agent -cat docs/operations/AI_SETUP_HANDOFF.md -``` diff --git a/openclaw-setup-copilot/docs/operations/WORK_SETUP_CHECKLIST.md b/openclaw-setup-copilot/docs/operations/WORK_SETUP_CHECKLIST.md deleted file mode 100644 index a9146bf..0000000 --- a/openclaw-setup-copilot/docs/operations/WORK_SETUP_CHECKLIST.md +++ /dev/null @@ -1,244 +0,0 @@ -# docs/operations/WORK_SETUP_CHECKLIST.md - -Use this checklist on the **target work computer only**. -Do not run these mutation steps on your current stable machine. - -## 0) Open terminal in this folder - -```bash -cd /path/to/openclaw-setup -``` - -If delegating to another AI assistant, point it to: -- `docs/operations/AI_SETUP_HANDOFF.md` - -## 1) Preflight - -```bash -uname -a -sw_vers -which brew || echo "brew missing" -which node || echo "node missing" -which npm || echo "npm missing" -``` - -## 2) Primary Copilot setup - -```bash -bash ./setup/setup_openclaw_copilot.sh -``` - -Optional custom locations: - -```bash -OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot bash ./setup/setup_openclaw_copilot.sh -NPM_GLOBAL_PREFIX="$HOME/.npm-global" bash ./setup/setup_openclaw_copilot.sh -``` - -Verify: - -```bash -which openclaw -openclaw --version -which copilot -copilot --version -``` - -## 3) Finalize setup in one command (recommended) - -```bash -bash ./scripts/finalize_copilot_setup.sh -``` - -Expected: -- Authenticated with enterprise-linked account -- Copilot models discovered -- If prompted, paid profile model selected from non-free candidates -- Guardrails installed + running -- Hooks enabled (`boot-md`, `command-logger`, `session-memory`) -- Gateway restarted - -If this step succeeds, you can skip to step 10. - -## 4) Manual fallback path (advanced, only if step 3 fails) - -If finalize fails due auth/browser flow, run: - -```bash -copilot auth login -copilot auth status -``` - -Then continue below. -## 5) Start/verify OpenClaw gateway - -```bash -openclaw gateway restart -openclaw status --deep -``` - -Expected: gateway reachable. - -## 6) Discover available models - -```bash -openclaw models refresh || true -openclaw models list -openclaw models status -``` - -Note: If `models refresh` is unsupported in your version, ignore and continue. - -How to choose from the list: - -- Pick a fast daily model as primary (usually Sonnet-Fast or Codex-Fast style naming). -- Pick only free-tier or lowest-cost fallbacks. -- Avoid premium fallbacks (Opus-class) in default routing. -- Keep model IDs exact from `openclaw models list`. - -Why this matters: - -- Better latency for normal work -- Better quality when complexity spikes -- Lower quota burn by not overusing heavyweight models -- Better uptime through fallback failover - -## 7) Set Copilot primary + fallbacks - -Replace models below with names from your `openclaw models list` output if needed. - -```bash -openclaw models set github-copilot/claude-sonnet-4.6 -openclaw models fallbacks clear -openclaw models fallbacks add github-copilot/ -openclaw models fallbacks add github-copilot/ -``` - -Verify: - -```bash -openclaw models status -``` - -Expected: - -- Default model is your fast daily Copilot model -- Fallback chain includes only free-tier or low-cost models -- Only `github-copilot/*` appears if strict enterprise policy is required - -## 8) Optional strict provider lock (Copilot-only) - -Run if your enterprise policy requires only Copilot provider traffic: - -```bash -openclaw config set --json providers.github-copilot.enabled true -openclaw config set --json providers.openai.enabled false -openclaw config set --json providers.anthropic.enabled false -openclaw config set --json providers.openrouter.enabled false -openclaw gateway restart -``` - -Verify: - -```bash -openclaw models list -openclaw models status -``` - -## 9) Configure + install Copilot guardrails (recommended) - -If step 3 already succeeded, this is already done. - -This one command auto-detects your available Copilot models, asks for paid model selection (interactive), picks low-cost free defaults, applies policy, and installs launchd guards: - -```bash -bash ./scripts/install_copilot_guardrails.sh -``` - -For unattended/non-interactive automation: - -```bash -PROMPT_FOR_PAID_MODEL=false bash ./scripts/install_copilot_guardrails.sh -``` - -3. Verify: - -```bash -launchctl print gui/$(id -u)/ai.openclaw.model-budget-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-policy-guard -launchctl print gui/$(id -u)/ai.openclaw.copilot-auth-watchdog -launchctl print gui/$(id -u)/ai.openclaw.copilot-model-schedule-guard -tail -n 30 /tmp/openclaw-model-budget-guard.log /tmp/openclaw-model-budget-guard.err.log -tail -n 30 /tmp/openclaw-copilot-policy-guard.log /tmp/openclaw-copilot-policy-guard.err.log -tail -n 30 /tmp/openclaw-copilot-auth-watchdog.log /tmp/openclaw-copilot-auth-watchdog.err.log -tail -n 30 /tmp/openclaw-copilot-model-schedule-guard.log /tmp/openclaw-copilot-model-schedule-guard.err.log -``` - -Why this matters: - -- User gets prompted when high model remains active -- Session is auto-switched back to lower model after timeout -- Copilot-only policy is auto-corrected if drift occurs -- Expired Copilot auth is surfaced quickly -- Work-hours/off-hours profile schedule is auto-enforced -- Protects enterprise quota and keeps routine latency low - -## 10) Enable recommended hooks - -If step 3 already succeeded, hooks were already enabled. - -```bash -openclaw hooks enable boot-md -openclaw hooks enable command-logger -openclaw hooks enable session-memory -openclaw hooks list -``` - -## 11) Persona/startup docs sanity - -Confirm these files exist in workspace root: - -```bash -ls -la AGENTS.md docs/context/BOOT.md docs/context/SOUL.md docs/context/IDENTITY.md docs/context/USER.md docs/context/TOOLS.md docs/operations/troubleshooting.md -``` - -## 12) Telegram/channel check (if used) - -Telegram account rule: -- No new personal Telegram account is required. -- Use your existing Telegram account and create a bot via `@BotFather`. -- Bot token is the only setup secret needed for Telegram. - -```bash -openclaw status --deep -``` - -Expected: channel `OK` and gateway reachable. - -## 13) First chat checks - -In your chat surface: - -1. `/new` -2. Ask: `reply with your active model and one sentence` - -Expected: response is fast and uses a `github-copilot/*` model. - -## 14) Daily operations - -```bash -openclaw status --deep -openclaw models status -copilot auth status -``` - -## 15) Fast failure recovery - -```bash -openclaw gateway restart -openclaw logs --follow -openclaw models status -copilot auth status -``` - -If still blocked, use `docs/operations/troubleshooting.md`. diff --git a/openclaw-setup-copilot/docs/operations/troubleshooting.md b/openclaw-setup-copilot/docs/operations/troubleshooting.md deleted file mode 100644 index 2dfa273..0000000 --- a/openclaw-setup-copilot/docs/operations/troubleshooting.md +++ /dev/null @@ -1,210 +0,0 @@ -# Troubleshooting - OpenClaw + Copilot Enterprise (Target Machine) - -This guide is for the work computer setup. - -## Quick triage - -```bash -openclaw status --deep -openclaw models status -copilot auth status -``` - -## 1) Copilot auth failure - -Symptoms: -- `copilot auth status` not authenticated -- prompts fail with auth errors - -Fix: - -```bash -copilot auth login -copilot auth status -``` - -Make sure browser login uses the enterprise-linked GitHub account. - -## 2) No Copilot model entitlement - -Symptoms: -- auth is valid but model usage denied - -Cause: -- org/enterprise policy does not permit Copilot CLI - -Fix: -- ask enterprise admin to enable Copilot CLI entitlement for your seat - -## 3) `Unknown model` in OpenClaw - -Fix: - -```bash -openclaw models refresh -openclaw models list -``` - -If `models refresh` is missing in your version, skip it and use `openclaw models list`. - -## 4) OpenClaw `config patch` not available - -Symptoms: -- guide references `openclaw config patch`, command not found - -Fix: -- use `openclaw config set --json ` commands instead -- use `openclaw models set` and `openclaw models fallbacks` commands for routing - -## 5) Still seeing non-Copilot providers - -Fix provider toggles: - -```bash -openclaw config set --json providers.github-copilot.enabled true -openclaw config set --json providers.openai.enabled false -openclaw config set --json providers.anthropic.enabled false -openclaw config set --json providers.openrouter.enabled false -openclaw gateway restart -``` - -## 6) Telegram/channel slow responses - -Fixes: -- start a fresh session with `/new` -- keep default model on a fast Copilot model -- verify gateway health and provider auth - -```bash -openclaw status --deep -openclaw models status -``` - -Telegram account confusion: -- You do not need a second Telegram user account. -- Keep your current personal Telegram account. -- Create/connect only the bot token from `@BotFather`. - -## 7) Cost and quota management - -- Use fast/cheap Copilot model as default -- Use `/new` for unrelated tasks -- Use compaction if available in your OpenClaw build - -## 8) Wrong model mix (common quality/latency issue) - -Symptoms: -- Replies are slow even when gateway is healthy -- Refactor suggestions are weak/inconsistent -- Quota burns too fast for routine tasks - -Cause: -- Heavy reasoning model set as default for all prompts -- No fallback diversity (all fast or all heavy) - -Fix: -1. Set a fast default model for day-to-day requests. -2. Keep fallbacks free-tier or low-cost only. -3. Remove premium fallback models from default routing. - -Then verify: - -```bash -openclaw models list -openclaw models status -``` - -## 9) High-model guardrail not prompting or not switching back - -Checks: - -```bash -launchctl print gui/$(id -u)/ai.openclaw.model-budget-guard -tail -n 100 /tmp/openclaw-model-budget-guard.log /tmp/openclaw-model-budget-guard.err.log -cat config/model-budget-guard.config.json -cat ~/Library/Application\ Support/openclaw-copilot-guard/model-budget-guard.config.json -``` - -Common fixes: -- Wrong model IDs in `highModels` - - Use exact IDs from `openclaw models list`. -- `lowModel` not available - - Set to a model your seat can access. -- Guard not installed/loaded - - Re-run `bash ./scripts/install_copilot_guardrails.sh`. -- Repo config changed but staged runtime is stale - - Re-run `bash ./scripts/install_copilot_guardrails.sh` to re-stage current files. -- Session key mismatch - - Keep `sessionKey` as `agent:main:main` unless you intentionally use another session. - -## 10) Copilot policy guard keeps fixing config unexpectedly - -Cause: -- `config/copilot-policy-guard.config.json` has `autoFix=true` and policy values that differ from your manual changes. - -Fix: -1. Edit `config/copilot-policy-guard.config.json`. -2. Set your intended `providerPolicy`, `desiredPrimaryModel`, and fallback rules. -3. If you want alert-only mode, set `autoFix` to `false`. - -Verify logs: - -```bash -tail -n 100 /tmp/openclaw-copilot-policy-guard.log /tmp/openclaw-copilot-policy-guard.err.log -cat ~/Library/Application\ Support/openclaw-copilot-guard/copilot-policy-guard.config.json -``` - -## 11) Manual model switch keeps changing back - -Cause: -- Schedule guard is enabled and re-applies the expected profile by time window. - - `08:00-18:00` -> paid profile - - `18:00-08:00` -> free profile - -Checks: - -```bash -launchctl print gui/$(id -u)/ai.openclaw.copilot-model-schedule-guard -tail -n 100 /tmp/openclaw-copilot-model-schedule-guard.log /tmp/openclaw-copilot-model-schedule-guard.err.log -cat config/model-schedule.config.json -cat config/model-profiles.config.json -cat ~/Library/Application\ Support/openclaw-copilot-guard/model-schedule.config.json -cat ~/Library/Application\ Support/openclaw-copilot-guard/model-profiles.config.json -``` - -Fixes: -- If behavior is correct, do nothing (schedule is enforcing policy). -- To temporarily hold a manual switch, disable schedule in `config/model-schedule.config.json` and re-run: - - `bash ./scripts/install_copilot_guardrails.sh` -- For a quick manual switch without live push: - - `bash ./scripts/model_profile_switch.sh free --no-live` -- If `profiles.paid.primary` / `profiles.free.primary` are empty, run: - - `bash ./scripts/finalize_copilot_setup.sh` - This populates `config/model-profiles.config.json` and restages launchd runtime configs. - -## 12) Copilot auth watchdog alerting repeatedly - -Checks: - -```bash -copilot auth status -openclaw models status --check -cat config/copilot-auth-watchdog.config.json -cat ~/Library/Application\ Support/openclaw-copilot-guard/copilot-auth-watchdog.config.json -``` - -Fixes: -- Re-authenticate with `copilot auth login`. -- Increase `minAlertIntervalMinutes` in `config/copilot-auth-watchdog.config.json`. -- If needed, temporarily disable watchdog by setting `enabled` to `false`. - -## 13) Recommended hooks not active - -Enable and verify: - -```bash -openclaw hooks enable boot-md -openclaw hooks enable command-logger -openclaw hooks enable session-memory -openclaw hooks list -``` diff --git a/openclaw-setup-copilot/memory/.gitkeep b/openclaw-setup-copilot/memory/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/openclaw-setup-copilot/scripts/configure_copilot_guardrails_defaults.sh b/openclaw-setup-copilot/scripts/configure_copilot_guardrails_defaults.sh deleted file mode 100755 index e528768..0000000 --- a/openclaw-setup-copilot/scripts/configure_copilot_guardrails_defaults.sh +++ /dev/null @@ -1,371 +0,0 @@ -#!/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) ]] -} - -prompt_for_paid_model() { - local default_model="$1" - shift - local -a candidates=("$@") - - if [[ ${#candidates[@]} -eq 0 ]]; then - echo "$default_model" - return 0 - fi - - echo "" >&2 - echo "[configure-guardrails] Choose paid profile primary model (non-free candidates):" >&2 - for i in "${!candidates[@]}"; do - local n=$((i + 1)) - local marker="" - if [[ "${candidates[$i]}" == "$default_model" ]]; then - marker=" (default)" - fi - printf " %d) %s%s\n" "$n" "${candidates[$i]}" "$marker" >&2 - done - printf "Select number [default=%s]: " "$default_model" >&2 - - local choice="" - if ! IFS= read -r choice; then - echo "" >&2 - echo "$default_model" - return 0 - fi - - if [[ -z "$choice" ]]; then - echo "$default_model" - return 0 - fi - - if [[ "$choice" =~ ^[0-9]+$ ]]; then - local idx=$((choice - 1)) - if (( idx >= 0 && idx < ${#candidates[@]} )); then - echo "${candidates[$idx]}" - return 0 - fi - fi - - echo "[configure-guardrails] Invalid selection '$choice'; using default: $default_model" >&2 - echo "$default_model" -} - -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 <&2 - if [[ -t 0 && -t 1 ]]; then - interactive_picker="true" - fi - ;; -esac - -if [[ "$interactive_picker" == "true" && ( ! -t 0 || ! -t 1 ) ]]; then - echo "[configure-guardrails] PROMPT_FOR_PAID_MODEL enabled but no interactive TTY; falling back to auto selection." >&2 - interactive_picker="false" -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 - -if [[ "$interactive_picker" == "true" && ${#high_models[@]} -gt 0 ]]; then - paid_model="$(prompt_for_paid_model "$paid_model" "${high_models[@]}")" - echo "[configure-guardrails] selected paid model: $paid_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" diff --git a/openclaw-setup-copilot/scripts/copilot_auth_watchdog.sh b/openclaw-setup-copilot/scripts/copilot_auth_watchdog.sh deleted file mode 100755 index 25ed28a..0000000 --- a/openclaw-setup-copilot/scripts/copilot_auth_watchdog.sh +++ /dev/null @@ -1,134 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -CONFIG_PATH="${AUTH_WATCHDOG_CONFIG:-$ROOT_DIR/config/copilot-auth-watchdog.config.json}" - -if ! command -v jq >/dev/null 2>&1; then - echo "[copilot-auth-watchdog] jq 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 -} - -now_ms() { - python3 - <<'PY' -import time -print(int(time.time()*1000)) -PY -} - -send_notice() { - local text="$1" - local last_channel="$2" - local last_to="$3" - - if [[ -z "$last_channel" || -z "$last_to" ]]; then - echo "[copilot-auth-watchdog] notice skipped (missing channel/target): $text" >&2 - return 0 - fi - - local target="$last_to" - if [[ "$target" == *:* ]]; then - target="${target#*:}" - fi - - openclaw message send \ - --channel "$last_channel" \ - --target "$target" \ - --message "$text" \ - >/dev/null 2>&1 || true -} - -if [[ ! -f "$CONFIG_PATH" ]]; then - echo "[copilot-auth-watchdog] missing config: $CONFIG_PATH" >&2 - exit 1 -fi - -enabled="$(jq -r '.enabled // true' "$CONFIG_PATH")" -if [[ "$enabled" != "true" ]]; then - exit 0 -fi - -session_key="$(jq -r '.sessionKey // "agent:main:main"' "$CONFIG_PATH")" -alert_interval_min="$(jq -r '.minAlertIntervalMinutes // 30' "$CONFIG_PATH")" -state_file_raw="$(jq -r '.stateFile // "~/.openclaw/copilot-auth-watchdog-state.json"' "$CONFIG_PATH")" -state_file="$(expand_tilde "$state_file_raw")" -check_model_status="$(jq -r '.checkOpenClawModelStatus // true' "$CONFIG_PATH")" - -state_dir="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" -sessions_file="$state_dir/agents/main/sessions/sessions.json" -last_channel="" -last_to="" -if [[ -r "$sessions_file" ]]; then - session_json="$(jq -c --arg key "$session_key" '.[$key] // {}' "$sessions_file" 2>/dev/null || true)" - if [[ -n "$session_json" && "$session_json" != "{}" ]]; then - last_channel="$(jq -r '.lastChannel // empty' <<<"$session_json")" - last_to="$(jq -r '.lastTo // empty' <<<"$session_json")" - fi -fi - -declare -a issues=() - -if ! command -v copilot >/dev/null 2>&1; then - issues+=("copilot CLI not installed; run setup_openclaw_copilot.sh") -else - set +e - copilot_out="$(copilot auth status 2>&1)" - copilot_rc=$? - set -e - - if [[ $copilot_rc -ne 0 ]]; then - issues+=("copilot auth status failed; run: copilot auth login") - elif echo "$copilot_out" | grep -Eiq 'not authenticated|not logged|login required|expired|unauthorized|invalid'; then - issues+=("copilot auth not healthy; run: copilot auth login") - fi -fi - -if [[ "$check_model_status" == "true" ]]; then - if ! command -v openclaw >/dev/null 2>&1; then - issues+=("openclaw CLI not installed") - else - if ! openclaw models status --check >/dev/null 2>&1; then - issues+=("openclaw model auth check failed; run: openclaw models status --json and copilot auth login") - fi - fi -fi - -if [[ ${#issues[@]} -eq 0 ]]; then - exit 0 -fi - -mkdir -p "$(dirname "$state_file")" -if [[ ! -f "$state_file" ]]; then - printf '{}\n' > "$state_file" -fi - -state_json="$(cat "$state_file")" -last_alert_at="$(jq -r --arg key "$session_key" '.[$key].lastAlertAt // 0' <<<"$state_json")" -if [[ ! "$last_alert_at" =~ ^[0-9]+$ ]]; then - last_alert_at=0 -fi - -now="$(now_ms)" -interval_ms=$((alert_interval_min * 60 * 1000)) -if (( now - last_alert_at < interval_ms )); then - exit 0 -fi - -summary="Copilot auth watchdog alert: ${issues[*]}" -echo "[copilot-auth-watchdog] $summary" -send_notice "$summary" "$last_channel" "$last_to" - -state_json="$(jq --arg key "$session_key" --argjson now "$now" '.[$key].lastAlertAt=$now' <<<"$state_json")" -printf '%s\n' "$state_json" > "$state_file" diff --git a/openclaw-setup-copilot/scripts/copilot_policy_guard.sh b/openclaw-setup-copilot/scripts/copilot_policy_guard.sh deleted file mode 100755 index ab3080b..0000000 --- a/openclaw-setup-copilot/scripts/copilot_policy_guard.sh +++ /dev/null @@ -1,235 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" -CONFIG_PATH="${POLICY_GUARD_CONFIG:-$ROOT_DIR/config/copilot-policy-guard.config.json}" - -if ! command -v jq >/dev/null 2>&1; then - echo "[copilot-policy-guard] jq is required" >&2 - exit 1 -fi -if ! command -v openclaw >/dev/null 2>&1; then - echo "[copilot-policy-guard] 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 -} - -now_ms() { - python3 - <<'PY' -import time -print(int(time.time()*1000)) -PY -} - -send_notice() { - local text="$1" - local last_channel="$2" - local last_to="$3" - - if [[ -z "$last_channel" || -z "$last_to" ]]; then - echo "[copilot-policy-guard] notice skipped (missing channel/target): $text" >&2 - return 0 - fi - - local target="$last_to" - if [[ "$target" == *:* ]]; then - target="${target#*:}" - fi - - openclaw message send \ - --channel "$last_channel" \ - --target "$target" \ - --message "$text" \ - >/dev/null 2>&1 || true -} - -if [[ ! -f "$CONFIG_PATH" ]]; then - echo "[copilot-policy-guard] missing config: $CONFIG_PATH" >&2 - exit 1 -fi - -enabled="$(jq -r '.enabled // true' "$CONFIG_PATH")" -if [[ "$enabled" != "true" ]]; then - exit 0 -fi - -auto_fix="$(jq -r '.autoFix // true' "$CONFIG_PATH")" -session_key="$(jq -r '.sessionKey // "agent:main:main"' "$CONFIG_PATH")" -alert_interval_min="$(jq -r '.minAlertIntervalMinutes // 20' "$CONFIG_PATH")" -state_file_raw="$(jq -r '.stateFile // "~/.openclaw/copilot-policy-guard-state.json"' "$CONFIG_PATH")" -state_file="$(expand_tilde "$state_file_raw")" -required_primary_prefix="$(jq -r '.requiredPrimaryPrefix // "github-copilot/"' "$CONFIG_PATH")" -required_fallback_prefix="$(jq -r '.requiredFallbackPrefix // "github-copilot/"' "$CONFIG_PATH")" -desired_primary_model="$(jq -r '.desiredPrimaryModel // empty' "$CONFIG_PATH")" -enforce_allowlist="$(jq -r '.enforceFallbackAllowlist // false' "$CONFIG_PATH")" - -state_dir="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" -sessions_file="$state_dir/agents/main/sessions/sessions.json" -last_channel="" -last_to="" -if [[ -r "$sessions_file" ]]; then - session_json="$(jq -c --arg key "$session_key" '.[$key] // {}' "$sessions_file" 2>/dev/null || true)" - if [[ -n "$session_json" && "$session_json" != "{}" ]]; then - last_channel="$(jq -r '.lastChannel // empty' <<<"$session_json")" - last_to="$(jq -r '.lastTo // empty' <<<"$session_json")" - fi -fi - -declare -a issues=() -declare -a fixes=() - -models_json="$(openclaw models status --json 2>/dev/null || true)" -if [[ -z "$models_json" ]]; then - issues+=("openclaw models status --json failed") -else - default_model="$(jq -r '.defaultModel // empty' <<<"$models_json")" - - if [[ -n "$default_model" && "$default_model" != ${required_primary_prefix}* ]]; then - issues+=("primary model is not Copilot: $default_model") - if [[ "$auto_fix" == "true" && -n "$desired_primary_model" ]]; then - if openclaw models set "$desired_primary_model" >/dev/null 2>&1; then - fixes+=("set primary model to $desired_primary_model") - else - issues+=("failed to set primary model to $desired_primary_model") - fi - fi - fi - - fallbacks=() - while IFS= read -r fb; do - [[ -z "$fb" ]] && continue - fallbacks+=("$fb") - done < <(jq -r '.fallbacks[]? // empty' <<<"$models_json") - bad_prefix=0 - bad_allowlist=0 - for fb in "${fallbacks[@]}"; do - if [[ "$fb" != ${required_fallback_prefix}* ]]; then - bad_prefix=1 - issues+=("fallback is not Copilot: $fb") - fi - done - - if [[ "$enforce_allowlist" == "true" ]]; then - allowed_fallbacks=() - while IFS= read -r af; do - [[ -z "$af" ]] && continue - allowed_fallbacks+=("$af") - done < <(jq -r '.allowedFallbacks[]? // empty' "$CONFIG_PATH") - if [[ ${#allowed_fallbacks[@]} -gt 0 ]]; then - for fb in "${fallbacks[@]}"; do - found=0 - for af in "${allowed_fallbacks[@]}"; do - if [[ "$fb" == "$af" ]]; then - found=1 - break - fi - done - if [[ $found -eq 0 ]]; then - bad_allowlist=1 - issues+=("fallback not in allowlist: $fb") - fi - done - fi - fi - - if [[ "$auto_fix" == "true" && ( $bad_prefix -eq 1 || $bad_allowlist -eq 1 ) ]]; then - desired_fallbacks=() - - if [[ "$enforce_allowlist" == "true" ]]; then - while IFS= read -r af; do - [[ -n "$af" ]] && desired_fallbacks+=("$af") - done < <(jq -r '.allowedFallbacks[]? // empty' "$CONFIG_PATH") - fi - - if [[ ${#desired_fallbacks[@]} -eq 0 ]]; then - for fb in "${fallbacks[@]}"; do - if [[ "$fb" == ${required_fallback_prefix}* ]]; then - desired_fallbacks+=("$fb") - fi - done - fi - - if openclaw models fallbacks clear >/dev/null 2>&1; then - fixes+=("cleared fallback list") - for fb in "${desired_fallbacks[@]}"; do - if openclaw models fallbacks add "$fb" >/dev/null 2>&1; then - fixes+=("added fallback $fb") - else - issues+=("failed to add fallback $fb") - fi - done - else - issues+=("failed to clear fallback list") - fi - fi -fi - -while IFS='=' read -r provider desired; do - [[ -z "$provider" ]] && continue - desired_bool="false" - if [[ "$desired" == "true" ]]; then - desired_bool="true" - fi - - current="$(openclaw config get "providers.${provider}.enabled" 2>/dev/null || true)" - current_trim="$(printf '%s' "$current" | tr -d '[:space:]')" - - if [[ "$current_trim" != "$desired_bool" ]]; then - issues+=("provider policy drift: providers.${provider}.enabled expected ${desired_bool}, got ${current_trim:-unset}") - if [[ "$auto_fix" == "true" ]]; then - if openclaw config set --json "providers.${provider}.enabled" "$desired_bool" >/dev/null 2>&1; then - fixes+=("set providers.${provider}.enabled=${desired_bool}") - else - issues+=("failed to set providers.${provider}.enabled=${desired_bool}") - fi - fi - fi -done < <(jq -r '.providerPolicy // {} | to_entries[] | "\(.key)=\(.value)"' "$CONFIG_PATH") - -if [[ ${#issues[@]} -eq 0 && ${#fixes[@]} -eq 0 ]]; then - exit 0 -fi - -mkdir -p "$(dirname "$state_file")" -if [[ ! -f "$state_file" ]]; then - printf '{}\n' > "$state_file" -fi - -state_json="$(cat "$state_file")" -last_alert_at="$(jq -r --arg key "$session_key" '.[$key].lastAlertAt // 0' <<<"$state_json")" -if [[ ! "$last_alert_at" =~ ^[0-9]+$ ]]; then - last_alert_at=0 -fi - -now="$(now_ms)" -interval_ms=$((alert_interval_min * 60 * 1000)) -should_alert="false" -if (( now - last_alert_at >= interval_ms )); then - should_alert="true" -fi - -summary="" -if [[ ${#fixes[@]} -gt 0 ]]; then - summary="Copilot policy guard auto-fixed: ${fixes[*]}" -else - summary="Copilot policy drift detected: ${issues[*]}" -fi - -echo "[copilot-policy-guard] $summary" - -if [[ "$should_alert" == "true" ]]; then - send_notice "$summary" "$last_channel" "$last_to" - state_json="$(jq --arg key "$session_key" --argjson now "$now" '.[$key].lastAlertAt=$now' <<<"$state_json")" - printf '%s\n' "$state_json" > "$state_file" -fi diff --git a/openclaw-setup-copilot/scripts/finalize_copilot_setup.sh b/openclaw-setup-copilot/scripts/finalize_copilot_setup.sh deleted file mode 100755 index 276cd47..0000000 --- a/openclaw-setup-copilot/scripts/finalize_copilot_setup.sh +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" - -log_info() { echo "[finalize] $*"; } -log_warn() { echo "[finalize] WARN: $*" >&2; } -log_err() { echo "[finalize] ERROR: $*" >&2; } - -require_cmd() { - local cmd="$1" - if ! command -v "$cmd" >/dev/null 2>&1; then - log_err "Missing required command: $cmd" - exit 1 - fi -} - -copilot_authed() { - copilot auth status >/dev/null 2>&1 -} - -refresh_models() { - openclaw models refresh >/dev/null 2>&1 || true -} - -copilot_model_count() { - openclaw models list 2>/dev/null \ - | awk 'NR>1 && /^github-copilot\// {count++} END {print count+0}' -} - -require_cmd openclaw -require_cmd copilot -require_cmd jq - -if ! copilot_authed; then - log_warn "Copilot auth is not active." - if [[ -t 0 ]]; then - log_info "Launching interactive login: copilot auth login" - copilot auth login - else - log_err "Non-interactive shell cannot complete browser login." - log_err "Run: copilot auth login" - exit 1 - fi -fi - -if ! copilot_authed; then - log_err "Copilot auth still not active after login." - log_err "Run 'copilot auth status' and resolve auth issues, then retry." - exit 1 -fi - -log_info "Refreshing model catalog..." -refresh_models - -count="$(copilot_model_count)" -if [[ "$count" -eq 0 ]]; then - log_warn "No github-copilot models detected yet. Restarting gateway and retrying once." - openclaw gateway restart >/dev/null 2>&1 || true - sleep 1 - refresh_models - count="$(copilot_model_count)" -fi - -if [[ "$count" -eq 0 ]]; then - log_err "No github-copilot models available to configure." - log_err "Check entitlement/auth, then rerun this script." - openclaw models list || true - exit 1 -fi - -log_info "Detected $count Copilot model(s). Installing guardrails + model profiles..." -bash "$SCRIPT_DIR/install_copilot_guardrails.sh" - -log_info "Enabling recommended hooks..." -openclaw hooks enable boot-md >/dev/null 2>&1 || true -openclaw hooks enable command-logger >/dev/null 2>&1 || true -openclaw hooks enable session-memory >/dev/null 2>&1 || true - -log_info "Restarting gateway..." -openclaw gateway restart >/dev/null 2>&1 || true - -log_info "Final status checks:" -copilot auth status || true -openclaw models status || true - -for label in \ - ai.openclaw.model-budget-guard \ - ai.openclaw.copilot-policy-guard \ - ai.openclaw.copilot-auth-watchdog \ - ai.openclaw.copilot-model-schedule-guard; do - if launchctl print "gui/$(id -u)/$label" >/dev/null 2>&1; then - echo "[finalize] launchd OK: $label" - else - echo "[finalize] launchd WARN: $label not loaded" - fi -done - -log_info "Done. Copilot setup is fully configured." diff --git a/openclaw-setup-copilot/scripts/install_copilot_auth_watchdog_launchd.sh b/openclaw-setup-copilot/scripts/install_copilot_auth_watchdog_launchd.sh deleted file mode 100755 index 5d55bdd..0000000 --- a/openclaw-setup-copilot/scripts/install_copilot_auth_watchdog_launchd.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" - -if ! command -v jq >/dev/null 2>&1; then - echo "[install-copilot-auth-watchdog] jq is required" >&2 - exit 1 -fi - -LABEL="ai.openclaw.copilot-auth-watchdog" -PLIST_PATH="$HOME/Library/LaunchAgents/$LABEL.plist" -STAGE_DIR="${MODEL_GUARD_STAGE_DIR:-$HOME/Library/Application Support/openclaw-copilot-guard}" -STAGE_SCRIPTS_DIR="$STAGE_DIR/scripts" -STAGE_CONFIG="$STAGE_DIR/copilot-auth-watchdog.config.json" -AUTH_WATCHDOG_CONFIG="${AUTH_WATCHDOG_CONFIG:-$STAGE_CONFIG}" -INTERVAL_SECONDS="${INTERVAL_SECONDS:-300}" - -mkdir -p "$STAGE_SCRIPTS_DIR" -cp "$ROOT_DIR/scripts/copilot_auth_watchdog.sh" "$STAGE_SCRIPTS_DIR/copilot_auth_watchdog.sh" -jq \ - --arg state "$STAGE_DIR/copilot-auth-watchdog-state.json" \ - '.stateFile=$state' \ - "$ROOT_DIR/config/copilot-auth-watchdog.config.json" > "$STAGE_CONFIG" -chmod +x "$STAGE_SCRIPTS_DIR/copilot_auth_watchdog.sh" - -cat > "$PLIST_PATH" < - - - - Label - $LABEL - - ProgramArguments - - /bin/bash - $STAGE_SCRIPTS_DIR/copilot_auth_watchdog.sh - - - EnvironmentVariables - - PATH - /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - AUTH_WATCHDOG_CONFIG - $AUTH_WATCHDOG_CONFIG - - - RunAtLoad - - - StartInterval - $INTERVAL_SECONDS - - StandardOutPath - /tmp/openclaw-copilot-auth-watchdog.log - - StandardErrorPath - /tmp/openclaw-copilot-auth-watchdog.err.log - - -PLIST - -launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true -launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" -launchctl kickstart -k "gui/$(id -u)/$LABEL" - -cat </dev/null 2>&1; then - echo "[install-copilot-policy-guard] jq is required" >&2 - exit 1 -fi - -LABEL="ai.openclaw.copilot-policy-guard" -PLIST_PATH="$HOME/Library/LaunchAgents/$LABEL.plist" -STAGE_DIR="${MODEL_GUARD_STAGE_DIR:-$HOME/Library/Application Support/openclaw-copilot-guard}" -STAGE_SCRIPTS_DIR="$STAGE_DIR/scripts" -STAGE_CONFIG="$STAGE_DIR/copilot-policy-guard.config.json" -POLICY_GUARD_CONFIG="${POLICY_GUARD_CONFIG:-$STAGE_CONFIG}" -INTERVAL_SECONDS="${INTERVAL_SECONDS:-180}" - -mkdir -p "$STAGE_SCRIPTS_DIR" -cp "$ROOT_DIR/scripts/copilot_policy_guard.sh" "$STAGE_SCRIPTS_DIR/copilot_policy_guard.sh" -jq \ - --arg state "$STAGE_DIR/copilot-policy-guard-state.json" \ - '.stateFile=$state' \ - "$ROOT_DIR/config/copilot-policy-guard.config.json" > "$STAGE_CONFIG" -chmod +x "$STAGE_SCRIPTS_DIR/copilot_policy_guard.sh" - -cat > "$PLIST_PATH" < - - - - Label - $LABEL - - ProgramArguments - - /bin/bash - $STAGE_SCRIPTS_DIR/copilot_policy_guard.sh - - - EnvironmentVariables - - PATH - /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - POLICY_GUARD_CONFIG - $POLICY_GUARD_CONFIG - - - RunAtLoad - - - StartInterval - $INTERVAL_SECONDS - - StandardOutPath - /tmp/openclaw-copilot-policy-guard.log - - StandardErrorPath - /tmp/openclaw-copilot-policy-guard.err.log - - -PLIST - -launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true -launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" -launchctl kickstart -k "gui/$(id -u)/$LABEL" - -cat </dev/null 2>&1; then - echo "[install-model-budget-guard] jq is required" >&2 - exit 1 -fi - -LABEL="ai.openclaw.model-budget-guard" -PLIST_PATH="$HOME/Library/LaunchAgents/$LABEL.plist" -STAGE_DIR="${MODEL_GUARD_STAGE_DIR:-$HOME/Library/Application Support/openclaw-copilot-guard}" -STAGE_SCRIPTS_DIR="$STAGE_DIR/scripts" -STAGE_CONFIG="$STAGE_DIR/model-budget-guard.config.json" -MODEL_GUARD_CONFIG="${MODEL_GUARD_CONFIG:-$STAGE_CONFIG}" -INTERVAL_SECONDS="${INTERVAL_SECONDS:-120}" - -mkdir -p "$STAGE_SCRIPTS_DIR" -cp "$ROOT_DIR/scripts/model_budget_guard.sh" "$STAGE_SCRIPTS_DIR/model_budget_guard.sh" -jq \ - --arg state "$STAGE_DIR/model-budget-guard-state.json" \ - '.stateFile=$state' \ - "$ROOT_DIR/config/model-budget-guard.config.json" > "$STAGE_CONFIG" -chmod +x "$STAGE_SCRIPTS_DIR/model_budget_guard.sh" - -cat > "$PLIST_PATH" < - - - - Label - $LABEL - - ProgramArguments - - /bin/bash - $STAGE_SCRIPTS_DIR/model_budget_guard.sh - - - EnvironmentVariables - - PATH - /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - MODEL_GUARD_CONFIG - $MODEL_GUARD_CONFIG - - - RunAtLoad - - - StartInterval - $INTERVAL_SECONDS - - StandardOutPath - /tmp/openclaw-model-budget-guard.log - - StandardErrorPath - /tmp/openclaw-model-budget-guard.err.log - - -PLIST - -launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true -launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" -launchctl kickstart -k "gui/$(id -u)/$LABEL" - -cat </dev/null 2>&1; then - echo "[install-model-schedule-guard] jq is required" >&2 - exit 1 -fi - -LABEL="ai.openclaw.copilot-model-schedule-guard" -PLIST_PATH="$HOME/Library/LaunchAgents/$LABEL.plist" -STAGE_DIR="${MODEL_GUARD_STAGE_DIR:-$HOME/Library/Application Support/openclaw-copilot-guard}" -STAGE_SCRIPTS_DIR="$STAGE_DIR/scripts" -STAGE_SCHEDULE_CONFIG="$STAGE_DIR/model-schedule.config.json" -STAGE_PROFILES_CONFIG="$STAGE_DIR/model-profiles.config.json" -STAGE_POLICY_CONFIG="$STAGE_DIR/copilot-policy-guard.config.json" -MODEL_SCHEDULE_CONFIG="${MODEL_SCHEDULE_CONFIG:-$STAGE_SCHEDULE_CONFIG}" -INTERVAL_SECONDS="${INTERVAL_SECONDS:-300}" - -mkdir -p "$STAGE_SCRIPTS_DIR" -cp "$ROOT_DIR/scripts/model_schedule_guard.sh" "$STAGE_SCRIPTS_DIR/model_schedule_guard.sh" -cp "$ROOT_DIR/scripts/model_profile_switch.sh" "$STAGE_SCRIPTS_DIR/model_profile_switch.sh" -cp "$ROOT_DIR/config/model-profiles.config.json" "$STAGE_PROFILES_CONFIG" -jq \ - --arg state "$STAGE_DIR/model-schedule-state.json" \ - '.stateFile=$state' \ - "$ROOT_DIR/config/model-schedule.config.json" > "$STAGE_SCHEDULE_CONFIG" -chmod +x "$STAGE_SCRIPTS_DIR/model_schedule_guard.sh" "$STAGE_SCRIPTS_DIR/model_profile_switch.sh" - -cat > "$PLIST_PATH" < - - - - Label - $LABEL - - ProgramArguments - - /bin/bash - $STAGE_SCRIPTS_DIR/model_schedule_guard.sh - - - EnvironmentVariables - - PATH - /opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - MODEL_SCHEDULE_CONFIG - $MODEL_SCHEDULE_CONFIG - MODEL_PROFILES_CONFIG - $STAGE_PROFILES_CONFIG - POLICY_GUARD_CONFIG - $STAGE_POLICY_CONFIG - - - RunAtLoad - - - StartInterval - $INTERVAL_SECONDS - - StandardOutPath - /tmp/openclaw-copilot-model-schedule-guard.log - - StandardErrorPath - /tmp/openclaw-copilot-model-schedule-guard.err.log - - -PLIST - -launchctl bootout "gui/$(id -u)/$LABEL" 2>/dev/null || true -launchctl bootstrap "gui/$(id -u)" "$PLIST_PATH" -launchctl kickstart -k "gui/$(id -u)/$LABEL" - -cat </dev/null 2>&1; then - echo "[model-guard] jq is required" >&2 - exit 1 -fi -if ! command -v openclaw >/dev/null 2>&1; then - echo "[model-guard] 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 -} - -safe_now_ms() { - python3 - <<'PY' -import time -print(int(time.time()*1000)) -PY -} - -send_notice() { - local text="$1" - local last_channel="$2" - local last_to="$3" - - if [[ -z "$last_channel" || -z "$last_to" ]]; then - echo "[model-guard] notice skipped (missing channel/target): $text" >&2 - return 0 - fi - - local target="$last_to" - if [[ "$target" == *:* ]]; then - target="${target#*:}" - fi - - openclaw message send \ - --channel "$last_channel" \ - --target "$target" \ - --message "$text" \ - >/dev/null 2>&1 || true -} - -if [[ ! -f "$CONFIG_PATH" ]]; then - echo "[model-guard] missing config: $CONFIG_PATH" >&2 - exit 1 -fi - -enabled="$(jq -r '.enabled // true' "$CONFIG_PATH")" -if [[ "$enabled" != "true" ]]; then - exit 0 -fi - -session_key="$(jq -r '.sessionKey // "agent:main:main"' "$CONFIG_PATH")" -low_model="$(jq -r '.lowModel // empty' "$CONFIG_PATH")" -warn_after_min="$(jq -r '.warnAfterMinutes // 2' "$CONFIG_PATH")" -revert_after_min="$(jq -r '.revertAfterMinutes // 45' "$CONFIG_PATH")" -min_warn_interval_min="$(jq -r '.minWarnIntervalMinutes // 20' "$CONFIG_PATH")" -state_file_raw="$(jq -r '.stateFile // "~/.openclaw/model-budget-guard-state.json"' "$CONFIG_PATH")" -state_file="$(expand_tilde "$state_file_raw")" - -if [[ -z "$low_model" ]]; then - echo "[model-guard] lowModel must be set" >&2 - exit 1 -fi - -state_dir="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}" -sessions_file="$state_dir/agents/main/sessions/sessions.json" - -if [[ ! -r "$sessions_file" ]]; then - echo "[model-guard] sessions file not found: $sessions_file" >&2 - exit 0 -fi - -session_json="$(jq -c --arg key "$session_key" '.[$key] // {}' "$sessions_file" 2>/dev/null || true)" -if [[ -z "$session_json" || "$session_json" == "{}" ]]; then - exit 0 -fi - -session_id="$(jq -r '.sessionId // empty' <<<"$session_json")" -updated_at="$(jq -r '.updatedAt // 0' <<<"$session_json")" -model_raw="$(jq -r '.model // empty' <<<"$session_json")" -provider_raw="$(jq -r '.provider // empty' <<<"$session_json")" -last_channel="$(jq -r '.lastChannel // empty' <<<"$session_json")" -last_to="$(jq -r '.lastTo // empty' <<<"$session_json")" - -if [[ -z "$model_raw" ]]; then - exit 0 -fi - -model_full="$model_raw" -if [[ "$model_raw" != */* && -n "$provider_raw" && "$provider_raw" != "null" ]]; then - model_full="$provider_raw/$model_raw" -fi - -high_match="$(jq -r --arg m "$model_full" '.highModels // [] | index($m) != null' "$CONFIG_PATH")" -if [[ "$high_match" != "true" ]]; then - exit 0 -fi - -if [[ ! "$updated_at" =~ ^[0-9]+$ ]]; then - exit 0 -fi - -now_ms="$(safe_now_ms)" -age_ms=$((now_ms - updated_at)) -if (( age_ms < 0 )); then age_ms=0; fi -warn_after_ms=$((warn_after_min * 60 * 1000)) -revert_after_ms=$((revert_after_min * 60 * 1000)) -min_warn_interval_ms=$((min_warn_interval_min * 60 * 1000)) - -mkdir -p "$(dirname "$state_file")" -if [[ ! -f "$state_file" ]]; then - cat > "$state_file" <<'JSON' -{} -JSON -fi - -state_json="$(cat "$state_file")" -last_warned_model="$(jq -r --arg key "$session_key" '.[$key].lastWarnedModel // empty' <<<"$state_json")" -last_warned_session="$(jq -r --arg key "$session_key" '.[$key].lastWarnedSessionId // empty' <<<"$state_json")" -last_warn_at="$(jq -r --arg key "$session_key" '.[$key].lastWarnAt // 0' <<<"$state_json")" -last_revert_at="$(jq -r --arg key "$session_key" '.[$key].lastRevertAt // 0' <<<"$state_json")" - -should_warn="false" -if (( age_ms >= warn_after_ms )); then - if [[ "$last_warned_model" != "$model_full" || "$last_warned_session" != "$session_id" ]]; then - should_warn="true" - elif [[ "$last_warn_at" =~ ^[0-9]+$ ]] && (( now_ms - last_warn_at >= min_warn_interval_ms )); then - should_warn="true" - fi -fi - -if [[ "$should_warn" == "true" ]]; then - send_notice "Heads up: high-cost model active ($model_full). Switch back after heavy work: /model $low_model" "$last_channel" "$last_to" - state_json="$(jq \ - --arg key "$session_key" \ - --arg model "$model_full" \ - --arg sid "$session_id" \ - --argjson now "$now_ms" \ - '.[$key].lastWarnedModel=$model | .[$key].lastWarnedSessionId=$sid | .[$key].lastWarnAt=$now' \ - <<<"$state_json")" -fi - -if (( age_ms >= revert_after_ms )); then - can_revert="true" - if [[ "$last_revert_at" =~ ^[0-9]+$ ]] && (( now_ms - last_revert_at < min_warn_interval_ms )); then - can_revert="false" - fi - - if [[ "$can_revert" == "true" && -n "$session_id" ]]; then - python3 - "$session_id" "$low_model" <<'PY' -import subprocess -import sys - -session_id = sys.argv[1] -low_model = sys.argv[2] -cmd = [ - "openclaw", - "agent", - "--session-id", session_id, - "--channel", "last", - "--message", f"/model {low_model}", -] -try: - subprocess.run( - cmd, - stdout=subprocess.DEVNULL, - stderr=subprocess.DEVNULL, - check=False, - timeout=20, - ) -except subprocess.TimeoutExpired: - pass -PY - - send_notice "Auto-switched back to $low_model to avoid high-model quota burn. Use high model only for deep tasks." "$last_channel" "$last_to" - - state_json="$(jq \ - --arg key "$session_key" \ - --arg model "$low_model" \ - --arg sid "$session_id" \ - --argjson now "$now_ms" \ - '.[$key].lastRevertAt=$now | .[$key].lastWarnedModel=$model | .[$key].lastWarnedSessionId=$sid | .[$key].lastWarnAt=$now' \ - <<<"$state_json")" - fi -fi - -printf '%s\n' "$state_json" > "$state_file" diff --git a/openclaw-setup-copilot/scripts/model_profile_switch.sh b/openclaw-setup-copilot/scripts/model_profile_switch.sh deleted file mode 100755 index 1505ab3..0000000 --- a/openclaw-setup-copilot/scripts/model_profile_switch.sh +++ /dev/null @@ -1,186 +0,0 @@ -#!/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}" -POLICY_CONFIG_PATH="${POLICY_GUARD_CONFIG:-$ROOT_DIR/config/copilot-policy-guard.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 [--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" 2>/dev/null || true -} - -sync_policy_config() { - local primary="$1" - shift - local -a fb_models=("$@") - - if [[ ! -f "$POLICY_CONFIG_PATH" ]]; then - return 0 - fi - - local fallbacks_json - if [[ ${#fb_models[@]} -eq 0 ]]; then - fallbacks_json="[]" - else - fallbacks_json="$(printf '%s\n' "${fb_models[@]}" | jq -R . | jq -s .)" - fi - - if jq \ - --arg primary "$primary" \ - --argjson fallbacks "$fallbacks_json" \ - '.desiredPrimaryModel=$primary | .allowedFallbacks=$fallbacks | .enforceFallbackAllowlist=true' \ - "$POLICY_CONFIG_PATH" > "$POLICY_CONFIG_PATH.tmp"; then - mv "$POLICY_CONFIG_PATH.tmp" "$POLICY_CONFIG_PATH" || true - else - rm -f "$POLICY_CONFIG_PATH.tmp" - fi -} - -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 // "(unset)") (\(.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 configured" >&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 - 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 - [[ -z "$provider" || -z "$enabled" ]] && continue - 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 - -sync_policy_config "$primary" "${fallbacks[@]}" - -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 diff --git a/openclaw-setup-copilot/scripts/model_schedule_guard.sh b/openclaw-setup-copilot/scripts/model_schedule_guard.sh deleted file mode 100755 index 1d84041..0000000 --- a/openclaw-setup-copilot/scripts/model_schedule_guard.sh +++ /dev/null @@ -1,118 +0,0 @@ -#!/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" diff --git a/openclaw-setup-copilot/setup/setup_openclaw_copilot.sh b/openclaw-setup-copilot/setup/setup_openclaw_copilot.sh deleted file mode 100755 index 5761e1d..0000000 --- a/openclaw-setup-copilot/setup/setup_openclaw_copilot.sh +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -# Optional overrides: -# OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot bash ./setup/setup_openclaw_copilot.sh -# NPM_GLOBAL_PREFIX="$HOME/.npm-global" bash ./setup/setup_openclaw_copilot.sh -# OPENCLAW_DATA_TARGET=/Volumes/Data/openclaw-copilot NPM_GLOBAL_PREFIX="$HOME/.npm-global" bash ./setup/setup_openclaw_copilot.sh -OPENCLAW_DATA_TARGET="${OPENCLAW_DATA_TARGET:-}" -NPM_GLOBAL_PREFIX="${NPM_GLOBAL_PREFIX:-}" - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" - -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' - -log_info() { echo -e "${GREEN}$*${NC}"; } -log_warn() { echo -e "${YELLOW}$*${NC}"; } -log_err() { echo -e "${RED}$*${NC}"; } - -require_cmd() { - local cmd="$1" - if ! command -v "$cmd" >/dev/null 2>&1; then - log_err "ERROR: Missing required command: $cmd" - exit 1 - fi -} - -node_major_version() { - node -v 2>/dev/null | sed 's/^v//' | cut -d. -f1 -} - -expand_tilde() { - local p="$1" - if [[ "$p" == "~" ]]; then - echo "$HOME" - elif [[ "$p" == "~/"* ]]; then - echo "$HOME/${p#~/}" - else - echo "$p" - fi -} - -link_data_dir() { - local source="$1" - local target="$2" - local label="$3" - - mkdir -p "$target" - - if [ -L "$source" ]; then - local current_link - current_link="$(readlink "$source")" - if [ "$current_link" != "$target" ]; then - rm "$source" - ln -s "$target" "$source" - log_info "${label}: updated symlink ${source} -> ${target}" - else - log_info "${label}: symlink already correct (${source} -> ${target})" - fi - return 0 - fi - - if [ -d "$source" ]; then - log_warn "${label}: migrating existing ${source} data to ${target}..." - if command -v rsync >/dev/null 2>&1; then - rsync -a "$source"/ "$target"/ - else - cp -a "$source"/. "$target"/ - fi - rm -rf "$source" - elif [ -e "$source" ]; then - log_err "ERROR: ${source} exists but is not a directory/symlink. Resolve manually." - exit 1 - fi - - ln -s "$target" "$source" - log_info "${label}: symlink created ${source} -> ${target}" -} - -install_npm_global() { - local pkg="$1" - require_cmd npm - if [[ -n "$NPM_GLOBAL_PREFIX" ]]; then - mkdir -p "$NPM_GLOBAL_PREFIX" - npm install -g --prefix "$NPM_GLOBAL_PREFIX" "$pkg" - else - npm install -g "$pkg" - fi -} - -if [[ -n "$OPENCLAW_DATA_TARGET" ]]; then - OPENCLAW_DATA_TARGET="$(expand_tilde "$OPENCLAW_DATA_TARGET")" -fi -if [[ -n "$NPM_GLOBAL_PREFIX" ]]; then - NPM_GLOBAL_PREFIX="$(expand_tilde "$NPM_GLOBAL_PREFIX")" -fi - -if [[ -n "$NPM_GLOBAL_PREFIX" ]]; then - export PATH="$NPM_GLOBAL_PREFIX/bin:$PATH" -fi - -echo -e "${GREEN}=== OpenClaw + GitHub Copilot CLI Setup ===${NC}" -echo "Current time: $(date)" -if [[ -n "$OPENCLAW_DATA_TARGET" ]]; then - echo "OpenClaw data target: $OPENCLAW_DATA_TARGET" -fi -if [[ -n "$NPM_GLOBAL_PREFIX" ]]; then - echo "npm global prefix: $NPM_GLOBAL_PREFIX" -fi -echo "" - -require_cmd curl - -# Step 1: Install / verify Node.js >= 22 -need_node_install=false -if ! command -v node >/dev/null 2>&1; then - need_node_install=true -else - node_major="$(node_major_version || true)" - if ! echo "$node_major" | grep -Eq '^[0-9]+$' || [ "$node_major" -lt 22 ]; then - need_node_install=true - fi -fi - -if [ "$need_node_install" = true ]; then - log_warn "Node.js >= 22 not found. Installing via Homebrew..." - if ! command -v brew >/dev/null 2>&1; then - log_err "Homebrew not found. Install it first:" - echo '/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"' - exit 1 - fi - brew install node -fi -log_info "Node.js ready ($(node -v))." - -# Step 2: Install / verify OpenClaw -if ! command -v openclaw >/dev/null 2>&1; then - log_warn "OpenClaw not found. Installing via npm..." - require_cmd npm - install_npm_global openclaw -else - log_info "OpenClaw already installed ($(openclaw --version))." -fi - -# Step 3: Install / verify GitHub Copilot CLI -if ! command -v copilot >/dev/null 2>&1; then - if command -v brew >/dev/null 2>&1; then - log_warn "Copilot CLI not found. Installing prerelease via Homebrew..." - brew install copilot-cli@prerelease || { - log_warn "Homebrew install failed, falling back to npm package..." - install_npm_global @github/copilot-cli - } - else - log_warn "Homebrew not found. Installing Copilot CLI via npm..." - install_npm_global @github/copilot-cli - fi -else - log_info "Copilot CLI already installed ($(copilot --version 2>/dev/null || echo present))." -fi - -if [[ -n "$OPENCLAW_DATA_TARGET" ]]; then - link_data_dir "$HOME/.openclaw" "$OPENCLAW_DATA_TARGET" "OpenClaw" -else - log_info "OpenClaw data location unchanged (~/.openclaw). Set OPENCLAW_DATA_TARGET to move it." -fi - -FINALIZE_SCRIPT="$SCRIPT_DIR/../scripts/finalize_copilot_setup.sh" -if [[ -x "$FINALIZE_SCRIPT" ]]; then - if copilot auth status >/dev/null 2>&1; then - log_info "Copilot auth already active. Running finalize flow now..." - if ! bash "$FINALIZE_SCRIPT"; then - log_warn "Finalize flow failed. Re-run manually after checking auth/models:" - echo " bash ./scripts/finalize_copilot_setup.sh" - fi - else - log_warn "Final setup step still needed after login:" - echo " bash ./scripts/finalize_copilot_setup.sh" - fi -fi - -echo "" -log_info "Setup complete (Copilot-first)." -echo "" -echo "Next steps (target machine):" -echo "1. Run one-command finalize (recommended):" -echo " bash ./scripts/finalize_copilot_setup.sh" -echo "2. If finalize cannot open browser login, authenticate first:" -echo " copilot auth login" -echo " copilot auth status" -echo " bash ./scripts/finalize_copilot_setup.sh" -echo "3. Verify:" -echo " openclaw status --deep" -echo " openclaw models status" -if [[ -n "$NPM_GLOBAL_PREFIX" ]]; then - echo "" - echo "If this is a new shell, ensure PATH includes your npm prefix bin:" - echo " export PATH=\"$NPM_GLOBAL_PREFIX/bin:\$PATH\"" -fi