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:
+52
-34
@@ -10,50 +10,57 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
ListenAddr string
|
||||
ServerBaseURL string
|
||||
UpstreamPath string
|
||||
CredentialsPath string
|
||||
SSOExchangeURL string
|
||||
SSOBaseURL string
|
||||
TokenDecryptKey string
|
||||
PublicKeyPEM string
|
||||
PhonePublicKeyPEM string
|
||||
Models []string
|
||||
DefaultModel string
|
||||
OpenAIAPIKey string
|
||||
LoginPassword string
|
||||
UpstreamTimeout time.Duration
|
||||
StreamIdleTimout time.Duration
|
||||
Debug bool
|
||||
Credentials auth.Credentials
|
||||
ListenAddr string
|
||||
MobileLoginBaseURL string
|
||||
MobileModelBaseURL string
|
||||
UpstreamPath string
|
||||
CredentialsPath string
|
||||
SSOExchangeURL string
|
||||
SSOBaseURL string
|
||||
TokenDecryptKey string
|
||||
PublicKeyPEM string
|
||||
PhonePublicKeyPEM string
|
||||
SM2PrivateKey string
|
||||
Models []string
|
||||
DefaultModel string
|
||||
OpenAIAPIKey string
|
||||
LoginPassword string
|
||||
PluginVersion string
|
||||
UpstreamTimeout time.Duration
|
||||
StreamIdleTimout time.Duration
|
||||
Debug bool
|
||||
Credentials auth.Credentials
|
||||
}
|
||||
|
||||
func Load() (Config, error) {
|
||||
cfg := Config{
|
||||
ListenAddr: getenv("ZHANLU_LISTEN_ADDR", ":8080"),
|
||||
ServerBaseURL: getenv("ZHANLU_SERVER_BASE_URL", "https://api-wuxi-1.cmecloud.cn:8443"),
|
||||
UpstreamPath: getenv("ZHANLU_UPSTREAM_PATH", "/api/acepilot/zhanlu/aiDeveloper/chat"),
|
||||
CredentialsPath: getenv("ZHANLU_CREDENTIALS_FILE", defaultCredentialsPath()),
|
||||
SSOBaseURL: getenv("ZHANLU_SSO_BASE_URL", "http://rdcloud.4c.hq.cmcc"),
|
||||
SSOExchangeURL: getenv("ZHANLU_SSO_EXCHANGE_URL", "https://api-wuxi-1.cmecloud.cn:8443/cmdevops-aiplus-agent-gateway/api/acepilot/zhanlu/checkoutCode"),
|
||||
TokenDecryptKey: os.Getenv("ZHANLU_TOKEN_DECRYPT_KEY"),
|
||||
PublicKeyPEM: getenv("ZHANLU_PUBLIC_KEY_PEM", defaultPublicKeyPEM),
|
||||
PhonePublicKeyPEM: getenv("ZHANLU_PHONE_PUBLIC_KEY_PEM", defaultPhonePublicKeyPEM),
|
||||
DefaultModel: getenv("ZHANLU_DEFAULT_MODEL", "minimax-m25"),
|
||||
OpenAIAPIKey: os.Getenv("OPENAI_COMPAT_API_KEY"),
|
||||
LoginPassword: os.Getenv("ZHANLU_LOGIN_PASSWORD"),
|
||||
UpstreamTimeout: durationEnv("ZHANLU_UPSTREAM_TIMEOUT", 300*time.Second),
|
||||
StreamIdleTimout: durationEnv("ZHANLU_STREAM_IDLE_TIMEOUT", 300*time.Second),
|
||||
Debug: strings.EqualFold(os.Getenv("ZHANLU_DEBUG"), "true"),
|
||||
ListenAddr: getenv("ZHANLU_LISTEN_ADDR", ":8080"),
|
||||
MobileLoginBaseURL: firstNonEmpty(os.Getenv("ZHANLU_MOBILE_LOGIN_BASE_URL"), getenv("ZHANLU_SERVER_BASE_URL", "https://ecloud.10086.cn")),
|
||||
MobileModelBaseURL: getenv("ZHANLU_MOBILE_MODEL_BASE_URL", "https://ecloud.10086.cn/api/query/aigateway"),
|
||||
UpstreamPath: getenv("ZHANLU_UPSTREAM_PATH", "/chat/completions"),
|
||||
CredentialsPath: getenv("ZHANLU_CREDENTIALS_FILE", defaultCredentialsPath()),
|
||||
SSOBaseURL: getenv("ZHANLU_SSO_BASE_URL", "http://4c.hq.cmcc"),
|
||||
SSOExchangeURL: getenv("ZHANLU_SSO_EXCHANGE_URL", "http://rdcloud.4c.hq.cmcc/cmdevops-aiplus-agent-gateway/api/acepilot/zhanlu/authToken"),
|
||||
TokenDecryptKey: getenv("ZHANLU_TOKEN_DECRYPT_KEY", "3jw7woww2rvhla6k"),
|
||||
PublicKeyPEM: getenv("ZHANLU_PUBLIC_KEY_PEM", defaultPublicKeyPEM),
|
||||
PhonePublicKeyPEM: getenv("ZHANLU_PHONE_PUBLIC_KEY_PEM", defaultPhonePublicKeyPEM),
|
||||
SM2PrivateKey: getenv("ZHANLU_APIKEY_AUTH_SM2_PRIVATE_KEY", defaultSM2PrivateKey),
|
||||
DefaultModel: getenv("ZHANLU_DEFAULT_MODEL", "GLM-4.7"),
|
||||
OpenAIAPIKey: os.Getenv("OPENAI_COMPAT_API_KEY"),
|
||||
LoginPassword: os.Getenv("ZHANLU_LOGIN_PASSWORD"),
|
||||
PluginVersion: getenv("ZHANLU_PLUGIN_VERSION", "1.4.2"),
|
||||
UpstreamTimeout: durationEnv("ZHANLU_UPSTREAM_TIMEOUT", 300*time.Second),
|
||||
StreamIdleTimout: durationEnv("ZHANLU_STREAM_IDLE_TIMEOUT", 300*time.Second),
|
||||
Debug: strings.EqualFold(os.Getenv("ZHANLU_DEBUG"), "true"),
|
||||
}
|
||||
cfg.Models = splitCSV(getenv("ZHANLU_MODELS", "glm47,minimax-m25"))
|
||||
cfg.Models = splitCSV(getenv("ZHANLU_MODELS", "GLM-4.7,MiniMax-M2.5"))
|
||||
cfg.Credentials = auth.Credentials{
|
||||
AccessKey: os.Getenv("ZHANLU_ACCESS_KEY"),
|
||||
SecretKey: os.Getenv("ZHANLU_SECRET_KEY"),
|
||||
Token: os.Getenv("ZHANLU_TOKEN"),
|
||||
APIKey: os.Getenv("ZHANLU_API_KEY"),
|
||||
}
|
||||
if cfg.Credentials.Validate() == nil {
|
||||
if cfg.Credentials.Validate() == nil || cfg.Credentials.HasAPIKey() {
|
||||
return cfg, nil
|
||||
}
|
||||
if creds, err := auth.LoadCredentials(cfg.CredentialsPath); err == nil {
|
||||
@@ -93,6 +100,15 @@ func durationEnv(key string, fallback time.Duration) time.Duration {
|
||||
return d
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, v := range values {
|
||||
if strings.TrimSpace(v) != "" {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func defaultCredentialsPath() string {
|
||||
return filepath.Join(".", "credentials.json")
|
||||
}
|
||||
@@ -104,3 +120,5 @@ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhxudxTewPgljUHEZHkusP7m3I+zA4/RGvuUM
|
||||
const defaultPhonePublicKeyPEM = `-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnqiA2qP9BNvKw5DnVnrBVBhd+5gJDVn3mDemCfq/AN1cdaHV57hQo6R1ufp45mOkSwLaJcTE82zFKmgKoEAKwD1SR10rp0xJC7x3yvx2FbpEsiW9TeZlvJdri1BYKUMS8OP8ykjHSJoy0oMaV6e95R2rsu4DEH7JuA9+Bt0sOoLewvHx/fs1e28tH+928uUEKdLug+cv/XTKjLudpLjiSMPZU6EHFqrUhA9zmEasOMmg9Dj0j4sChBooCeCGnh/pYHJaosH5amhlSQ8FnEG0BQBrQbZ+qhRH4LYyqGYN8grDNeSnPj7vPDcwiEm++85i5AngZfEMnGWZg5jYDhO9+QIDAQAB
|
||||
-----END PUBLIC KEY-----`
|
||||
|
||||
const defaultSM2PrivateKey = "8d6ee90b3c4d299ae5abd655dbc3547c110ae8aeff1de18b0df241f215f90748"
|
||||
|
||||
Reference in New Issue
Block a user