#22893: Add Z.AI image format support
agents
size: S
Cluster:
Wizard Enhancements and Config Fixes
Z.AI uses a different format for images than OpenAI:
- OpenAI: { content: [{ type: image_url, image_url: { url: ... } }] }
- Z.AI: { content: [...], files: [{ type: image, file: { url: ..., name: ... } }] }
This patch adds a streamFn wrapper that transforms OpenAI-style image_url content blocks to Z.AIs files array format at the payload level.
The wrapper is automatically applied for zai and z-ai providers.
## Summary
Describe the problem and fix in 2–5 bullets:
- Problem:
- Why it matters:
- What changed:
- What did NOT change (scope boundary):
## Change Type (select all)
- [ ] Bug fix
- [ ] Feature
- [ ] Refactor
- [ ] Docs
- [ ] Security hardening
- [ ] Chore/infra
## Scope (select all touched areas)
- [ ] Gateway / orchestration
- [ ] Skills / tool execution
- [ ] Auth / tokens
- [ ] Memory / storage
- [ ] Integrations
- [ ] API / contracts
- [ ] UI / DX
- [ ] CI/CD / infra
## Linked Issue/PR
- Closes #
- Related #
## User-visible / Behavior Changes
List user-visible changes (including defaults/config).
If none, write `None`.
## Security Impact (required)
- New permissions/capabilities? (`Yes/No`)
- Secrets/tokens handling changed? (`Yes/No`)
- New/changed network calls? (`Yes/No`)
- Command/tool execution surface changed? (`Yes/No`)
- Data access scope changed? (`Yes/No`)
- If any `Yes`, explain risk + mitigation:
## Repro + Verification
### Environment
- OS:
- Runtime/container:
- Model/provider:
- Integration/channel (if any):
- Relevant config (redacted):
### Steps
1.
2.
3.
### Expected
-
### Actual
-
## Evidence
Attach at least one:
- [ ] Failing test/log before + passing after
- [ ] Trace/log snippets
- [ ] Screenshot/recording
- [ ] Perf numbers (if relevant)
## Human Verification (required)
What you personally verified (not just CI), and how:
- Verified scenarios:
- Edge cases checked:
- What you did **not** verify:
## Compatibility / Migration
- Backward compatible? (`Yes/No`)
- Config/env changes? (`Yes/No`)
- Migration needed? (`Yes/No`)
- If yes, exact upgrade steps:
## Failure Recovery (if this breaks)
- How to disable/revert this change quickly:
- Files/config to restore:
- Known bad symptoms reviewers should watch for:
## Risks and Mitigations
List only real risks for this PR. Add/remove entries as needed. If none, write `None`.
- Risk:
- Mitigation:
<!-- greptile_comment -->
<h3>Greptile Summary</h3>
This PR adds a `createZaiImageFormatWrapper` function to transform OpenAI-style `image_url` content blocks into Z.AI's `files` array format. The wrapper hooks into the `onPayload` callback to rewrite messages before they're sent to Z.AI, moving image data from inline content blocks to a top-level `files` array on each message. It is applied for `zai` and `z-ai` providers alongside the existing `createZaiToolStreamWrapper`.
- Adds image format translation for Z.AI providers, converting `{ type: "image_url", image_url: { url } }` blocks to `{ type: "image", file: { url, name } }` entries in a `files` array
- MIME type is extracted from data URIs to generate appropriate file extensions; HTTP URLs default to `image.png`
- When all content blocks are images, a fallback empty text block `{ type: "text", text: "" }` is inserted
- **Issue found**: `image_url` blocks with a missing/empty URL are silently dropped from the message (neither added to `files` nor preserved in content)
- No tests were added for the new wrapper, though the existing Z.AI test file (`extra-params.zai-tool-stream.test.ts`) provides a pattern that could be followed
<h3>Confidence Score: 3/5</h3>
- Low-risk feature addition scoped to Z.AI providers only, but has a data-loss edge case and no test coverage
- The change is well-scoped (only affects zai/z-ai providers) and follows established patterns in the file (onPayload wrapper). However, there's a logic issue where malformed image_url blocks can be silently dropped from messages, and the PR adds no tests despite the existing test infrastructure supporting this pattern. The comment-only change on line 73 is trivial and fine.
- `src/agents/pi-embedded-runner/extra-params.ts` — the `createZaiImageFormatWrapper` function has a logic gap around malformed `image_url` blocks
<sub>Last reviewed commit: 8322565</sub>
<!-- greptile_other_comments_section -->
<sub>(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!</sub>
<!-- /greptile_comment -->
Most Similar PRs
#22909: feat(zai): add image format wrapper for Z.AI API
by AlexanderWillner · 2026-02-21
86.3%
#16346: feat: support image attachments in OpenAI chat completions endpoint
by sh1nj1 · 2026-02-14
74.9%
#16018: feat: add image support to /v1/chat/completions endpoint
by sebastienb · 2026-02-14
73.1%
#19326: Agents: improve z.ai GLM-5 integration and failover
by gabrielespinheira · 2026-02-17
72.4%
#13814: feat(web-search): add ZAI Search (zsearch) provider
by strelov1 · 2026-02-11
71.3%
#18219: fix: validate base64 image data before sending to LLM APIs
by Grynn · 2026-02-16
70.8%
#19394: fix(agents): normalize tool call arguments dropped to {} (#19261)
by DevvGwardo · 2026-02-17
70.4%
#15327: feat:(models): discover ZAI models dynamically for GLM-5 support [A...
by vincentkoc · 2026-02-13
70.2%
#22175: fix: support xai tool stream and compat flags
by ShunsukeHayashi · 2026-02-20
70.1%
#22941: feat: add ZHIPU provider + doctor chat check (Phase 1A)
by feelega · 2026-02-21
69.9%