#!/usr/bin/env python3 """Centralized channel definitions for NewAPI. All channel configs live here so that add/recreate/fix scripts share a single source of truth. Keys are read from environment variables when available, falling back to the known hardcoded values. """ import os from pathlib import Path from newapi_client import ( TYPE_OPENAI, TYPE_CUSTOM, TYPE_ANTHROPIC, TYPE_ZHIPU_V4, TYPE_MINIMAX, TYPE_OLLAMA, TYPE_VOLC_ENGINE, ) # ── Paths ──────────────────────────────────────────────────────── _SCRIPTS_DIR = Path(__file__).parent _ZHIPUAI_KEYS_FILE = _SCRIPTS_DIR / "llm-key-hunter" / "results" / "live" / "china" / "zhipuai" / "keys.txt" def _env_or(default_key, env_var): """Read from env, fall back to hardcoded default.""" return os.environ.get(env_var, default_key) # ── VolcanoArk model lists ─────────────────────────────────────── _VOLC_MODELS_FULL = ( "doubao-seed-2-0-pro-260215,doubao-seed-2-0-lite-260215," "doubao-seed-2-0-mini-260215,doubao-seed-2-1-pro-260628," "doubao-seed-2-1-turbo-260628,doubao-seed-1-6-250615," "doubao-seed-1-6-251015,doubao-seed-1-6-flash-250615," "doubao-seed-1-6-flash-250828,deepseek-v4-flash-260425," "deepseek-v4-pro-260425,glm-5-2-260617" ) _VOLC_MODELS_MID = ( "doubao-seed-2-0-pro-260215,doubao-seed-2-0-lite-260215," "doubao-seed-2-1-pro-260628,doubao-seed-1-6-250615," "doubao-seed-1-6-251015,doubao-seed-1-6-flash-250615," "doubao-seed-1-6-flash-250828,deepseek-v4-flash-260425," "deepseek-v4-pro-260425" ) _VOLC_MODELS_MIN = "doubao-seed-2-0-pro-260215" # ── VolcanoArk keys ────────────────────────────────────────────── VOLC_ARK_KEYS = [ ("209bcbe8-3cdf-4397-b13c-2323e481af82", _VOLC_MODELS_FULL), ("5cf8e2f7-8465-4ccc-bf84-e32f05be0fb4", _VOLC_MODELS_FULL), ("6ef45f7f-1d82-4d34-80c0-c70180bd59fc", _VOLC_MODELS_MID), ("60186d5d-95bf-4265-beaa-4c3842e10802", _VOLC_MODELS_MIN), ] # ── Base URLs ──────────────────────────────────────────────────── URL_ZHIPUAI = "https://open.bigmodel.cn/api/paas/v4" URL_ZHIPUAI_FULL = f"{URL_ZHIPUAI}/chat/completions" URL_VOLC_ARK = "https://ark.cn-beijing.volces.com/api/v3" URL_VOLC_ARK_FULL = f"{URL_VOLC_ARK}/chat/completions" URL_VOLC_ARK_CODING = "https://ark.cn-beijing.volces.com/api/coding" URL_MINIMAX = "https://api.minimaxi.com/v1" URL_MINIMAX_FULL = f"{URL_MINIMAX}/chat/completions" URL_BAIDU = "https://qianfan.baidubce.com/v2/coding" URL_STEPFUN = "https://api.stepfun.com/step_plan" URL_OLLAMA = "https://api.ollama.com" URL_XKIRO = "https://api.xkiro.com/v1" # ── Channel builders ───────────────────────────────────────────── def _load_zhipuai_keys(): """Load ZhipuAI keys from the live keys file.""" with open(_ZHIPUAI_KEYS_FILE) as f: return [line.strip() for line in f if line.strip()] def build_zhipuai(channel_type=TYPE_OPENAI, full_url=False): """Build the ZhipuAI channel config (multi-key pool).""" keys = _load_zhipuai_keys() base = URL_ZHIPUAI_FULL if full_url else URL_ZHIPUAI return { "type": channel_type, "name": "ZhipuAI-Pool", "key": "\n".join(keys), "base_url": base, "models": "glm-4v-flash,glm-4-flash,glm-4,glm-4-plus,glm-4-long,glm-4.5,glm-4.6,glm-4.7", "group": "default", }, len(keys) def build_volcano_ark(channel_type=TYPE_OPENAI, full_url=False): """Build VolcanoArk channel configs (one per key).""" base = URL_VOLC_ARK_FULL if full_url else URL_VOLC_ARK channels = [] for i, (key, models) in enumerate(VOLC_ARK_KEYS, 1): channels.append({ "type": channel_type, "name": f"VolcanoArk-K{i}", "key": key, "base_url": base, "models": models, "group": "default", }) return channels def build_volcano_ark_coding(): """Build the VolcanoArk CodingPlan channel (Anthropic-compatible).""" return { "type": TYPE_ANTHROPIC, "name": "VolcanoArk-CodingPlan", "key": VOLC_ARK_KEYS[0][0], "base_url": URL_VOLC_ARK_CODING, "models": "claude-sonnet-4-6,claude-opus-4-6,claude-haiku-3-5,claude-3-5-haiku-20241022,claude-3-haiku-20240307,claude-sonnet-4-20250514,claude-opus-4-20250514,claude-3-7-sonnet-20250219,doubao-seed-2-0-pro-260215", "group": "default", } def build_minimax(channel_type=TYPE_OPENAI, full_url=False): """Build the MiniMax channel config.""" base = URL_MINIMAX_FULL if full_url else URL_MINIMAX return { "type": channel_type, "name": "MiniMax", "key": _env_or( "sk-cp-WCVxiI5uFbxuIydEUdgZ9ejiC89_csqs0uE9QJUct4k148OhpwYYtu1QdeTDH7shuOyn4kD831hXibst3CmswaZYLhBZE4UOT5qLslMn8R5IYooGzdTajkA", "MINIMAX_KEY", ), "base_url": base, "models": "MiniMax-M2.5", "group": "default", } def build_baidu_qianfan(): """Build the Baidu Qianfan Coding Plan channel.""" return { "type": TYPE_OPENAI, "name": "BaiduQianfan-Coding", "key": _env_or( "bce-v3/ALTAKSP-XiBlXOXnSzzyMFAB5UaJg/935c59dfdc8ce7142c02fe6fea4a3017a0f311a6", "BAIDU_QIANFAN_KEY", ), "base_url": URL_BAIDU, "models": "qianfan-code-latest,deepseek-v4-flash,deepseek-v4-pro,deepseek-v3.2,glm-5.1,glm-5", "group": "default", } def build_stepfun(): """Build the StepFun channel (Anthropic-compatible).""" return { "type": TYPE_ANTHROPIC, "name": "StepFun", "key": _env_or( "2abjHPkM2rgD6d8EzWBMPNzwAtALMtgvqUB9jYTPqgr5ouZzxdPOmgTYlTPuDs2xa", "STEPFUN_KEY", ), "base_url": URL_STEPFUN, "models": "step-3.7-flash,step-router-v1,step-3.5-flash-2603", "group": "default", } def build_ollama_cloud(): """Build the Ollama Cloud channel.""" return { "type": TYPE_OLLAMA, "name": "OllamaCloud", "key": _env_or( "a3f899539f3c4effad78e220462be7a6.fVn8luLNb206KKkpYgAs9JRR", "OLLAMA_KEY", ), "base_url": URL_OLLAMA, "models": "gemma4:31b,gpt-oss:20b,gpt-oss:120b,nemotron-3-nano:30b", "group": "default", } def build_xkiro(key=None): """Build the xKiro channel (OpenAI-compatible aggregator). Models use provider/model format (like OpenRouter): anthropic/claude-sonnet-4-5, anthropic/claude-opus-4-5, openai/gpt-4o, etc. """ return { "type": TYPE_OPENAI, "name": "XKiro", "key": key or _env_or("", "XKIRO_KEY"), "base_url": URL_XKIRO, "models": "anthropic/claude-sonnet-4-5,anthropic/claude-opus-4-5,openai/gpt-4o,openai/gpt-4o-mini", "group": "default", } # ── Fix table (for fix_channels.py) ────────────────────────────── FIX_TABLE = [ # (id, name, new_type, base_url) (6, "ZhipuAI-Pool", TYPE_OPENAI, URL_ZHIPUAI), (7, "VolcanoArk-K1", TYPE_OPENAI, URL_VOLC_ARK), (8, "VolcanoArk-K2", TYPE_OPENAI, URL_VOLC_ARK), (9, "VolcanoArk-K3", TYPE_OPENAI, URL_VOLC_ARK), (10, "VolcanoArk-K4", TYPE_OPENAI, URL_VOLC_ARK), (12, "MiniMax", TYPE_OPENAI, URL_MINIMAX), ]