# Model Selector FastAPI dashboard for browsing and editing the model/provider config in `~/.openclaw/openclaw.json`. It is intentionally small: - canonical config stays in `/home/lucky/.openclaw/openclaw.json` - provider snapshots are cached locally under `data/model-cache/` - alias edits land in `agents.defaults.models..alias` - the server runs on port `3300` ## What it shows - configured models from the canonical OpenClaw config - live provider catalogs from OpenAI, Groq, and OpenRouter - aliases, reasoning flags, context window, max tokens, and provider metadata when present - missing capabilities as `—`, rather than guessing ## Files That Matter - [`model_selector/main.py`](model_selector/main.py) - FastAPI app and API routes - [`model_selector/config.py`](model_selector/config.py) - canonical config read/write logic - [`model_selector/providers.py`](model_selector/providers.py) - provider adapters and config serialization - [`model_selector/service.py`](model_selector/service.py) - dashboard state assembly - [`model_selector/cache.py`](model_selector/cache.py) - local JSON snapshot cache - [`run.sh`](run.sh) - start the app - [`killserver.sh`](killserver.sh) - clear stale listeners on port `3300` - [`restart.sh`](restart.sh) - kill then start - [`tests.sh`](tests.sh) - run the test suite ## Quick Start ```bash # Create a local virtualenv and install dependencies python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt # Configure API keys if you want live provider catalogs cp .env.example .env # Start the dashboard ./run.sh ``` Open `http://localhost:3300`. ## Configuration The app reads these environment variables: | Variable | Default | Purpose | | --- | --- | --- | | `OPENCLAW_CONFIG_PATH` | `/home/lucky/.openclaw/openclaw.json` | Canonical config file | | `MODEL_SELECTOR_PORT` | `3300` | Web server port | | `MODEL_SELECTOR_HOST` | `0.0.0.0` | Bind host | | `MODEL_SELECTOR_REFRESH_INTERVAL` | `1800` | Live provider refresh interval, in seconds | | `MODEL_SELECTOR_CACHE_DIR` | `data/model-cache` | Local JSON snapshot directory | | `OPENAI_API_KEY` | unset | OpenAI live catalog access | | `GROQ_API_KEY` | unset | Groq live catalog access | | `OPENROUTER_API_KEY` | unset | OpenRouter live catalog access | The config schema is intentionally narrow: ```json { "models": { "providers": { "openai": { "models": [ { "id": "gpt-4o", "name": "GPT-4o", "reasoning": false, "input": ["text"], "contextWindow": 128000, "maxTokens": 16000 } ] } } }, "agents": { "defaults": { "models": { "openai/gpt-4o": { "alias": "my-favorite" } } } } } ``` ## API - `GET /` - dashboard UI - `GET /api/state` - full dashboard state - `GET /api/config` - config path and configured models - `POST /api/alias` - update alias for a configured model - `POST /api/config/models/add` - add a provider model to config - `POST /api/config/models/delete` - remove a configured model - `POST /api/refresh` - force a live provider refresh ## Testing Use the repo-local test runner: ```bash bash tests.sh ``` That script uses `.venv` when present and falls back to `python3 -m pytest -q` if not. The tests use temporary config fixtures and do not touch the live `~/.openclaw/openclaw.json`. ## Notes - Runtime cache files under `data/model-cache/` are local-only and ignored by git. - The dashboard keeps the configured-model view separate from provider catalogs on purpose. - OpenRouter config writes only include parameters that the dashboard knows are valid.