m1saka b146ccb7ac
build / build (push) Successful in 51s
Document systemd service setup
2026-07-08 09:24:56 +08:00
2026-07-08 09:13:45 +08:00
2026-07-08 09:13:45 +08:00
2026-07-08 09:24:56 +08:00

Zhanlu Proxy

一个本地 Go 代理服务,用于读取湛卢插件凭据,按插件认证签名规则请求湛卢上游,并暴露 OpenAI 兼容接口。

当前实现包含:

  • 登录页支持插件默认的移动云手机号验证码登录,成功后自动保存凭据到本地 JSON。
  • OpenAI 兼容接口:/v1/models/v1/chat/completions
  • 湛卢签名逻辑:RSA authorization、SHA-256 query hash、HMAC-SHA1 Signature
  • 湛卢加密 SSE 响应解密并转换为 OpenAI SSE;非流式请求在本地聚合为 OpenAI Chat Completion JSON。
  • OpenAI 函数/工具调用:支持 toolstool_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/login

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
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 后输入手机号并点击“获取验证码”。实现按插件默认登录分支工作:

  • 生成 16 位一次性 secret
  • 使用插件内置 RSA 公钥加密手机号和 secret
  • 调用公网接口 /api/query/acepilot-h5/manager/code/getAuthCode 发送验证码。
  • 输入验证码后调用 /api/query/acepilot-h5/manager/code/checkCode
  • 使用本次 secret AES 解密响应中的 aksklicense,得到 AccessKeySecretKeyToken
  • 凭据会写入 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}'

工具调用

请求中的 toolstool_choice 会传给湛卢模型。流式响应返回增量 delta.tool_calls;非流式响应会把分片聚合为完整的 message.tool_calls,并保留 finish_reason: "tool_calls"。执行工具后,将 assistant 的 tool_callsrole: "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_DEBUG false 调试模式,错误信息更详细但会脱敏敏感 query
OPENAI_COMPAT_API_KEY 本地 OpenAI 兼容接口鉴权 key

凭据优先级

服务启动时按以下优先级加载凭据:

  1. 环境变量 ZHANLU_ACCESS_KEYZHANLU_SECRET_KEYZHANLU_TOKEN
  2. ZHANLU_CREDENTIALS_FILE 指向的 JSON 文件。

登录页面保存后,运行中的服务会立即使用新凭据。

安全说明

  • credentials.json 包含明文 AccessKeySecretKeyToken,请不要提交到仓库。
  • 默认保存在当前执行目录的 credentials.json
  • 错误响应默认不会返回签名 URL,避免泄露 AccessKeyauthorizationSignature
  • ZHANLU_DEBUG=true 时会返回更详细错误,但仍会对敏感 query 参数脱敏。

已知限制

  • ZHANLU_UPSTREAM_PATH 当前默认值是根据插件分析给出的候选路径,真实环境如果返回 404 或上游错误,需要用实际路径覆盖。
  • 手机号验证码接口可能有风控或频率限制;请按正常登录频率使用。
  • 湛卢上游必须使用 stream:true;代理对 OpenAI stream:false 请求负责聚合流式响应。
  • UI 模型名 glm4.7minimax-m2.5 会按插件逻辑映射为上游 glm47minimax-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
S
Description
No description provided
Readme
402 KiB
v0.2.1
Latest
2026-08-23 22:16:32 +08:00
Languages
Go 81.1%
HTML 17.7%
Shell 1.2%