Update proxy to Zhanlu v1.4.2 provider flow
The 1.4.2 extension replaced the old signed/encrypted chat gateway with an
OpenAI-compatible aigateway. Align the proxy with the new flow:
- Use ecloud.10086.cn login/model base URLs, zhanlu_ide plugin headers and
v1.4.2 plugin version
- Provision the model API key via SM2-signed get-or-create after v1/login
profile fetch; store api_key/model_base_url/email in credentials
- Chat via Bearer apiKey against {modelBaseUrl}/chat/completions with plain
OpenAI SSE passthrough; fetch /v1/models from the gateway model-info endpoint
- Force HTTP/1.1 upstream (gateway drops HTTP/2 ALPN negotiation with EOF)
- Drop obsolete AES body encryption, model name mapping and vscode headers
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
# Zhanlu Proxy
|
||||
|
||||
一个本地 Go 代理服务,用于读取湛卢插件凭据,按插件认证签名规则请求湛卢上游,并暴露 OpenAI 兼容接口。
|
||||
一个本地 Go 代理服务,用于读取湛卢(v1.4.2)插件凭据,按插件认证规则换取模型 API Key,并暴露 OpenAI 兼容接口。
|
||||
|
||||
当前实现包含:
|
||||
|
||||
- 登录页支持插件默认的移动云手机号验证码登录,成功后自动保存凭据到本地 JSON。
|
||||
- OpenAI 兼容接口:`/v1/models`、`/v1/chat/completions`。
|
||||
- 湛卢签名逻辑:RSA `authorization`、SHA-256 query hash、HMAC-SHA1 `Signature`。
|
||||
- 湛卢加密 SSE 响应解密并转换为 OpenAI SSE;非流式请求在本地聚合为 OpenAI Chat Completion JSON。
|
||||
- 登录页支持插件默认的移动云手机号验证码登录:验证码校验后按插件流程调用 `/api/acepilot/zhanlu/v1/login` 获取用户资料,再通过 SM2 签名调用 `/user/api/v2/external/key/get-or-create` 换取模型 API Key,凭据自动保存到本地 JSON。
|
||||
- OpenAI 兼容接口:`/v1/models`(优先从 `/gateway/v1/model/info` 拉取模型列表)、`/v1/chat/completions`(携带 `Authorization: Bearer <apiKey>` 请求 `{modelBaseUrl}/chat/completions`)。
|
||||
- 湛卢登录签名逻辑:RSA `authorization`、SHA-256 query hash、HMAC-SHA1 `Signature`,用于 v1.4.2 的 v1/login 认证。
|
||||
- 模型 API Key 换取签名逻辑:SM3 摘要 + SM2 签名(`X-Auth-Signature`/`X-Auth-Timestamp`/`X-Auth-Nonce`)。
|
||||
- 上游 SSE 直接透传为 OpenAI SSE;非流式请求在本地聚合为 OpenAI Chat Completion JSON。
|
||||
- OpenAI 函数/工具调用:支持 `tools`、`tool_choice`、流式 `delta.tool_calls`、非流式 `message.tool_calls` 以及 `role: tool` 结果续传。
|
||||
|
||||
## 运行
|
||||
@@ -47,10 +48,10 @@ http://127.0.0.1:8080/
|
||||
```env
|
||||
ZHANLU_LISTEN_ADDR=:8080
|
||||
ZHANLU_CREDENTIALS_FILE=/opt/zhanlu-proxy/credentials.json
|
||||
ZHANLU_SERVER_BASE_URL=https://api-wuxi-1.cmecloud.cn:8443
|
||||
ZHANLU_UPSTREAM_PATH=/api/acepilot/zhanlu/aiDeveloper/chat
|
||||
ZHANLU_MODELS=glm47,minimax-m25
|
||||
ZHANLU_DEFAULT_MODEL=minimax-m25
|
||||
ZHANLU_MOBILE_LOGIN_BASE_URL=https://ecloud.10086.cn
|
||||
ZHANLU_MOBILE_MODEL_BASE_URL=https://ecloud.10086.cn/api/query/aigateway
|
||||
ZHANLU_MODELS=GLM-4.7,MiniMax-M2.5
|
||||
ZHANLU_DEFAULT_MODEL=GLM-4.7
|
||||
ZHANLU_UPSTREAM_TIMEOUT=300s
|
||||
ZHANLU_LOGIN_PASSWORD=change-this-login-password
|
||||
OPENAI_COMPAT_API_KEY=change-this-local-secret
|
||||
@@ -105,7 +106,9 @@ journalctl -u zhanlu-proxy -f
|
||||
- 调用公网接口 `/api/query/acepilot-h5/manager/code/getAuthCode` 发送验证码。
|
||||
- 输入验证码后调用 `/api/query/acepilot-h5/manager/code/checkCode`。
|
||||
- 使用本次 `secret` AES 解密响应中的 `ak`、`sk`、`license`,得到 `AccessKey`、`SecretKey`、`Token`。
|
||||
- 凭据会写入 JSON 文件,后续 OpenAI 兼容接口自动读取。
|
||||
- 按插件 v1.4.2 流程调用 `/api/acepilot/zhanlu/v1/login`(RSA+HmacSHA1 签名 URL + `plugin_type=zhanlu_ide` 请求头)获取用户资料(email/组织/团队)。
|
||||
- 用 SM2 私钥签名调用 `{mobileModelBaseUrl}/user/api/v2/external/key/get-or-create` 换取模型 `apiKey`。
|
||||
- 凭据(含 `apiKey`、`modelBaseUrl`、email 等)会写入 JSON 文件,后续 OpenAI 兼容接口自动使用。
|
||||
|
||||
默认保存到当前执行目录:
|
||||
|
||||
@@ -119,13 +122,14 @@ credentials.json
|
||||
$env:ZHANLU_CREDENTIALS_FILE="E:\path\to\credentials.json"
|
||||
```
|
||||
|
||||
手机号验证码登录使用 `ZHANLU_SERVER_BASE_URL`,默认公网地址来自插件配置:
|
||||
手机号验证码登录使用 `ZHANLU_MOBILE_LOGIN_BASE_URL`,默认公网地址来自插件配置(兼容旧环境变量 `ZHANLU_SERVER_BASE_URL`):
|
||||
|
||||
```powershell
|
||||
$env:ZHANLU_SERVER_BASE_URL="https://api-wuxi-1.cmecloud.cn:8443"
|
||||
$env:ZHANLU_MOBILE_LOGIN_BASE_URL="https://ecloud.10086.cn"
|
||||
$env:ZHANLU_MOBILE_MODEL_BASE_URL="https://ecloud.10086.cn/api/query/aigateway"
|
||||
```
|
||||
|
||||
四共 SSO 的 `/auth/start` 和 `/auth/callback` 仍保留为备用接口,但不是 `/login` 的默认主流程。
|
||||
灵犀(内网)SSO 的 `/auth/start` 和 `/auth/callback` 仍保留为备用接口,但不是 `/login` 的默认主流程。
|
||||
|
||||
## OpenAI 兼容接口
|
||||
|
||||
@@ -148,7 +152,7 @@ curl http://127.0.0.1:8080/v1/models
|
||||
```powershell
|
||||
curl http://127.0.0.1:8080/v1/chat/completions `
|
||||
-H "Content-Type: application/json" `
|
||||
-d '{"model":"minimax-m2.5","messages":[{"role":"user","content":"hello"}],"stream":false}'
|
||||
-d '{"model":"GLM-4.7","messages":[{"role":"user","content":"hello"}],"stream":false}'
|
||||
```
|
||||
|
||||
流式:
|
||||
@@ -156,7 +160,7 @@ curl http://127.0.0.1:8080/v1/chat/completions `
|
||||
```powershell
|
||||
curl -N http://127.0.0.1:8080/v1/chat/completions `
|
||||
-H "Content-Type: application/json" `
|
||||
-d '{"model":"minimax-m2.5","messages":[{"role":"user","content":"hello"}],"stream":true}'
|
||||
-d '{"model":"GLM-4.7","messages":[{"role":"user","content":"hello"}],"stream":true}'
|
||||
```
|
||||
|
||||
### 工具调用
|
||||
@@ -179,19 +183,23 @@ curl http://127.0.0.1:8080/v1/models `
|
||||
| 环境变量 | 默认值 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `ZHANLU_LISTEN_ADDR` | `:8080` | 本地监听地址 |
|
||||
| `ZHANLU_SERVER_BASE_URL` | `https://api-wuxi-1.cmecloud.cn:8443` | 湛卢上游 Base URL |
|
||||
| `ZHANLU_UPSTREAM_PATH` | `/api/acepilot/zhanlu/aiDeveloper/chat` | 湛卢聊天接口路径,按插件 `createZhanluRequest` 默认分支设置 |
|
||||
| `ZHANLU_MOBILE_LOGIN_BASE_URL` | `https://ecloud.10086.cn` | 移动云公网登录 Base URL(兼容旧变量 `ZHANLU_SERVER_BASE_URL`) |
|
||||
| `ZHANLU_MOBILE_MODEL_BASE_URL` | `https://ecloud.10086.cn/api/query/aigateway` | 移动云公网模型网关 Base URL |
|
||||
| `ZHANLU_UPSTREAM_PATH` | `/chat/completions` | 模型网关聊天接口路径 |
|
||||
| `ZHANLU_CREDENTIALS_FILE` | `credentials.json` | 凭据 JSON 路径,默认当前执行目录 |
|
||||
| `ZHANLU_ACCESS_KEY` | 空 | 直接从环境变量提供 AccessKey |
|
||||
| `ZHANLU_SECRET_KEY` | 空 | 直接从环境变量提供 SecretKey |
|
||||
| `ZHANLU_TOKEN` | 空 | 直接从环境变量提供 Token |
|
||||
| `ZHANLU_SSO_BASE_URL` | `http://rdcloud.4c.hq.cmcc` | 四共 SSO 备用页面 Base URL,非默认手机号登录流程 |
|
||||
| `ZHANLU_SSO_EXCHANGE_URL` | `https://api-wuxi-1.cmecloud.cn:8443/cmdevops-aiplus-agent-gateway/api/acepilot/zhanlu/checkoutCode` | 四共 SSO code 换 token 的备用接口 |
|
||||
| `ZHANLU_TOKEN_DECRYPT_KEY` | 空 | 解密四共 SSO 返回 `ak/sk/token` 的 AES key;手机号登录不需要设置 |
|
||||
| `ZHANLU_API_KEY` | 空 | 直接从环境变量提供已换取的模型 API Key |
|
||||
| `ZHANLU_SSO_BASE_URL` | `http://4c.hq.cmcc` | 灵犀内网 SSO 备用页面 Base URL,非默认手机号登录流程 |
|
||||
| `ZHANLU_SSO_EXCHANGE_URL` | `http://rdcloud.4c.hq.cmcc/cmdevops-aiplus-agent-gateway/api/acepilot/zhanlu/authToken` | 灵犀 SSO 换取用户资料的备用接口 |
|
||||
| `ZHANLU_TOKEN_DECRYPT_KEY` | `3jw7woww2rvhla6k` | 解密 SSO 返回用户资料字段的 AES key(插件内置默认值) |
|
||||
| `ZHANLU_PUBLIC_KEY_PEM` | 插件内置签名公钥 | 签名 URL 中 `authorization` 使用的 RSA 公钥,通常不需要设置 |
|
||||
| `ZHANLU_PHONE_PUBLIC_KEY_PEM` | 插件内置手机号登录公钥 | 手机号验证码登录加密手机号和一次性 secret 使用的 RSA 公钥,通常不需要设置 |
|
||||
| `ZHANLU_MODELS` | `glm47,minimax-m25` | `/v1/models` 返回的模型列表,逗号分隔 |
|
||||
| `ZHANLU_DEFAULT_MODEL` | `minimax-m25` | 请求未传 `model` 时使用的默认模型 |
|
||||
| `ZHANLU_APIKEY_AUTH_SM2_PRIVATE_KEY` | 插件内置 SM2 私钥 | 换取模型 API Key 时 `X-Auth-Signature` 使用的 SM2 私钥,通常不需要设置 |
|
||||
| `ZHANLU_PLUGIN_VERSION` | `1.4.2` | 请求头 `plugin_version` |
|
||||
| `ZHANLU_MODELS` | `GLM-4.7,MiniMax-M2.5` | `/v1/models` 回退模型列表;有凭据时优先从模型网关拉取 |
|
||||
| `ZHANLU_DEFAULT_MODEL` | `GLM-4.7` | 请求未传 `model` 时使用的默认模型 |
|
||||
| `ZHANLU_UPSTREAM_TIMEOUT` | `300s` | 上游请求超时 |
|
||||
| `ZHANLU_STREAM_IDLE_TIMEOUT` | `300s` | 预留的流式空闲超时配置 |
|
||||
| `ZHANLU_LOGIN_PASSWORD` | 空 | `/login` 管理页面密码;设置后登录成功跳转到 `/admin/login` 管理湛卢凭据 |
|
||||
@@ -202,14 +210,14 @@ curl http://127.0.0.1:8080/v1/models `
|
||||
|
||||
服务启动时按以下优先级加载凭据:
|
||||
|
||||
1. 环境变量 `ZHANLU_ACCESS_KEY`、`ZHANLU_SECRET_KEY`、`ZHANLU_TOKEN`。
|
||||
1. 环境变量 `ZHANLU_ACCESS_KEY`、`ZHANLU_SECRET_KEY`、`ZHANLU_TOKEN` 或 `ZHANLU_API_KEY`。
|
||||
2. `ZHANLU_CREDENTIALS_FILE` 指向的 JSON 文件。
|
||||
|
||||
登录页面保存后,运行中的服务会立即使用新凭据。
|
||||
登录页面保存后,运行中的服务会立即使用新凭据。若环境中只有 AK/SK/Token 而没有 `apiKey`,首次调用聊天接口时会自动按插件流程换取 API Key 并回写凭据文件。
|
||||
|
||||
## 安全说明
|
||||
|
||||
- `credentials.json` 包含明文 `AccessKey`、`SecretKey`、`Token`,请不要提交到仓库。
|
||||
- `credentials.json` 包含明文 `AccessKey`、`SecretKey`、`Token` 和 `apiKey`,请不要提交到仓库。
|
||||
- 默认保存在当前执行目录的 `credentials.json`。
|
||||
- 建议设置 `ZHANLU_LOGIN_PASSWORD`,避免公网暴露的 `/admin/login` 被直接访问。
|
||||
- 错误响应默认不会返回签名 URL,避免泄露 `AccessKey`、`authorization`、`Signature`。
|
||||
@@ -217,11 +225,9 @@ curl http://127.0.0.1:8080/v1/models `
|
||||
|
||||
## 已知限制
|
||||
|
||||
- `ZHANLU_UPSTREAM_PATH` 当前默认值是根据插件分析给出的候选路径,真实环境如果返回 404 或上游错误,需要用实际路径覆盖。
|
||||
- 灵犀内网 SSO(`/auth/start`、`/auth/callback`)为备用接口,主流程是移动云手机号验证码登录。
|
||||
- 手机号验证码接口可能有风控或频率限制;请按正常登录频率使用。
|
||||
- 湛卢上游必须使用 `stream:true`;代理对 OpenAI `stream:false` 请求负责聚合流式响应。
|
||||
- UI 模型名 `glm4.7`、`minimax-m2.5` 会按插件逻辑映射为上游 `glm47`、`minimax-m25`。
|
||||
- `zhanlu3` 使用独立的内网 VL Gateway 和 `ZHANLU_VL_API_KEY`,当前代理未接入该特殊分支。
|
||||
- 模型网关对 OpenAI `stream:false` 请求由代理负责聚合流式响应。
|
||||
|
||||
## 验证
|
||||
|
||||
|
||||
Reference in New Issue
Block a user