Last active
March 29, 2026 22:30
-
-
Save ts-sz/caa22322ecb73274f68f69a25f047536 to your computer and use it in GitHub Desktop.
Convert /v1/models response to OpenClaw models config block
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Convert /v1/models response to OpenClaw models config block. | |
| Usage: | |
| # Print standalone models JSON to stdout: | |
| python3 models_to_config.py | |
| # Merge into an existing config file (replaces agents.defaults.models in-place): | |
| python3 models_to_config.py --config config.json | |
| Environment variables (used as fallback if not set below): | |
| CLIPROXY_URL Base URL of the proxy (e.g. https://my-proxy.example.com) | |
| CLIPROXY_APIKEY Bearer token for authentication | |
| CLIPROXY_PREFIX Prefix for model keys (e.g. "my-provider") | |
| """ | |
| import argparse | |
| import json | |
| import os | |
| import re | |
| import sys | |
| import urllib.request | |
| import urllib.error | |
| # Set these directly, or leave empty to read from environment variables | |
| CLIPROXY_URL = "" | |
| CLIPROXY_APIKEY = "" | |
| CLIPROXY_PREFIX = "" | |
| def format_alias(model_id: str, owned_by: str) -> str: | |
| """Build a human-readable alias from a model ID and its owner.""" | |
| # Keep only the last segment (e.g. "openrouter/claude-xxx" -> "claude-xxx") | |
| name = model_id.split("/")[-1] | |
| # Split on dashes and underscores into individual tokens | |
| parts = re.split(r"[-_]", name) | |
| words = [] | |
| for p in parts: | |
| if not p: | |
| continue | |
| if re.match(r"^\d", p): # version number: append to previous word | |
| if words: | |
| words[-1] = words[-1] + " " + p | |
| else: | |
| words.append(p) | |
| continue | |
| else: | |
| words.append(p.capitalize()) | |
| alias_name = " ".join(words) | |
| return f"{alias_name} [{owned_by}]" | |
| def fetch_models(base_url: str, api_key: str) -> dict: | |
| """Fetch /v1/models from the proxy and return the JSON response.""" | |
| # Strip trailing /v1/models (or /v1) in case the user included it in the URL | |
| base_url = re.sub(r"/v1(/models)?/?$", "", base_url.rstrip("/")) | |
| url = f"{base_url}/v1/models" | |
| print(f"→ Fetching {url}", file=sys.stderr) | |
| req = urllib.request.Request(url) | |
| req.add_header("Authorization", f"Bearer {api_key}") | |
| with urllib.request.urlopen(req) as resp: | |
| return json.loads(resp.read()) | |
| def main(): | |
| """Fetch models from the proxy and print or merge the config.""" | |
| parser = argparse.ArgumentParser(description="Convert /v1/models to OpenClaw config.") | |
| parser.add_argument("--config", "-c", help="Existing config JSON file to update in-place") | |
| args = parser.parse_args() | |
| # Resolve config: in-script values take priority, then env vars | |
| base_url = CLIPROXY_URL or os.environ.get("CLIPROXY_URL", "") | |
| api_key = CLIPROXY_APIKEY or os.environ.get("CLIPROXY_APIKEY", "") | |
| prefix = CLIPROXY_PREFIX or os.environ.get("CLIPROXY_PREFIX", "") | |
| if not base_url or not api_key or not prefix: | |
| sys.exit("Error: CLIPROXY_URL, CLIPROXY_APIKEY, and CLIPROXY_PREFIX must be set (in script or as env vars).") | |
| # Fetch the model list from the proxy | |
| data = fetch_models(base_url, api_key) | |
| # Build the models config mapping | |
| models = {} | |
| for m in data.get("data", []): | |
| model_id = m["id"] | |
| owned_by = m.get("owned_by", "unknown") | |
| key = f"{prefix}/{model_id}" | |
| alias = format_alias(model_id, owned_by) | |
| models[key] = {"alias": alias} | |
| if args.config: | |
| # Merge into existing config file, replacing agents.defaults.models | |
| with open(args.config) as f: | |
| config = json.load(f) | |
| config["agents"]["defaults"]["models"] = models | |
| with open(args.config, "w") as f: | |
| json.dump(config, f, indent=2, ensure_ascii=False) | |
| f.write("\n") | |
| print(f"Updated agents.defaults.models in {args.config} ({len(models)} models)") | |
| else: | |
| # Print standalone JSON to stdout | |
| output = {"models": models} | |
| print(json.dumps(output, indent=2, ensure_ascii=False)) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment