diff --git a/hermes_cli/main.py b/hermes_cli/main.py index 32d90ac6a..e6cb01a2b 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -784,6 +784,7 @@ def cmd_model(args): "opencode-go": "OpenCode Go", "ai-gateway": "AI Gateway", "kilocode": "Kilo Code", + "alibaba": "Alibaba Cloud (DashScope)", "custom": "Custom endpoint", } active_label = provider_labels.get(active, active) @@ -807,6 +808,7 @@ def cmd_model(args): ("opencode-zen", "OpenCode Zen (35+ curated models, pay-as-you-go)"), ("opencode-go", "OpenCode Go (open models, $10/month subscription)"), ("ai-gateway", "AI Gateway (Vercel — 200+ models, pay-per-use)"), + ("alibaba", "Alibaba Cloud / DashScope (Qwen models, Anthropic-compatible)"), ] # Add user-defined custom providers from config.yaml @@ -875,7 +877,7 @@ def cmd_model(args): _model_flow_anthropic(config, current_model) elif selected_provider == "kimi-coding": _model_flow_kimi(config, current_model) - elif selected_provider in ("zai", "minimax", "minimax-cn", "kilocode", "opencode-zen", "opencode-go", "ai-gateway"): + elif selected_provider in ("zai", "minimax", "minimax-cn", "kilocode", "opencode-zen", "opencode-go", "ai-gateway", "alibaba"): _model_flow_api_key_provider(config, selected_provider, current_model) diff --git a/hermes_cli/setup.py b/hermes_cli/setup.py index a79844def..b635377f5 100644 --- a/hermes_cli/setup.py +++ b/hermes_cli/setup.py @@ -738,6 +738,7 @@ def setup_model_provider(config: dict): "Kilo Code (Kilo Gateway API)", "Anthropic (Claude models — API key or Claude Code subscription)", "AI Gateway (Vercel — 200+ models, pay-per-use)", + "Alibaba Cloud / DashScope (Qwen models via Anthropic-compatible API)", "OpenCode Zen (35+ curated models, pay-as-you-go)", "OpenCode Go (open models, $10/month subscription)", ] @@ -1313,7 +1314,39 @@ def setup_model_provider(config: dict): _update_config_for_provider("ai-gateway", pconfig.inference_base_url, default_model="anthropic/claude-opus-4.6") _set_model_provider(config, "ai-gateway", pconfig.inference_base_url) - elif provider_idx == 11: # OpenCode Zen + elif provider_idx == 11: # Alibaba Cloud / DashScope + selected_provider = "alibaba" + print() + print_header("Alibaba Cloud / DashScope API Key") + pconfig = PROVIDER_REGISTRY["alibaba"] + print_info(f"Provider: {pconfig.name}") + print_info("Get your API key at: https://modelstudio.console.alibabacloud.com/") + print() + + existing_key = get_env_value("DASHSCOPE_API_KEY") + if existing_key: + print_info(f"Current: {existing_key[:8]}... (configured)") + if prompt_yes_no("Update API key?", False): + new_key = prompt(" DashScope API key", password=True) + if new_key: + save_env_value("DASHSCOPE_API_KEY", new_key) + print_success("DashScope API key updated") + else: + new_key = prompt(" DashScope API key", password=True) + if new_key: + save_env_value("DASHSCOPE_API_KEY", new_key) + print_success("DashScope API key saved") + else: + print_warning("Skipped - agent won't work without an API key") + + # Clear custom endpoint vars if switching + if existing_custom: + save_env_value("OPENAI_BASE_URL", "") + save_env_value("OPENAI_API_KEY", "") + _update_config_for_provider("alibaba", pconfig.inference_base_url, default_model="qwen3.5-plus") + _set_model_provider(config, "alibaba", pconfig.inference_base_url) + + elif provider_idx == 12: # OpenCode Zen selected_provider = "opencode-zen" print() print_header("OpenCode Zen API Key") @@ -1346,7 +1379,7 @@ def setup_model_provider(config: dict): _set_model_provider(config, "opencode-zen", pconfig.inference_base_url) selected_base_url = pconfig.inference_base_url - elif provider_idx == 12: # OpenCode Go + elif provider_idx == 13: # OpenCode Go selected_provider = "opencode-go" print() print_header("OpenCode Go API Key") @@ -1379,7 +1412,7 @@ def setup_model_provider(config: dict): _set_model_provider(config, "opencode-go", pconfig.inference_base_url) selected_base_url = pconfig.inference_base_url - # else: provider_idx == 13 (Keep current) — only shown when a provider already exists + # else: provider_idx == 14 (Keep current) — only shown when a provider already exists # Normalize "keep current" to an explicit provider so downstream logic # doesn't fall back to the generic OpenRouter/static-model path. if selected_provider is None: diff --git a/website/docs/reference/environment-variables.md b/website/docs/reference/environment-variables.md index 0b5afa4b8..ed4b0f907 100644 --- a/website/docs/reference/environment-variables.md +++ b/website/docs/reference/environment-variables.md @@ -32,6 +32,7 @@ All variables go in `~/.hermes/.env`. You can also set them with `hermes config | `KILOCODE_BASE_URL` | Override Kilo Code base URL (default: `https://api.kilo.ai/api/gateway`) | | `ANTHROPIC_API_KEY` | Anthropic Console API key ([console.anthropic.com](https://console.anthropic.com/)) | | `ANTHROPIC_TOKEN` | Manual or legacy Anthropic OAuth/setup-token override | +| `DASHSCOPE_API_KEY` | Alibaba Cloud DashScope API key for Qwen models via Anthropic-compatible API ([modelstudio.console.alibabacloud.com](https://modelstudio.console.alibabacloud.com/)) | | `CLAUDE_CODE_OAUTH_TOKEN` | Explicit Claude Code token override if you export one manually | | `HERMES_MODEL` | Preferred model name (checked before `LLM_MODEL`, used by gateway) | | `LLM_MODEL` | Default model name (fallback when not set in config.yaml) | @@ -46,7 +47,7 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe | Variable | Description | |----------|-------------| -| `HERMES_INFERENCE_PROVIDER` | Override provider selection: `auto`, `openrouter`, `nous`, `openai-codex`, `anthropic`, `zai`, `kimi-coding`, `minimax`, `minimax-cn`, `kilocode` (default: `auto`) | +| `HERMES_INFERENCE_PROVIDER` | Override provider selection: `auto`, `openrouter`, `nous`, `openai-codex`, `anthropic`, `zai`, `kimi-coding`, `minimax`, `minimax-cn`, `kilocode`, `alibaba` (default: `auto`) | | `HERMES_PORTAL_BASE_URL` | Override Nous Portal URL (for development/testing) | | `NOUS_INFERENCE_BASE_URL` | Override Nous inference API URL | | `HERMES_NOUS_MIN_KEY_TTL_SECONDS` | Min agent key TTL before re-mint (default: 1800 = 30min) | @@ -162,6 +163,8 @@ For native Anthropic auth, Hermes prefers Claude Code's own credential files whe | `EMAIL_HOME_ADDRESS_NAME` | Display name for the email home target | | `EMAIL_POLL_INTERVAL` | Email polling interval in seconds | | `EMAIL_ALLOW_ALL_USERS` | Allow all inbound email senders | +| `DINGTALK_CLIENT_ID` | DingTalk bot AppKey from developer portal ([open.dingtalk.com](https://open.dingtalk.com)) | +| `DINGTALK_CLIENT_SECRET` | DingTalk bot AppSecret from developer portal | | `HASS_TOKEN` | Home Assistant Long-Lived Access Token (enables HA platform + tools) | | `HASS_URL` | Home Assistant URL (default: `http://homeassistant.local:8123`) | | `MESSAGING_CWD` | Working directory for terminal commands in messaging mode (default: `~`) |