Zhanlu Proxy
一个本地 Go 代理服务,用于读取湛卢插件凭据,按插件认证签名规则请求湛卢上游,并暴露 OpenAI 兼容接口。
当前实现包含:
- 登录页支持插件默认的移动云手机号验证码登录,成功后自动保存凭据到本地 JSON。
- OpenAI 兼容接口:
/v1/models、/v1/chat/completions。 - 湛卢签名逻辑:RSA
authorization、SHA-256 query hash、HMAC-SHA1Signature。 - 湛卢加密 SSE 响应解密并转换为 OpenAI SSE;非流式请求在本地聚合为 OpenAI Chat Completion JSON。
- OpenAI 函数/工具调用:支持
tools、tool_choice、流式delta.tool_calls、非流式message.tool_calls以及role: tool结果续传。
运行
go run ./cmd/zhanlu-proxy
默认监听:
http://127.0.0.1:8080
打开首页会自动跳转到管理登录页:
http://127.0.0.1:8080/
systemd 服务示例
假设二进制文件放在:
/opt/zhanlu-proxy/zhanlu-proxy
凭据文件放在:
/opt/zhanlu-proxy/credentials.json
创建环境变量文件 /etc/zhanlu-proxy/zhanlu-proxy.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_UPSTREAM_TIMEOUT=300s
ZHANLU_LOGIN_PASSWORD=change-this-login-password
OPENAI_COMPAT_API_KEY=change-this-local-secret
创建 systemd service 文件 /etc/systemd/system/zhanlu-proxy.service:
[Unit]
Description=Zhanlu OpenAI-compatible proxy
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
WorkingDirectory=/opt/zhanlu-proxy
EnvironmentFile=/etc/zhanlu-proxy/zhanlu-proxy.env
ExecStart=/opt/zhanlu-proxy/zhanlu-proxy
Restart=always
RestartSec=3
User=zhanlu-proxy
Group=zhanlu-proxy
[Install]
WantedBy=multi-user.target
启用并启动服务:
sudo systemctl daemon-reload
sudo systemctl enable --now zhanlu-proxy
sudo systemctl status zhanlu-proxy
查看日志:
journalctl -u zhanlu-proxy -f
登录与凭据
移动云手机号验证码登录
打开 /login 后输入手机号并点击“获取验证码”。实现按插件默认登录分支工作:
如果设置了 ZHANLU_LOGIN_PASSWORD,/login 只负责管理密码登录。密码正确后服务会设置 HttpOnly 会话 Cookie,并跳转到 /admin/login。/admin/login 才是手机号验证码登录湛卢的页面,之后才能查看凭据状态、获取短信验证码、保存凭据或使用备用 SSO 管理接口。
- 生成 16 位一次性
secret。 - 使用插件内置 RSA 公钥加密手机号和
secret。 - 调用公网接口
/api/query/acepilot-h5/manager/code/getAuthCode发送验证码。 - 输入验证码后调用
/api/query/acepilot-h5/manager/code/checkCode。 - 使用本次
secretAES 解密响应中的ak、sk、license,得到AccessKey、SecretKey、Token。 - 凭据会写入 JSON 文件,后续 OpenAI 兼容接口自动读取。
默认保存到当前执行目录:
credentials.json
可以通过环境变量覆盖:
$env:ZHANLU_CREDENTIALS_FILE="E:\path\to\credentials.json"
手机号验证码登录使用 ZHANLU_SERVER_BASE_URL,默认公网地址来自插件配置:
$env:ZHANLU_SERVER_BASE_URL="https://api-wuxi-1.cmecloud.cn:8443"
四共 SSO 的 /auth/start 和 /auth/callback 仍保留为备用接口,但不是 /login 的默认主流程。
OpenAI 兼容接口
健康检查
curl http://127.0.0.1:8080/healthz
模型列表
curl http://127.0.0.1:8080/v1/models
Chat Completions
非流式:
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}'
流式:
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}'
工具调用
请求中的 tools、tool_choice 会传给湛卢模型。流式响应返回增量 delta.tool_calls;非流式响应会把分片聚合为完整的 message.tool_calls,并保留 finish_reason: "tool_calls"。执行工具后,将 assistant 的 tool_calls 和 role: "tool" 结果放回 messages 再发起请求即可得到最终回答。
如果设置了本地 OpenAI 兼容 API Key,需要带 Authorization:
$env:OPENAI_COMPAT_API_KEY="local-secret"
curl http://127.0.0.1:8080/v1/models `
-H "Authorization: Bearer local-secret"
配置项
| 环境变量 | 默认值 | 说明 |
|---|---|---|
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_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_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_UPSTREAM_TIMEOUT |
300s |
上游请求超时 |
ZHANLU_STREAM_IDLE_TIMEOUT |
300s |
预留的流式空闲超时配置 |
ZHANLU_LOGIN_PASSWORD |
空 | /login 管理页面密码;设置后登录成功跳转到 /admin/login 管理湛卢凭据 |
ZHANLU_DEBUG |
false |
调试模式,错误信息更详细但会脱敏敏感 query |
OPENAI_COMPAT_API_KEY |
空 | 本地 OpenAI 兼容接口鉴权 key |
凭据优先级
服务启动时按以下优先级加载凭据:
- 环境变量
ZHANLU_ACCESS_KEY、ZHANLU_SECRET_KEY、ZHANLU_TOKEN。 ZHANLU_CREDENTIALS_FILE指向的 JSON 文件。
登录页面保存后,运行中的服务会立即使用新凭据。
安全说明
credentials.json包含明文AccessKey、SecretKey、Token,请不要提交到仓库。- 默认保存在当前执行目录的
credentials.json。 - 建议设置
ZHANLU_LOGIN_PASSWORD,避免公网暴露的/admin/login被直接访问。 - 错误响应默认不会返回签名 URL,避免泄露
AccessKey、authorization、Signature。 ZHANLU_DEBUG=true时会返回更详细错误,但仍会对敏感 query 参数脱敏。
已知限制
ZHANLU_UPSTREAM_PATH当前默认值是根据插件分析给出的候选路径,真实环境如果返回 404 或上游错误,需要用实际路径覆盖。- 手机号验证码接口可能有风控或频率限制;请按正常登录频率使用。
- 湛卢上游必须使用
stream:true;代理对 OpenAIstream:false请求负责聚合流式响应。 - UI 模型名
glm4.7、minimax-m2.5会按插件逻辑映射为上游glm47、minimax-m25。 zhanlu3使用独立的内网 VL Gateway 和ZHANLU_VL_API_KEY,当前代理未接入该特殊分支。
验证
go test ./...
go build ./cmd/zhanlu-proxy
本地端点验证:
go run ./cmd/zhanlu-proxy
curl http://127.0.0.1:8080/healthz
curl http://127.0.0.1:8080/v1/models