Skip to content

Commit eb969e7

Browse files
authored
feat: support Z.ai coding platform (#35)
* feat: support Z.ai coding platform (#34) * fix: address PR feedback (unit tests, docs cleanup, news revert)
1 parent 00f2708 commit eb969e7

9 files changed

Lines changed: 37 additions & 9 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ vibe-trading-mcp # start MCP server (stdio)
226226
- **Python 3.11+** for Path B
227227
- **Docker** for Path A
228228

229-
> **Supported LLM providers:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Ollama (local). See `.env.example` for config.
229+
> **Supported LLM providers:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Z.ai, Ollama (local). See `.env.example` for config.
230230
231231
> **Tip:** All markets work without any API keys thanks to automatic fallback. yfinance (HK/US), OKX (crypto), and AKShare (A-shares, US, HK, futures, forex) are all free. Tushare token is optional — AKShare covers A-shares as a free fallback.
232232

README_ar.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ vibe-trading-mcp # بدء خادم MCP (stdio)
226226
- **Python 3.11+** للمسار B
227227
- **Docker** للمسار A
228228

229-
> **مزودو نماذج اللغة المدعومون:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Ollama (محلي). راجع `.env.example` للإعدادات.
229+
> **مزودو نماذج اللغة المدعومون:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Z.ai, Ollama (محلي). راجع `.env.example` للإعدادات.
230230
231231
> **نصيحة:** جميع الأسواق تعمل بدون أي مفاتيح API بفضل البديل التلقائي. yfinance (HK/US) و OKX (العملات المشفرة) و AKShare (أسهم A، US، HK، العقود الآجلة، الفوركس) جميعها مجانية. رمز Tushare اختياري — AKShare يغطي أسهم A كبديل مجاني.
232232
@@ -300,7 +300,7 @@ npx clawhub@latest install vibe-trading --force
300300

301301
| المتغير | مطلوب | الوصف |
302302
|----------|:--------:|-------------|
303-
| `LANGCHAIN_PROVIDER` | نعم | اسم المزود (`openrouter`, `deepseek`, `groq`, `ollama`, إلخ) |
303+
| `LANGCHAIN_PROVIDER` | نعم | اسم المزود (`openrouter`, `deepseek`, `groq`, `z.ai`, `ollama`, إلخ) |
304304
| `<PROVIDER>_API_KEY` | نعم* | مفتاح API (`OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY`, إلخ) |
305305
| `<PROVIDER>_BASE_URL` | نعم | رابط نقطة نهاية API |
306306
| `LANGCHAIN_MODEL_NAME` | نعم | اسم النموذج (مثلاً `deepseek/deepseek-v3.2`) |

README_ja.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ vibe-trading-mcp # MCPサーバー(stdio)起動
224224
- Path Bでは**Python 3.11+**
225225
- Path Aでは**Docker**
226226

227-
> **サポートされるLLMプロバイダー:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Ollama(ローカル)。設定は`.env.example`を参照。
227+
> **サポートされるLLMプロバイダー:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Z.ai, Ollama(ローカル)。設定は`.env.example`を参照。
228228
229229
> **Tip:** すべての市場でAPIキーなしでも動作(自動フォールバック)。yfinance(HK/US)、OKX(暗号)、AKShare(A株・US・HK・先物・FX)は無料。Tushareトークンは任意 — A株はAKShareで無料フォールバック。
230230

README_ko.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ vibe-trading-mcp # MCP 서버 시작(stdio)
224224
- 경로 B용 **Python 3.11+**
225225
- 경로 A용 **Docker**
226226

227-
> **지원 LLM 제공자:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Ollama(로컬). 설정은 `.env.example` 참고.
227+
> **지원 LLM 제공자:** OpenRouter, OpenAI, DeepSeek, Gemini, Groq, DashScope/Qwen, Zhipu, Moonshot/Kimi, MiniMax, Xiaomi MIMO, Z.ai, Ollama(로컬). 설정은 `.env.example` 참고.
228228
229229
> **팁:** 모든 시장은 자동 폴백 덕분에 API 키 없이도 작동합니다. yfinance(HK/US), OKX(크립토), AKShare(A주, 미국, HK, 선물, FX)는 모두 무료입니다. Tushare 토큰은 선택 사항 — AKShare가 A주 무료 폴백을 제공합니다.
230230
@@ -298,7 +298,7 @@ npx clawhub@latest install vibe-trading --force
298298

299299
| Variable | Required | Description |
300300
|----------|:--------:|-------------|
301-
| `LANGCHAIN_PROVIDER` | Yes | 제공자 이름(`openrouter`, `deepseek`, `groq`, `ollama` 등) |
301+
| `LANGCHAIN_PROVIDER` | Yes | 제공자 이름(`openrouter`, `deepseek`, `groq`, `z.ai`, `ollama` 등) |
302302
| `<PROVIDER>_API_KEY` | Yes* | API 키(`OPENROUTER_API_KEY`, `DEEPSEEK_API_KEY` 등) |
303303
| `<PROVIDER>_BASE_URL` | Yes | API 엔드포인트 URL |
304304
| `LANGCHAIN_MODEL_NAME` | Yes | 모델 이름(예: `deepseek/deepseek-v3.2`) |

README_zh.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ vibe-trading-mcp # 启动 MCP 服务器(stdio)
224224
- Path B 需 **Python 3.11+**
225225
- Path A 需 **Docker**
226226

227-
> **支持的 LLM 提供商:** OpenRouter、OpenAI、DeepSeek、Gemini、Groq、DashScope/Qwen、智谱、Moonshot/Kimi、MiniMax、小米 MIMO、Ollama(本地)。参见 `.env.example` 配置。
227+
> **支持的 LLM 提供商:** OpenRouter、OpenAI、DeepSeek、Gemini、Groq、DashScope/Qwen、智谱、Moonshot/Kimi、MiniMax、小米 MIMO、Z.ai、Ollama(本地)。参见 `.env.example` 配置。
228228
229229
> **提示:** 所有市场都可在无 API key 情况下运行,因自动回退。yfinance(港美股)、OKX(加密)、AKShare(A 股、美股、港股、期货、外汇)均免费。Tushare token 可选——A 股可回退到 AKShare 免费获取。
230230
@@ -298,7 +298,7 @@ npx clawhub@latest install vibe-trading --force
298298

299299
| Variable | Required | Description |
300300
|----------|:--------:|-------------|
301-
| `LANGCHAIN_PROVIDER` | Yes | 提供商名称(`openrouter``deepseek``groq``ollama` 等) |
301+
| `LANGCHAIN_PROVIDER` | Yes | 提供商名称(`openrouter``deepseek``groq``z.ai``ollama` 等) |
302302
| `<PROVIDER>_API_KEY` | Yes* | API key(`OPENROUTER_API_KEY``DEEPSEEK_API_KEY` 等) |
303303
| `<PROVIDER>_BASE_URL` | Yes | API 端点 URL |
304304
| `LANGCHAIN_MODEL_NAME` | Yes | 模型名(如 `deepseek/deepseek-v3.2`|

agent/.env.example

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ OPENROUTER_BASE_URL=https://openrouter.ai/api/v1
6363
# MIMO_API_KEY=xxx
6464
# MIMO_BASE_URL=https://api.xiaomimimo.com/v1
6565

66+
# --- Z.ai (for Coding Plan) ---
67+
# LANGCHAIN_PROVIDER=zai
68+
# LANGCHAIN_MODEL_NAME=glm-5.1
69+
# ZAI_API_KEY=xxx
70+
# ZAI_BASE_URL=https://api.z.ai/api/coding/paas/v4
71+
6672
# --- Ollama (local) ---
6773
# LANGCHAIN_PROVIDER=ollama
6874
# LANGCHAIN_MODEL_NAME=qwen2.5:32b

agent/cli.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,16 @@ def _handle_prompt_command(
15191519
"key_prefix": None,
15201520
"key_placeholder": "api-key...",
15211521
},
1522+
{
1523+
"label": "Z.ai (Coding platform)",
1524+
"provider": "zai",
1525+
"key_env": "ZAI_API_KEY",
1526+
"base_env": "ZAI_BASE_URL",
1527+
"base_url": "https://api.z.ai/api/coding/paas/v4",
1528+
"model": "glm-5.1",
1529+
"key_prefix": None,
1530+
"key_placeholder": "api-key...",
1531+
},
15221532
{
15231533
"label": "Ollama (local, free)",
15241534
"provider": "ollama",
@@ -1564,6 +1574,8 @@ def _render_env_content(config: dict[str, str]) -> str:
15641574
"MINIMAX_BASE_URL",
15651575
"MIMO_API_KEY",
15661576
"MIMO_BASE_URL",
1577+
"ZAI_API_KEY",
1578+
"ZAI_BASE_URL",
15671579
"OLLAMA_BASE_URL",
15681580
"LANGCHAIN_MODEL_NAME",
15691581
"TUSHARE_TOKEN",

agent/src/providers/llm.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ def _sync_provider_env() -> None:
7979
"moonshot": ("MOONSHOT_API_KEY", "MOONSHOT_BASE_URL"),
8080
"minimax": ("MINIMAX_API_KEY", "MINIMAX_BASE_URL"),
8181
"mimo": ("MIMO_API_KEY", "MIMO_BASE_URL"),
82+
"zai": ("ZAI_API_KEY", "ZAI_BASE_URL"),
8283
"ollama": (None, "OLLAMA_BASE_URL"),
8384
}
8485

agent/tests/test_llm.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def _run_sync(self, env: dict[str, str]) -> dict[str, str]:
2424
import src.providers.llm as llm_mod
2525
llm_mod._dotenv_loaded = True # pretend already loaded
2626

27-
clean = {k: v for k, v in os.environ.items() if not k.startswith(("OPENAI_", "LANGCHAIN_", "DEEPSEEK_", "GROQ_", "OLLAMA_", "DASHSCOPE_"))}
27+
clean = {k: v for k, v in os.environ.items() if not k.startswith(("OPENAI_", "LANGCHAIN_", "DEEPSEEK_", "GROQ_", "OLLAMA_", "DASHSCOPE_", "ZAI_"))}
2828
clean.update(env)
2929
with patch.dict(os.environ, clean, clear=True):
3030
_sync_provider_env()
@@ -75,6 +75,15 @@ def test_qwen_alias_to_dashscope(self) -> None:
7575
})
7676
assert result["OPENAI_API_KEY"] == "qwen-key"
7777

78+
def test_zai_provider(self) -> None:
79+
result = self._run_sync({
80+
"LANGCHAIN_PROVIDER": "zai",
81+
"ZAI_API_KEY": "zai-key-test",
82+
"ZAI_BASE_URL": "https://api.z.ai/api/coding/paas/v4",
83+
})
84+
assert result["OPENAI_API_KEY"] == "zai-key-test"
85+
assert result["OPENAI_API_BASE"] == "https://api.z.ai/api/coding/paas/v4"
86+
7887
def test_unknown_provider_falls_back_to_openai(self) -> None:
7988
result = self._run_sync({
8089
"LANGCHAIN_PROVIDER": "unknown_provider_xyz",

0 commit comments

Comments
 (0)