Skip to content

(MOT-3905) feat(provider-zai): add Z.AI (GLM) Chat Completions provider worker#443

Merged
andersonleal merged 4 commits into
mainfrom
feat/provider-zai
Jul 7, 2026
Merged

(MOT-3905) feat(provider-zai): add Z.AI (GLM) Chat Completions provider worker#443
andersonleal merged 4 commits into
mainfrom
feat/provider-zai

Conversation

@andersonleal

@andersonleal andersonleal commented Jul 7, 2026

Copy link
Copy Markdown
Collaborator

Summary

New provider-zai worker: Z.AI's GLM models (GLM-5.2, GLM-5-Turbo, GLM-4.7, and the wider lineup) behind llm-router, targeting the OpenAI-compatible Chat Completions API.

  • Endpoints: default upstream is the GLM Coding Plan endpoint (api.z.ai/api/coding/paas/v4) — subscription keys work with zero config, and they hard-fail (business code 1113) on the general endpoint. Pay-as-you-go operators override api_url to api.z.ai/api/paas/v4 for the full lineup.
  • Catalog: Z.AI exposes no models-listing endpoint, so a curated table carries ids, limits, capability flags, and pricing. Reconcile is credential-gated (no key → empty slice) and follows the resolved endpoint (Coding Plan subset vs full table).
  • GLM reasoning: explicit thinking {enabled|disabled} toggle on every current GLM model, reasoning_effort on GLM-5.2+ only, tool_stream on GLM-4.6+, max_tokens (Z.AI doesn't document max_completion_tokens), json_object-only structured output with a report-and-continue warning when a schema is requested.
  • Stream-path hardening over the forked baseline: UTF-8-boundary-safe chunk reassembly (CJK deltas split across transport chunks no longer corrupt to U+FFFD) and a cap on wire-controlled tool_call indexes.
  • Errors: Z.AI business code 1113 (billing wall / endpoint-restricted key) classifies as permanent so the router fails fast instead of retrying.
  • Repo wiring: create-tag.yml options, release.yml tag pattern (provider-zai/v*), root README modules row.

Testing

  • cargo fmt --check, cargo clippy --all-targets -D warnings clean; 76 unit tests (request assembly, SSE grammar incl. thinking/tool-call streaming, curated catalog invariants, error taxonomy, UTF-8 reassembly).
  • Golden wire-schema snapshots for the three provider::zai::* functions.
  • 5-scenario engine-backed integration suite (real engine + real router + TCP stub upstream): registration with token persistence and credential-gated catalog, end-to-end router::chat stream with cost fill, upstream 401 → auth_expired, curated-catalog reconcile, re-declare after router registry loss.

Fixes MOT-3905

Summary by CodeRabbit

  • New Features

    • Added a new provider-zai worker with streaming chat support, model refresh, and router registration.
    • Introduced curated model handling, request/response mapping, and SSE event processing for the new provider.
    • Added manifest, configuration, and permissions support for the worker.
  • Documentation

    • Updated the main README and added provider-specific docs and usage details.
  • Tests

    • Added schema snapshots, integration coverage, and unit tests for the new provider behavior.

Fork of provider-xai targeting Z.AI's OpenAI-compatible endpoint
(api.z.ai/api/paas/v4). Z.AI exposes no models-listing endpoint, so a
curated catalog (GLM 5.2 → 4.5 text families plus vision rows, with
docs-sourced limits and pricing) replaces live discovery — reconciled
through the router and gated on a configured credential.

GLM specifics: an explicit thinking {enabled|disabled} toggle on every
current GLM model, reasoning_effort on GLM-5.2+ only, tool_stream on
GLM-4.6+, max_tokens (Z.AI does not document max_completion_tokens),
and json_object-only structured output with a report-and-continue
warning when a schema is requested.

Also hardens the inherited stream path: UTF-8-boundary-safe chunk
reassembly (CJK output split across transport chunks no longer corrupts
to U+FFFD) and a cap on wire-controlled tool_call indexes.

Registers the worker in the release workflows and the root README
modules table.
Coding Plan subscription keys are the common case and hard-fail
(business code 1113) on the general pay-as-you-go endpoint, so the
default api_url is now api.z.ai/api/coding/paas/v4/chat/completions.

The catalog follows the resolved endpoint: the coding endpoint
reconciles only the plan's models (glm-5.2, glm-5-turbo, glm-4.7);
the general endpoint or a custom OpenAI-compatible server gets the
full curated table. Pay-as-you-go operators override api_url in the
llm-router config slice.
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
workers Ready Ready Preview, Comment Jul 7, 2026 7:34pm
workers-tech-spec Ready Ready Preview, Comment Jul 7, 2026 7:34pm

Request Review

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

skill-check — worker

0 verified, 38 skipped (no docs/).

Layer Result
structure
vale
ai
render

Four for four. Nicely done.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@andersonleal, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0c0ce241-756b-4780-8bc2-2352ee77d79b

📥 Commits

Reviewing files that changed from the base of the PR and between 5e34cf5 and 2cc0411.

📒 Files selected for processing (4)
  • provider-zai/README.md
  • provider-zai/src/curated.rs
  • provider-zai/src/discovery.rs
  • provider-zai/src/reasoning.rs
📝 Walkthrough

Walkthrough

Introduces a new provider-zai Rust worker crate implementing Z.AI/GLM chat completions behind llm-router: configuration resolution, curated model catalog, error classification, request/reasoning assembly, registration/state persistence, SSE streaming pipeline, wire format conversions, binary entrypoint, golden-schema and integration tests, plus CI/README updates.

Changes

provider-zai worker addition

Layer / File(s) Summary
Repository wiring, docs, and manifests
.github/workflows/create-tag.yml, .github/workflows/release.yml, README.md, provider-zai/.gitignore, provider-zai/Cargo.toml, provider-zai/README.md, provider-zai/build.rs, provider-zai/config.yaml, provider-zai/iii-permissions.yaml, provider-zai/iii.worker.yaml, provider-zai/prompts/identity.txt
Adds provider-zai to CI workflows and README, and defines crate metadata, permissions, worker manifest, config layout, and agent identity prompt.
Provider configuration and credentials
provider-zai/src/config.rs
Builds ZaiConfig (credential, model, max_tokens, api_url) from ProviderResolveResponse with validation and precedence rules.
Model catalog and discovery
provider-zai/src/curated.rs, provider-zai/src/discovery.rs
Defines the curated GLM model table and catalog selection/reconciliation logic used by refresh_models.
Error classification
provider-zai/src/errors.rs
Maps HTTP/JSON error bodies and router bus errors into a shared ErrorKind taxonomy, plus invalid-request error constructors.
Reasoning params and request assembly
provider-zai/src/reasoning.rs, provider-zai/src/request.rs
Computes thinking/reasoning_effort parameters and builds the Z.AI chat-completions request body and headers.
Registration, state, and router client
provider-zai/src/state.rs, provider-zai/src/router_client.rs, provider-zai/src/register.rs
Persists registration tokens, wraps router protocol calls, and implements declaration/backoff registration plus catalog-refresh wiring.
SSE parsing and streaming pipeline
provider-zai/src/sse.rs, provider-zai/src/upstream.rs, provider-zai/src/stream_fn.rs
Implements incremental SSE chunk handling, an upstream HTTP-to-channel bridge, and the streaming orchestration/pump with heartbeats.
Wire conversions, surface catalog, entrypoint
provider-zai/src/wire/..., provider-zai/src/surface.rs, provider-zai/src/lib.rs, provider-zai/src/main.rs, provider-zai/src/manifest.rs
Converts internal messages/tools to Z.AI wire shapes, defines the function schema catalog, and wires the crate library/binary entrypoint and manifest.
Golden schemas and integration tests
provider-zai/tests/golden/schemas/*, provider-zai/tests/schemas.rs, provider-zai/tests/support/mod.rs, provider-zai/tests/integration.rs
Adds golden schema snapshots, snapshot-validation tests, a golden-file test harness, and end-to-end integration tests against a real engine.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • iii-hq/workers#438: Both PRs modify the workflow_dispatch worker dropdown options in .github/workflows/create-tag.yml.

Suggested reviewers: sergiofilhowz

Poem

A new provider hops into the den,
Z.AI streams thoughts again and again 🐰
Catalogs curated, errors well-sniffed,
Tokens persisted, tests airtight and swift,
Hop, hop, hooray — ship it, my friends!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change: adding the new provider-zai Z.AI/GLM Chat Completions worker.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/provider-zai

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

clippy 1.96 denies items_after_test_module under -D warnings.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (4)
provider-zai/src/errors.rs (1)

59-61: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add a unit test for the 1113 business-code mapping.

This is called out as a headline feature of the PR ("Classifying Z.AI business code 1113 as a permanent error so routing fails fast"), and the code path is confirmed correct (Z.AI does send code as a JSON string), but no test in this file exercises it directly.

✅ Suggested test
     #[test]
     fn zai_envelope_codes_are_honored() {
         let body = r#"{"error":{"message":"This model's maximum context length is 400000 tokens.","type":"invalid_request_error","code":"context_length_exceeded"}}"#;
         assert_eq!(classify(Some(400), body), ErrorKind::ContextOverflow);

         let body = r#"{"error":{"message":"You exceeded your current quota.","type":"insufficient_quota","code":"insufficient_quota"}}"#;
         assert_eq!(classify(Some(429), body), ErrorKind::Permanent);

         let body = r#"{"error":{"message":"Incorrect API key provided.","type":"invalid_request_error","code":"invalid_api_key"}}"#;
         assert_eq!(classify(Some(401), body), ErrorKind::AuthExpired);
+
+        // Z.AI business code 1113: insufficient balance / no resource package,
+        // frequently surfaced with a 429 status — must not be treated as a
+        // retryable rate limit.
+        let body = r#"{"error":{"code":"1113","message":"Insufficient balance or no resource package. Please recharge."}}"#;
+        assert_eq!(classify(Some(429), body), ErrorKind::Permanent);
     }

Also applies to: 111-189

🤖 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 `@provider-zai/src/errors.rs` around lines 59 - 61, Add a focused unit test in
the errors module that exercises the business-code mapping for Z.AI code 1113
and asserts it returns ErrorKind::Permanent. Use the existing mapping entry in
the error classification logic (the match arm handling the string code) and
mirror the style of any nearby tests in this file so the new test directly
covers the JSON-string business code path.
provider-zai/src/upstream.rs (1)

92-98: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

SSE framing assumes LF-only boundaries and a space after data:.

Two spec-robustness gaps that only bite with certain OpenAI-compatible endpoints/proxies (your tests and stubs only exercise \n\n):

  • buf.find("\n\n") won't match a CRLF event boundary (\r\n\r\n contains no adjacent \n\n), so with CRLF framing events would never dispatch and content is lost.
  • strip_prefix("data: ") requires the single space, but per the SSE spec the space after data: is optional; a data:{...} line is silently dropped (and [DONE] missed).

Please confirm Z.AI's wire framing; if CRLF or spaceless data: are possible, harden both.

♻️ Optional-space handling for data_line
 fn data_line(block: &str) -> Option<&str> {
     block
         .lines()
-        .filter_map(|l| l.strip_prefix("data: "))
+        .filter_map(|l| l.strip_prefix("data:").map(|r| r.strip_prefix(' ').unwrap_or(r)))
         .next_back()
 }

Also applies to: 167-171

🤖 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 `@provider-zai/src/upstream.rs` around lines 92 - 98, The SSE parsing in
upstream.rs is too strict for some OpenAI-compatible endpoints: the event
splitter in the stream loop and the data_line helper only handle LF-only
boundaries and require a space after data:. Update the parsing around data_line
and the buffer scanning logic to accept CRLF event delimiters as well as
optional whitespace after data:, while preserving the existing behavior for
current tests and stubs.
provider-zai/src/sse.rs (1)

1-10: 🧹 Nitpick | 🔵 Trivial

CI clippy gate is red for this crate — please resolve before merge.

cargo clippy --all-targets --all-features -- -D warnings fails with 1 error in the provider-zai lib test build. I couldn't reproduce clippy in the review sandbox (no toolchain) and couldn't localize the offending lint to the three streaming files under review, so the error may live elsewhere in the crate. Please run the command locally and address it.

Want me to open a tracking issue for the clippy failure?

🤖 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 `@provider-zai/src/sse.rs` around lines 1 - 10, The crate-level clippy gate is
failing in the provider-zai lib test build, and the offending lint may be
outside the streaming files currently under review. Run cargo clippy
--all-targets --all-features -- -D warnings locally, identify the exact warning,
and fix it in the relevant symbol(s) such as the sse.rs state machine imports or
related provider-zai code. If the lint is in nearby helper code, adjust the
implementation to satisfy clippy without weakening the warning level.

Source: Pipeline failures

provider-zai/src/register.rs (1)

63-79: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Backoff/unreachable logic is correct but tightly coupled to the 0..5 / attempt < 4 pairing.

Every arm returns except the guarded retry arm, so the loop always exits via return and the trailing unreachable!() is sound — but if either the range or the guard bound is changed independently later, this becomes a silent panic trap. Low risk today; consider deriving the guard from the range bound (e.g., a named MAX_ATTEMPTS constant) for resilience against future edits.

🤖 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 `@provider-zai/src/register.rs` around lines 63 - 79, The retry/backoff logic
in persist_registration_token is correct today, but it is tightly coupled to the
hardcoded 0..5 loop and attempt < 4 guard. Refactor this to use a shared named
bound (for example, a MAX_ATTEMPTS-style constant) so the retry condition and
loop range stay in sync, and the trailing unreachable!() remains safe if the
attempt count is changed later.
🤖 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 `@provider-zai/src/curated.rs`:
- Around line 156-159: The Coding Plan model allowlist in CODING_PLAN_IDS is
missing glm-5.1, which causes it to be filtered out of the coding endpoint
picker. Update the curated model list in curated.rs where CODING_PLAN_IDS is
defined so it includes glm-5.1 alongside glm-5.2, glm-5-turbo, and glm-4.7,
keeping the existing coding-endpoint filtering behavior intact.

In `@provider-zai/src/discovery.rs`:
- Around line 50-87: Move make_refresh_models so it is defined before the
#[cfg(test)] mod tests block in discovery.rs; clippy’s items_after_test_module
lint is triggered by having a non-test item after the test module. Keep the
function body and signature unchanged, and place it alongside the other public
discovery helpers such as catalog_for and refresh_models so the module order
satisfies the lint.

In `@provider-zai/src/reasoning.rs`:
- Around line 36-38: The accepts_effort helper currently matches only model
names starting with glm-5.2, which does not align with the stated support for
GLM-5.2 and newer. Update accepts_effort in reasoning.rs to use a version-aware
comparison against the GLM family so later versions like glm-5.3 and glm-6.x are
also accepted, or otherwise tighten the wording/docs if the intent is only
glm-5.2.

In `@provider-zai/src/request.rs`:
- Around line 74-79: The authorization header construction in build_headers is
using cfg.credential_value directly inside format!, which Clippy rejects under
-D warnings. Introduce a local binding for the credential value in
build_headers, then use that binding in the Bearer token formatting so the
header creation compiles cleanly.

In `@provider-zai/src/wire/names.rs`:
- Around line 4-10: The tool-name helpers in encode_tool_name and
decode_tool_name are not bijective because literal double underscores collide
with encoded namespace separators. Update the names.rs logic so encode_tool_name
preserves enough information to round-trip uniquely, either by escaping literal
underscores before replacing namespace separators or by rejecting ids containing
"__", and make decode_tool_name reverse that scheme reliably.

---

Nitpick comments:
In `@provider-zai/src/errors.rs`:
- Around line 59-61: Add a focused unit test in the errors module that exercises
the business-code mapping for Z.AI code 1113 and asserts it returns
ErrorKind::Permanent. Use the existing mapping entry in the error classification
logic (the match arm handling the string code) and mirror the style of any
nearby tests in this file so the new test directly covers the JSON-string
business code path.

In `@provider-zai/src/register.rs`:
- Around line 63-79: The retry/backoff logic in persist_registration_token is
correct today, but it is tightly coupled to the hardcoded 0..5 loop and attempt
< 4 guard. Refactor this to use a shared named bound (for example, a
MAX_ATTEMPTS-style constant) so the retry condition and loop range stay in sync,
and the trailing unreachable!() remains safe if the attempt count is changed
later.

In `@provider-zai/src/sse.rs`:
- Around line 1-10: The crate-level clippy gate is failing in the provider-zai
lib test build, and the offending lint may be outside the streaming files
currently under review. Run cargo clippy --all-targets --all-features -- -D
warnings locally, identify the exact warning, and fix it in the relevant
symbol(s) such as the sse.rs state machine imports or related provider-zai code.
If the lint is in nearby helper code, adjust the implementation to satisfy
clippy without weakening the warning level.

In `@provider-zai/src/upstream.rs`:
- Around line 92-98: The SSE parsing in upstream.rs is too strict for some
OpenAI-compatible endpoints: the event splitter in the stream loop and the
data_line helper only handle LF-only boundaries and require a space after data:.
Update the parsing around data_line and the buffer scanning logic to accept CRLF
event delimiters as well as optional whitespace after data:, while preserving
the existing behavior for current tests and stubs.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9e781551-e2ea-441e-90bf-e7a338e5557d

📥 Commits

Reviewing files that changed from the base of the PR and between 4303c34 and 5e34cf5.

⛔ Files ignored due to path filters (1)
  • provider-zai/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (37)
  • .github/workflows/create-tag.yml
  • .github/workflows/release.yml
  • README.md
  • provider-zai/.gitignore
  • provider-zai/Cargo.toml
  • provider-zai/README.md
  • provider-zai/build.rs
  • provider-zai/config.yaml
  • provider-zai/iii-permissions.yaml
  • provider-zai/iii.worker.yaml
  • provider-zai/prompts/identity.txt
  • provider-zai/src/config.rs
  • provider-zai/src/curated.rs
  • provider-zai/src/discovery.rs
  • provider-zai/src/errors.rs
  • provider-zai/src/lib.rs
  • provider-zai/src/main.rs
  • provider-zai/src/manifest.rs
  • provider-zai/src/reasoning.rs
  • provider-zai/src/register.rs
  • provider-zai/src/request.rs
  • provider-zai/src/router_client.rs
  • provider-zai/src/sse.rs
  • provider-zai/src/state.rs
  • provider-zai/src/stream_fn.rs
  • provider-zai/src/surface.rs
  • provider-zai/src/upstream.rs
  • provider-zai/src/wire/messages.rs
  • provider-zai/src/wire/mod.rs
  • provider-zai/src/wire/names.rs
  • provider-zai/src/wire/tools.rs
  • provider-zai/tests/golden/schemas/provider.zai.on_router_ready.json
  • provider-zai/tests/golden/schemas/provider.zai.refresh_models.json
  • provider-zai/tests/golden/schemas/provider.zai.stream.json
  • provider-zai/tests/integration.rs
  • provider-zai/tests/schemas.rs
  • provider-zai/tests/support/mod.rs

Comment thread provider-zai/src/curated.rs Outdated
Comment thread provider-zai/src/discovery.rs Outdated
Comment thread provider-zai/src/reasoning.rs
Comment on lines +74 to +79
pub fn build_headers(cfg: &ZaiConfig) -> Vec<(&'static str, String)> {
vec![
("authorization", format!("Bearer {}", cfg.credential_value)),
("content-type", "application/json".to_string()),
]
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repo files of interest:\n'
git ls-files 'provider-zai/src/request.rs' 'Cargo.toml' 'provider-zai/Cargo.toml' '.cargo/config.toml' 'rust-toolchain.toml' 2>/dev/null || true

printf '\n--- provider-zai/src/request.rs ---\n'
cat -n provider-zai/src/request.rs

printf '\n--- Cargo.toml (root, if present) ---\n'
if [ -f Cargo.toml ]; then cat -n Cargo.toml; fi

printf '\n--- provider-zai/Cargo.toml (if present) ---\n'
if [ -f provider-zai/Cargo.toml ]; then cat -n provider-zai/Cargo.toml; fi

printf '\n--- .cargo/config.toml (if present) ---\n'
if [ -f .cargo/config.toml ]; then cat -n .cargo/config.toml; fi

printf '\n--- rust-toolchain.toml (if present) ---\n'
if [ -f rust-toolchain.toml ]; then cat -n rust-toolchain.toml; fi

Repository: iii-hq/workers

Length of output: 10105


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for lint configuration and the exact format usage.
rg -n --hidden --glob '!target' 'uninlined_format_args|-D warnings|deny\(warnings\)|clippy::' .
printf '\n--- occurrences of format!("Bearer {}" ---\n'
rg -n --hidden --glob '!target' 'format!\("Bearer \{\}"' provider-zai .

Repository: iii-hq/workers

Length of output: 3364


🌐 Web query:

Rust format string capture field access edition 2021 docs

💡 Result:

In Rust, the ability to capture variables directly in format strings was introduced in Rust 1.58.0 [1]. This feature allows you to use identifiers from the local scope inside curly braces, such as println!("Hello, {person}!");, which captures the local variable person [1]. Regarding field access (e.g., format!("{obj.field}")): this syntax is not supported as an implicit capture in standard format strings [1][2]. Format strings can only capture plain identifiers [1]. If you need to access a field, you must either assign the field value to a local variable first or use the explicit named argument style [1]: // Not supported: // println!("{person.name}"); // Recommended approach: let name = &person.name; println!("{name}"); // Alternative: println!("{}", person.name); While there have been community discussions and RFC proposals (such as RFC 3626) to extend implicit argument capturing to allow field access syntax (e.g., var.field), this has not been implemented as of July 2026 [2][3]. Note that the 2021 edition of Rust introduced other significant features like disjoint capture for closures, but implicit field access in format strings is not part of that edition's specification [4].

Citations:


Use a local binding here format!("Bearer {credential_value}") only works with a plain identifier, so cfg.credential_value can’t be captured directly. Bind it first: let credential_value = &cfg.credential_value; format!("Bearer {credential_value}"). CI runs clippy with -D warnings, so the current form blocks the build.

🧰 Tools
🪛 GitHub Actions: CI / provider-zai rust lint + test

[error] Command failed: cargo clippy --all-targets --all-features -- -D warnings (exit code 101). could not compile provider-zai (lib test) due to the clippy error.

🤖 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 `@provider-zai/src/request.rs` around lines 74 - 79, The authorization header
construction in build_headers is using cfg.credential_value directly inside
format!, which Clippy rejects under -D warnings. Introduce a local binding for
the credential value in build_headers, then use that binding in the Bearer token
formatting so the header creation compiles cleanly.

Source: Pipeline failures

Comment on lines +4 to +10
pub fn encode_tool_name(name: &str) -> String {
name.replace("::", "__")
}

pub fn decode_tool_name(name: &str) -> String {
name.replace("__", "::")
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether any registered iii function id contains a literal double underscore,
# which would collide with the "::" -> "__" encoding used here.
rg -nP '"[a-zA-Z0-9_-]*__[a-zA-Z0-9_-]*"' --type=rust -g '!provider-zai/**'

Repository: iii-hq/workers

Length of output: 152


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find encode/decode usage and any validation/schema around tool names.
rg -n "encode_tool_name|decode_tool_name|tool[_ -]?name|function[_ -]?id|name.*64|a-zA-Z0-9_-|__" provider-zai provider-* . \
  --glob '!**/target/**' --glob '!**/node_modules/**' --glob '!**/dist/**' --glob '!**/build/**' || true

Repository: iii-hq/workers

Length of output: 50371


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== matching files ==\n'
git ls-files 'provider-zai/**' 'provider-openai-codex/src/wire/names.rs' 'provider-openai-codex/src/sse.rs' 'acp/src/handler.rs'

printf '\n== names.rs ==\n'
sed -n '1,120p' provider-openai-codex/src/wire/names.rs

printf '\n== sse decode path ==\n'
sed -n '250,290p' provider-openai-codex/src/sse.rs

printf '\n== acp __-containing function ids ==\n'
sed -n '660,690p' acp/src/handler.rs

Repository: iii-hq/workers

Length of output: 5061


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== provider-zai function ids containing __ ==\n'
rg -n '"[^"]*__[^"]*"' provider-zai/src provider-zai/tests --glob '*.rs' || true

printf '\n== provider-zai wire usage ==\n'
sed -n '1,220p' provider-zai/src/wire/messages.rs
printf '\n---\n'
sed -n '1,120p' provider-zai/src/wire/tools.rs
printf '\n---\n'
sed -n '250,290p' provider-zai/src/sse.rs

Repository: iii-hq/workers

Length of output: 14370


Make tool-name encoding bijective provider-zai/src/wire/names.rs:4-10 maps both web::fetch and web__fetch to web__fetch, so decode_tool_name can return the wrong function id. Escape literal underscores or reject __ in ids.

🧰 Tools
🪛 GitHub Actions: CI / provider-zai rust lint + test

[error] Command failed: cargo clippy --all-targets --all-features -- -D warnings (exit code 101). could not compile provider-zai (lib test) due to the clippy error.

🤖 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 `@provider-zai/src/wire/names.rs` around lines 4 - 10, The tool-name helpers in
encode_tool_name and decode_tool_name are not bijective because literal double
underscores collide with encoded namespace separators. Update the names.rs logic
so encode_tool_name preserves enough information to round-trip uniquely, either
by escaping literal underscores before replacing namespace separators or by
rejecting ids containing "__", and make decode_tool_name reverse that scheme
reliably.

…ng_effort

The coding-tools guide documents glm-5.1, glm-5, and glm-4.5-air as valid
model codes on the coding endpoint alongside the featured GLM-5.2 /
GLM-5-Turbo / GLM-4.7 tier, so the Coding Plan slice now carries all six.

accepts_effort now parses the numeric GLM version instead of matching the
literal glm-5.2 prefix: the docs say "GLM-5.2 and newer", so glm-5.3 /
glm-6 qualify without a code change while glm-5-turbo and glm-5v-turbo
stay excluded.
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