Skip to content

feat(auth): add explicit Z.AI compatibility routes - #206

Merged
elkaix merged 9 commits into
mainfrom
feat/provider-compatibility-z-ai-routes
Jul 15, 2026
Merged

feat(auth): add explicit Z.AI compatibility routes#206
elkaix merged 9 commits into
mainfrom
feat/provider-compatibility-z-ai-routes

Conversation

@elkaix

@elkaix elkaix commented Jul 15, 2026

Copy link
Copy Markdown
Member

Related Issue

N/A — planned provider-compatibility and Z.AI route work following #205.

Description

Centralizes provider/model quirks behind immutable compatibility profiles and replaces the legacy single Z.AI route with two explicit OpenAI-compatible routes:

  • managed:z-ai-coding / z-ai-coding/*https://api.z.ai/api/coding/paas/v4
  • managed:z-ai-api / z-ai-api/*https://api.z.ai/api/paas/v4

The routes have independent environment variables, login/logout, model catalogs, refresh outcomes, defaults, usage notes, and rate-limit caches. There is no credential inference, migration, alias, endpoint fallback, or cross-route retry.

Compatibility profiles now own:

  • native/proxy tool-result conversion and deferred-tool support
  • provider output-token parameter names and curated GLM output ceilings
  • exact/tool-call/strict-synthetic reasoning replay policy
  • model-specific thinking controls and supported UI effort levels
  • Z.AI tool-stream capability

OpenAILegacy keeps direct-caller model inference when replay mode is omitted, while Pythinker factory callers pass explicit policy. Z.AI replay preserves only returned reasoning_content, in order, without synthesizing missing reasoning.

Curated Z.AI behavior

  • GLM-5.2: 1M context, 131,072 output, tiered high/max effort, preserved thinking, streamed tool calls when tools are present.
  • GLM-5.1 / 5 / 5-Turbo / 4.7: binary thinking, 131,072 output, streamed tool calls.
  • GLM-4.5-Air: binary thinking, 98,304 output, no tool streaming.
  • Unknown Z.AI models and local models named glm-* remain conservative.

Verification

  • make check-pythinker-core — exit 0; existing advisory core ty diagnostics only
  • make test-pythinker-core414 passed
  • make check-pythinker-code — Ruff/format/Pyright/ty clean
  • make test-pythinker-code7,035 passed, 9 skipped, 1 xfailed
  • Pythinker Code e2e — 65 passed, 4 skipped
  • Focused auth/compatibility/request/CLI/usage suite — 219 passed
  • OpenAI Legacy snapshots — 17 passed
  • Exact outbound Z.AI request matrix — 41 passed
  • git diff --check — clean
  • cd docs && npm run sync — generated changelog synchronized and idempotent
  • Active-source/test legacy identity scan — zero matches for managed:z-ai, z-ai/*, and api.z.ai/api/anthropic

Primary Z.AI documentation was revalidated for endpoint, Bearer auth, 1M/128K limits, thinking/effort mapping, exact preserved-reasoning replay, and tool streaming.

Risk review

  • C01–C15 manually reviewed: no blocking tripwire.
  • Unauthorized discovery saves nothing.
  • Degraded catalog fallback is typed and surfaced; stale route data is preserved during refresh failures.
  • Usage adapters do not inspect credentials or probe undocumented billing endpoints.
  • No raw reasoning, SSE payload, tool arguments, or credentials are logged.
  • No dependencies, telemetry endpoints, persisted compatibility fields, or unrelated refactors added.

Checklist

  • I have read the contributing and repository guidance.
  • I have added tests for success, failure, malformed input, coexistence, route isolation, and exact request behavior.
  • I have run the full package checks and tests listed above.
  • I have added an ## Unreleased changelog entry.
  • I updated provider, environment-variable, slash-command, architecture, and README documentation.
  • I regenerated docs/en/release-notes/changelog.md only via npm run sync.

Summary by CodeRabbit

  • New Features
    • Added distinct Z.AI Coding Plan and Z.AI API routes for login/logout, credentials, model identity, and managed model catalog syncing.
    • Updated CLI/shell routing for selecting the correct Z.AI mode and ensuring model/usage handling stays route-scoped.
    • Enhanced provider compatibility for thinking controls, curated GLM request limits, exact reasoning replay, and tool-stream support where available.
    • Thinking options now respect the resolved provider/model profile to constrain selectable levels.
  • Documentation
    • Updated README and Unreleased changelog entries with the new Z.AI routes, environment variables, and routing/capability details.

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1cd2526a-afef-49e6-94e8-adbc6fbd8f0b

📥 Commits

Reviewing files that changed from the base of the PR and between e90a552 and bbbe6f3.

📒 Files selected for processing (5)
  • src/pythinker_code/llm.py
  • tests/core/test_compaction_overflow.py
  • tests/core/test_create_llm.py
  • tests/core/test_model_switch_carryover.py
  • tests/core/test_z_ai_provider_requests.py

📝 Walkthrough

Walkthrough

Provider compatibility is centralized for thinking, tool, token, and reasoning behavior. Z.AI is split into independent coding and API routes with separate credentials, endpoints, catalogs, model identities, CLI commands, usage adapters, and UI handling.

Changes

Provider compatibility and request shaping

Layer / File(s) Summary
Compatibility profiles and request overrides
src/pythinker_code/provider_compatibility.py, src/pythinker_code/llm.py, tests/core/*
Provider profiles resolve thinking levels, token fields, tool handling, proxy behavior, and model-specific request overrides.
Reasoning replay and tool streaming
packages/pythinker-core/src/pythinker_core/contrib/chat_provider/*, src/pythinker_code/llm.py, tests/core/test_z_ai_provider_requests.py
OpenAI legacy requests support explicit reasoning replay modes, optional automatic effort, copied generation kwargs, and conditional tool streaming.

Z.AI routing and interfaces

Layer / File(s) Summary
Route-scoped authentication and catalogs
src/pythinker_code/auth/*, tests/auth/*
Z.AI coding and API routes use separate credentials, catalogs, providers, models, refresh results, login/logout flows, and persistence updates.
CLI, shell, and usage integration
src/pythinker_code/cli/*, src/pythinker_code/ui/shell/*, tests/cli/*, tests/ui/*
Separate Z.AI login/logout options, selectors, provider keys, environment variables, and notes-only usage adapters are wired through the interfaces.
Thinking controls and documentation
src/pythinker_code/soul/*, README.md, CHANGELOG.md, tests/ui_and_conv/*
Thinking-level selection receives provider compatibility context, and documentation describes the two Z.AI routes and model identities.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI
  participant ZAIAuth
  participant ZAIEndpoint
  participant Config
  User->>CLI: login --z-ai-coding or --z-ai-api
  CLI->>ZAIAuth: submit route-specific API key
  ZAIAuth->>ZAIEndpoint: discover route models
  ZAIEndpoint-->>ZAIAuth: return catalog result
  ZAIAuth->>Config: save route provider and models
  Config-->>User: expose route-specific model identity
Loading

Possibly related PRs

Suggested labels: enhancement

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.27% which is insufficient. The required threshold is 70.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title follows conventional commit format and accurately summarizes the Z.AI compatibility route changes.
Description check ✅ Passed The description covers the required sections, detailed changes, tests, docs, and checklist items; only the issue field is nonstandard.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/provider-compatibility-z-ai-routes

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 15, 2026

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pythinker_code/llm.py (1)

525-546: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Docstring is stale — scoping isn't limited to GPT-5 anymore.

"currently the OpenAI GPT-5 family" no longer matches reality: compatibility.supported_thinking_levels now also scopes Z.AI GLM models (see test_available_model_thinking_levels_prefers_profile_override). Worth a one-line update so future readers don't assume GPT-5 is still the only scoped family.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pythinker_code/llm.py` around lines 525 - 546, Update the docstring of
available_model_thinking_levels to describe provider-specific scoping
generically rather than limiting it to the OpenAI GPT-5 family, reflecting that
compatibility.supported_thinking_levels also covers Z.AI GLM models. Keep the
existing fallback and selection behavior unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/pythinker_code/llm.py`:
- Around line 76-78: Update the generation-kwargs logic in the affected helper
to access llm.compatibility.output_tokens_kwarg directly, removing the getattr
and None fallback. Then update the _fake_llm() test double in
test_compaction_overflow.py to provide a valid compatibility object matching the
LLM contract, while leaving supports_deferred_tool_search unchanged.

In `@tests/core/test_create_llm.py`:
- Around line 770-887: Rewrite the affected
tests—test_create_llm_zai_glm52_activates_explicit_profile_policy,
test_create_llm_zai_binary_model_maps_minimal_to_disabled, and
test_create_llm_self_hosted_qwen_uses_chat_template_thinking_toggle—to verify
observable request JSON instead of OpenAILegacy private attributes. Use the
existing respx request-capture pattern from test_z_ai_provider_requests.py,
covering the Z.AI thinking settings, reasoning effort, token limit, and Qwen
chat-template toggle, and remove assertions requiring reportPrivateUsage
ignores.

---

Outside diff comments:
In `@src/pythinker_code/llm.py`:
- Around line 525-546: Update the docstring of available_model_thinking_levels
to describe provider-specific scoping generically rather than limiting it to the
OpenAI GPT-5 family, reflecting that compatibility.supported_thinking_levels
also covers Z.AI GLM models. Keep the existing fallback and selection behavior
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2b06a17a-9356-44d8-9bc8-ed6616de5196

📥 Commits

Reviewing files that changed from the base of the PR and between dbc59bc and e90a552.

⛔ Files ignored due to path filters (5)
  • docs/en/configuration/env-vars.md is excluded by !docs/**
  • docs/en/configuration/providers.md is excluded by !docs/**
  • docs/en/customization/architecture.md is excluded by !docs/**
  • docs/en/reference/slash-commands.md is excluded by !docs/**
  • docs/en/release-notes/changelog.md is excluded by !docs/**
📒 Files selected for processing (29)
  • CHANGELOG.md
  • README.md
  • packages/pythinker-core/src/pythinker_core/contrib/chat_provider/common.py
  • packages/pythinker-core/src/pythinker_core/contrib/chat_provider/openai_legacy.py
  • packages/pythinker-core/tests/api_snapshot_tests/test_openai_legacy.py
  • src/pythinker_code/auth/__init__.py
  • src/pythinker_code/auth/platforms.py
  • src/pythinker_code/auth/z_ai.py
  • src/pythinker_code/cli/__init__.py
  • src/pythinker_code/llm.py
  • src/pythinker_code/provider_compatibility.py
  • src/pythinker_code/soul/pythinkersoul.py
  • src/pythinker_code/ui/shell/oauth.py
  • src/pythinker_code/ui/shell/slash.py
  • src/pythinker_code/ui/shell/usage_adapters/__init__.py
  • src/pythinker_code/ui/shell/usage_adapters/z_ai.py
  • tests/auth/test_platforms.py
  • tests/auth/test_z_ai_auth.py
  • tests/cli/test_z_ai_login_cli.py
  • tests/core/test_compaction_overflow.py
  • tests/core/test_create_llm.py
  • tests/core/test_model_thinking_levels.py
  • tests/core/test_provider_compatibility.py
  • tests/core/test_tool_search_gating.py
  • tests/core/test_z_ai_provider_requests.py
  • tests/ui/usage_adapters/test_provider_key_coverage.py
  • tests/ui/usage_adapters/test_z_ai.py
  • tests/ui_and_conv/test_model_profile_thinking.py
  • tests/ui_and_conv/test_openai_shell_login.py

Comment thread src/pythinker_code/llm.py Outdated
Comment thread tests/core/test_create_llm.py
@elkaix

elkaix commented Jul 15, 2026

Copy link
Copy Markdown
Member Author

Also updated the outside-diff available_model_thinking_levels() docstring in bbbe6f3: scoping is now described through the resolved provider/model profile rather than as GPT-5-only.

@elkaix
elkaix merged commit 10aedf2 into main Jul 15, 2026
43 checks passed
@elkaix
elkaix deleted the feat/provider-compatibility-z-ai-routes branch July 17, 2026 19:41
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.

1 participant