Initial commit
This commit is contained in:
141
skills/config.generate.router/generate_router.py
Executable file
141
skills/config.generate.router/generate_router.py
Executable file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Skill: config.generate.router
|
||||
Generates Claude Code Router configuration
|
||||
"""
|
||||
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any
|
||||
|
||||
|
||||
class RouterConfigGenerator:
|
||||
"""Generates router configuration for Claude Code"""
|
||||
|
||||
CONFIG_VERSION = "1.0.0"
|
||||
|
||||
def generate(
|
||||
self,
|
||||
llm_backends: List[Dict[str, Any]],
|
||||
routing_rules: Dict[str, Any],
|
||||
config_options: Dict[str, Any] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate router configuration matching Claude Code Router schema
|
||||
|
||||
Args:
|
||||
llm_backends: List of backend provider configs
|
||||
routing_rules: Dictionary of routing context mappings
|
||||
config_options: Optional config settings (LOG, API_TIMEOUT_MS, etc.)
|
||||
|
||||
Returns:
|
||||
Complete router configuration in Claude Code Router format
|
||||
"""
|
||||
options = config_options or {}
|
||||
|
||||
config = {
|
||||
"Providers": self._format_providers(llm_backends),
|
||||
"Router": self._format_router(routing_rules)
|
||||
}
|
||||
|
||||
# Add optional configuration fields if provided
|
||||
if "LOG" in options:
|
||||
config["LOG"] = options["LOG"]
|
||||
if "LOG_LEVEL" in options:
|
||||
config["LOG_LEVEL"] = options["LOG_LEVEL"]
|
||||
if "API_TIMEOUT_MS" in options:
|
||||
config["API_TIMEOUT_MS"] = options["API_TIMEOUT_MS"]
|
||||
if "NON_INTERACTIVE_MODE" in options:
|
||||
config["NON_INTERACTIVE_MODE"] = options["NON_INTERACTIVE_MODE"]
|
||||
if "APIKEY" in options:
|
||||
config["APIKEY"] = options["APIKEY"]
|
||||
if "PROXY_URL" in options:
|
||||
config["PROXY_URL"] = options["PROXY_URL"]
|
||||
if "CUSTOM_ROUTER_PATH" in options:
|
||||
config["CUSTOM_ROUTER_PATH"] = options["CUSTOM_ROUTER_PATH"]
|
||||
if "HOST" in options:
|
||||
config["HOST"] = options["HOST"]
|
||||
|
||||
return config
|
||||
|
||||
def _format_providers(self, backends: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
|
||||
"""Format provider configurations for Claude Code Router"""
|
||||
formatted = []
|
||||
for backend in backends:
|
||||
entry = {
|
||||
"name": backend["name"],
|
||||
"api_base_url": backend["api_base_url"],
|
||||
"models": backend["models"]
|
||||
}
|
||||
|
||||
# Only include API key if present (not for local providers)
|
||||
if backend.get("api_key"):
|
||||
entry["api_key"] = backend["api_key"]
|
||||
|
||||
# Include transformer if specified
|
||||
if backend.get("transformer"):
|
||||
entry["transformer"] = backend["transformer"]
|
||||
|
||||
# Include any additional provider-specific settings
|
||||
for key, value in backend.items():
|
||||
if key not in ["name", "api_base_url", "models", "api_key", "transformer"]:
|
||||
entry[key] = value
|
||||
|
||||
formatted.append(entry)
|
||||
|
||||
return formatted
|
||||
|
||||
def _format_router(self, routing_rules: Dict[str, Any]) -> Dict[str, str]:
|
||||
"""
|
||||
Format routing rules for Claude Code Router
|
||||
|
||||
Converts from object format to "provider,model" string format:
|
||||
Input: {"provider": "openrouter", "model": "claude-3.5-sonnet"}
|
||||
Output: "openrouter,claude-3.5-sonnet"
|
||||
"""
|
||||
formatted = {}
|
||||
for context, rule in routing_rules.items():
|
||||
provider = rule["provider"]
|
||||
model = rule["model"]
|
||||
# Claude Code Router expects "provider,model" string format
|
||||
formatted[context] = f"{provider},{model}"
|
||||
|
||||
return formatted
|
||||
|
||||
|
||||
def main():
|
||||
"""CLI entrypoint"""
|
||||
if len(sys.argv) < 2:
|
||||
print(json.dumps({
|
||||
"error": "Usage: generate_router.py <input_json>"
|
||||
}))
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
input_data = json.loads(sys.argv[1])
|
||||
|
||||
generator = RouterConfigGenerator()
|
||||
config = generator.generate(
|
||||
llm_backends=input_data.get("llm_backends", []),
|
||||
routing_rules=input_data.get("routing_rules", {}),
|
||||
config_options=input_data.get("config_options", {})
|
||||
)
|
||||
|
||||
print(json.dumps(config, indent=2))
|
||||
sys.exit(0)
|
||||
|
||||
except json.JSONDecodeError as e:
|
||||
print(json.dumps({
|
||||
"error": f"Invalid JSON: {e}"
|
||||
}))
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(json.dumps({
|
||||
"error": f"Generation error: {e}"
|
||||
}))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user