Skip to content

feat: add GLM (z.ai) provider#34

Open
antonioacg wants to merge 1 commit into
raine:mainfrom
antonioacg:feat/glm-provider
Open

feat: add GLM (z.ai) provider#34
antonioacg wants to merge 1 commit into
raine:mainfrom
antonioacg:feat/glm-provider

Conversation

@antonioacg

Copy link
Copy Markdown

What

Adds a GLM (z.ai) provider exposing glm-4.7 and glm-5.2.

Why

z.ai speaks the Anthropic Messages API natively (https://api.z.ai/api/anthropic), so unlike the Codex/Kimi/Grok/Cursor providers it needs no request/response translation. The provider is a thin pass-through: it forwards the Anthropic request verbatim (after stripping the local [1m] compaction hint), authenticates with a static API key, and pipes the upstream Anthropic SSE/JSON reply back to Claude Code unchanged. This lets GLM users route through the same local serve process as the other providers (unified monitoring, model routing, traffic capture).

How

  • src/providers/glm/{auth,client,mod}.rs — provider + API-key auth. CCP_GLM_API_KEY (alias GLM_API_KEY) env takes precedence; otherwise glm auth login reads the key from stdin. Stored via the existing KeychainFileAuthStore (Keychain service claude-code-proxy.glm, with the same file fallback the other providers use).
  • src/registry.rs — register glm-4.7 / glm-5.2, routed by model id (consistent with codex/kimi).
  • src/config.rsglm.baseUrl (CCP_GLM_BASE_URL, default https://api.z.ai/api/anthropic).
  • src/main.rsglm auth login|status|logout subcommands; listed in models/banner.
  • README.md — provider section, model routing, env/config rows, auth commands, limitations.

handle_count_tokens uses a rough local estimate (like the cursor provider) to avoid an upstream round-trip. Streaming responses are buffered before forwarding, matching the existing codex/kimi providers.

Verification

  • cargo build, cargo fmt --all --check, cargo test --all (incl. new registry routing + auth round-trip tests) pass.
  • Smoke-tested end-to-end against z.ai with a real key: serve + a streaming POST /v1/messages with model: glm-5.2 returns a well-formed Anthropic SSE stream (message_start -> content_block_delta -> message_stop) with genuine usage.
  • Rebased on the latest main (which landed Grok in the meantime); the GLM provider coexists cleanly with the other providers.

Notes

  • API-key provider, not OAuth -- device prints guidance pointing at the env var / login.
  • The [1m] suffix is stripped before forwarding (consistent with codex/kimi).

Related: #4 (routing to an Anthropic-native backend).

z.ai exposes an Anthropic-compatible Messages API, so the GLM provider is a thin pass-through: it forwards the Anthropic request verbatim (after stripping the local [1m] compaction hint), authenticates with a static API key, and pipes the upstream Anthropic SSE/JSON reply back to Claude Code unchanged. No format translation, no OAuth.

- providers/glm/{auth,client,mod}.rs: provider + API-key auth (CCP_GLM_API_KEY / GLM_API_KEY env, or 'glm auth login' stdin prompt) via the shared KeychainFileAuthStore
- registry: register glm-4.7 / glm-5.2, routed by model id
- config: glm.baseUrl (CCP_GLM_BASE_URL, default https://api.z.ai/api/anthropic)
- main: glm auth login|status|logout subcommands
- README: provider section, model table, env/config rows, auth commands

count_tokens uses a rough local estimate (like the cursor provider) to avoid an upstream round-trip. Responses are buffered before forwarding, matching the existing codex/kimi providers. Smoke-tested end-to-end against z.ai.
@raine

raine commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Hi, I'm not sure this is needed because z.ai has an Anthropic compatible API directly.

https://docs.z.ai/devpack/tool/claude#manual-configuration

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants