<!-- Template from
https://github.com/kubevirt/kubevirt/blob/main/.github/PULL_REQUEST_TEMPLATE.md?-->
<!-- Thanks for sending a pull request! Here are some tips for you:
1. Consider creating this PR as draft:
https://github.com/CherryHQ/cherry-studio/blob/main/CONTRIBUTING.md
-->
<!--
🚨 Branch Strategy Change (Effective April 3, 2026) 🚨
The `main` branch is now under CODE FREEZE.
- main branch: Only accepts critical bug fixes via `hotfix/*` branches.
Fix PRs must be minimal in scope and must not include any refactoring
code.
- v2 branch: All new features, refactoring, and optimizations should be
submitted to the `v2` branch.
If you are submitting a bug fix to main, please ensure your PR is from a
`hotfix/*` branch.
-->
### What this PR does
Before this PR:
- `gpt-image-2` (and any image-edit request routed through AiHubMix /
NewAPI / CherryIN) failed with `common.UnmarshalBodyReusable failed:
bind request body failed: invalid character '-' in numeric literal`. The
providers hard-coded `Content-Type: application/json` in
`authHeaders()`, but `OpenAICompatibleImageModel.doGenerate` uses
`postFormDataToApi` for `/images/edits` and relies on `fetch` to
auto-set `multipart/form-data; boundary=...`. Forcing JSON made the
server receive a multipart body under a JSON content-type and choke on
the leading `--boundary`.
- Even when the request reached the server, image uploads failed with
`unsupported mimetype ('image')` because `collectImagesFromMessages`
built data URIs using `block.file.type` — which is the `FileType` enum
(`"image"`), not a MIME type.
- Some saved/pasted images produced `ENOENT: ... <uuid>jpg` because
`saveBase64Image` / `savePastedImage` return `ext` without the leading
dot, and the caller was concatenating `file.id + file.ext`.
- After a successful image generation, a `BeatLoader` placeholder kept
spinning next to the finished image. `fetchImageGeneration` only emitted
`LLM_RESPONSE_COMPLETE`; the trailing loader in `Blocks/index.tsx` is
driven by `isMessageProcessing(message)`, which is only cleared when
`onComplete` runs on `BLOCK_COMPLETE`.
- If a `file` chunk arrived without a preceding `IMAGE_CREATED`, the
initial UNKNOWN placeholder block was never claimed, leaving an orphan
spinner below the image.
- `gpt-image-2` / `gpt-image-1.5` / `gpt-image-1*` / `chatgpt-image-*`
generations through any OpenAI-compatible provider still failed with
`400 Unknown parameter: 'response_format'` (see #14485, #14540, #14579).
The earlier `@ai-sdk/openai@3.0.53` patch (#14488) only covered
`OpenAIImageModel` (direct OpenAI + Azure via `@ai-sdk/azure`);
`OpenAICompatibleImageModel.doGenerate` unconditionally added
`response_format: "b64_json"` to the `/images/generations` body, so
every provider whose image model is wired to
`OpenAICompatibleImageModel` kept hitting the 400 — including `type:
'openai-compatible'` and the AiHubMix / NewAPI / CherryIN gateway image
models in this repo.
After this PR:
- `aihubmix-provider`, `newapi-provider`, and `cherryin-provider` no
longer hard-code `Content-Type` in auth headers. `postJsonToApi` still
defaults JSON for other endpoints, and `postFormDataToApi` is free to
let `fetch` set `multipart/form-data; boundary=...` for `/images/edits`.
- `collectImagesFromMessages` reads via
`window.api.file.base64Image(block.file.name)`, which returns a correct
`data:image/<ext>;base64,...` URI (with `jpg → jpeg` normalization) and
uses the consistent on-disk filename regardless of whether the stored
`ext` has a leading dot.
- `fetchImageGeneration` now emits `ChunkType.BLOCK_COMPLETE` before
`LLM_RESPONSE_COMPLETE`, so `onComplete` runs and the assistant message
transitions out of `PROCESSING`.
- `onImageGenerated` reuses the initial UNKNOWN placeholder when one
exists, so a `file` chunk without a prior `IMAGE_CREATED` no longer
leaves an orphan spinner.
- `gpt-image-2` is registered in `IMAGE_ENHANCEMENT_MODELS`.
- `patches/@ai-sdk__openai-compatible@2.0.37.patch` is extended with the
same `hasDefaultResponseFormat` guard that `@ai-sdk/openai` already
uses. `OpenAICompatibleImageModel.doGenerate` now spreads
`response_format: "b64_json"` only when the model ID does **not** start
with `chatgpt-image-`, `gpt-image-1-mini`, `gpt-image-1.5`,
`gpt-image-1`, or `gpt-image-2`. This fixes#14485, #14540, #14579 for
`openai-compatible` typed providers and the AiHubMix / NewAPI / CherryIN
gateways.
Fixes#14485Fixes#14540Fixes#14579
### Why we need it and why it was done in this way
The following tradeoffs were made:
- The `ext`-with-or-without-dot inconsistency exists in historical DB
records, so patching only `FileStorage.ts` would not help already-saved
rows. The fix uses `file.name` at the consumer side — always the real
on-disk filename across every save path — without touching the storage
layer.
- The provider `authHeaders()` change could theoretically affect
non-JSON, non-multipart requests, but all SDK models in use go through
`postJsonToApi`, which already defaults `Content-Type: application/json`
internally, so behavior is preserved.
- Extending the `@ai-sdk/openai-compatible` patch rather than overriding
`response_format` per-provider keeps the fix in one place and
automatically covers every caller of `OpenAICompatibleImageModel`
(current and future). The guard list mirrors the upstream
`@ai-sdk/openai` list, so the two stay in sync.
The following alternatives were considered:
- Normalizing `ext` in `FileStorage.saveBase64Image` /
`savePastedImage`: rejected because it would not repair existing records
and could regress other callers that have compensated for the dotless
form.
- Overriding `Content-Type` only inside the image model factory:
rejected as more surface area than needed; the global `authHeaders()`
already defers to `postJsonToApi` defaults.
- Stripping `response_format` in each custom provider (AiHubMix / NewAPI
/ CherryIN) instead of patching the SDK: rejected — it would leave
`type: 'openai-compatible'` users still broken and duplicate the
model-prefix list in three places.
Links to places where the discussion took place: #14485, #14540, #14579,
#14488
### Breaking changes
<!-- optional -->
None.
### Special notes for your reviewer
<!-- optional -->
Scope is intentionally minimal for the main branch freeze: no
refactoring, no new abstractions. Surface changes:
- `authHeaders()` in three custom providers (drops one hard-coded
header).
- `collectImagesFromMessages` (one helper, swaps input building).
- `fetchImageGeneration` (one extra chunk emission).
- `onImageGenerated` (placeholder-claim fallback).
- `IMAGE_ENHANCEMENT_MODELS` (one new entry).
- `patches/@ai-sdk__openai-compatible@2.0.37.patch` (adds
`hasDefaultResponseFormat` helper + conditional spread of
`response_format`; mirrors `@ai-sdk/openai@3.0.53` patch).
Drop the openai-compatible patch addition once
`@ai-sdk/openai-compatible` ships the equivalent check upstream.
### Checklist
This checklist is not enforcing, but it's a reminder of items that could
be relevant to every PR.
Approvers are expected to review this list.
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: [Write code that humans can
understand](https://en.wikiquote.org/wiki/Martin_Fowler#code-for-humans)
and [Keep it simple](https://en.wikipedia.org/wiki/KISS_principle)
- [x] Refactor: You have [left the code cleaner than you found it (Boy
Scout
Rule)](https://learning.oreilly.com/library/view/97-things-every/9780596809515/ch08.html)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: A [user-guide update](https://docs.cherry-ai.com)
was considered and is present (link) or not required. Check this only
when the PR introduces or changes a user-facing feature or behavior.
- [x] Self-review: I have reviewed my own code (e.g., via
[`/gh-pr-review`](/.claude/skills/gh-pr-review/SKILL.md), `gh pr diff`,
or GitHub UI) before requesting review from others
### Release note
<!-- Write your release note:
1. Enter your extended release note in the below block. If the PR
requires additional action from users switching to the new release,
include the string "action required".
2. If no release note is required, just write "NONE".
3. Only include user-facing changes (new features, bug fixes visible to
users, UI changes, behavior changes). For CI, maintenance, internal
refactoring, build tooling, or other non-user-facing work, write "NONE".
-->
```release-note
Fix image generation and editing for gpt-image-2 / gpt-image-1.5 / gpt-image-1* / chatgpt-image-* across AiHubMix, NewAPI, CherryIN, Azure OpenAI, and other OpenAI-compatible providers: requests no longer fail with `Unknown parameter: 'response_format'`, multipart content-type, or mimetype errors; generated/pasted images are resolved correctly; and the loading placeholder disappears once the image is rendered.
```
---------
Signed-off-by: suyao <sy20010504@gmail.com>
<!-- Template from
https://github.com/kubevirt/kubevirt/blob/main/.github/PULL_REQUEST_TEMPLATE.md?-->
<!-- Thanks for sending a pull request! Here are some tips for you:
1. Consider creating this PR as draft:
https://github.com/CherryHQ/cherry-studio/blob/main/CONTRIBUTING.md
-->
<!--
⚠️ Important: Redux/IndexedDB Data-Changing Feature PRs Temporarily On
Hold ⚠️
Please note: For our current development cycle, we are not accepting
feature Pull Requests that introduce changes to Redux data models or
IndexedDB schemas.
While we value your contributions, PRs of this nature will be blocked
without merge. We welcome all other contributions (bug fixes, perf
enhancements, docs, etc.). Thank you!
Once version 2.0.0 is released, we will resume reviewing feature PRs.
-->
### What this PR does
regular upgrade
---------
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: icarus <eurfelux@gmail.com>
* fix: update deepseek dependency to version 1.0.31 and improve provider creation logging
* chore
* feat: deepseek official hybrid infer
* fix: deepseek-v3.2-speciale tooluse and reasoning
* fix: 添加固定推理模型支持并更新相关逻辑
* refactor: simplify logic
* feat: aihubmix
* all system_providers
* feat: cherryin
* temp fix
* fix: address PR review feedback for DeepSeek v3.2 implementation
- Add default case in buildCherryInProviderOptions to fallback to genericProviderOptions
- Add clarifying comment for switch fall-through in reasoning.ts
- Add comprehensive test coverage for isFixedReasoningModel (negative cases)
- Add test coverage for new provider whitelist (deepseek, cherryin, new-api, aihubmix, sophnet, dmxapi)
- Add test coverage for isDeepSeekHybridInferenceModel prefix patterns
- Verify function calling logic works correctly via regex matching after removing provider-based checks
- Use includes() for deepseek-chat matching to support potential variants
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
* fix: remove unnecessary fall-through case for unknown providers in getReasoningEffort
---------
Co-authored-by: Claude <noreply@anthropic.com>
* fix(i18n): remove image-generation translations and clarify endpoint type
Update English locale to specify OpenAI for image generation
Add comments to clarify image-generation endpoint type relationship
* fix(i18n): correct portuguese translations in pt-pt.json
* feat: add endpoint type support for cherryin provider
* chore: bump @cherrystudio/ai-sdk-provider version to 0.1.1
* chore: bump ai-sdk-provider version to 0.1.3
* feat: add @cherrystudio/ai-sdk-provider package and integrate with CherryIN
- Introduced the @cherrystudio/ai-sdk-provider package, providing a CherryIN routing solution for AI SDKs.
- Updated configuration files to include the new provider.
- Enhanced provider initialization to support CherryIN as a new AI provider.
- Added README and documentation for usage instructions.
* chore: remove deprecated @ai-sdk/google dependency and clean up package files
- Removed the @ai-sdk/google dependency from package.json and yarn.lock as it is no longer needed.
- Simplified the createGeminiModel function in index.ts for better readability and maintainability.
* feat: update CherryIN provider integration and dependencies
- Updated @ai-sdk/anthropic and @ai-sdk/google dependencies to their latest versions in package.json and yarn.lock.
- Introduced a new CherryInProvider implementation in cherryin-provider.ts, enhancing support for CherryIN API.
- Refactored provider initialization to include CherryIN as a supported provider in schemas.ts and options.ts.
- Updated web search plugin to utilize the new CherryIN provider capabilities.
- Cleaned up and organized imports across various files for better maintainability.
* chore: clean up tsconfig and remove unnecessary nullish coalescing in CherryIn provider
- Simplified tsconfig.json by consolidating exclude and include arrays.
- Removed nullish coalescing in cherryin-provider.ts for cleaner header handling in model initialization.
* fix: remove console.log from webSearchPlugin to clean up code
- Eliminated unnecessary console.log statement in the webSearchPlugin to enhance code clarity and maintainability.
* fix(i18n): Auto update translations for PR #10715
* chore: update yarn.lock with new package versions and dependencies
- Added new versions for @ai-sdk/anthropic, @ai-sdk/google, @ai-sdk/provider-utils, and eventsource-parser.
- Updated dependencies and peerDependencies for the newly added packages.
* feat: enhance CherryIn provider with chat model support and custom fetch logic
- Introduced CherryInOpenAIChatLanguageModel to handle chat-specific configurations.
- Updated createChatModel to support CherryIn chat models.
- Modified webSearchPlugin to accommodate both 'cherryin' and 'cherryin-chat' provider IDs.
- Added 'cherryin-chat' provider ID to schemas and provider configurations.
- Adjusted provider factory to correctly set provider ID for chat mode.
- Enhanced web search utility to handle CherryIn chat models.
* 🐛 fix: resolve cherryin provider lint errors and web search config
- Add fetch global variable declaration for ai-sdk-provider in oxlintrc
- Fix endpoint_type mapping fallback logic in cherryin provider
- Add error handling comment for better code readability
* chore(dependencies): update AI SDK packages and patches
- Added new versions for @ai-sdk/anthropic, @ai-sdk/google, and @ai-sdk/provider-utils in yarn.lock.
- Updated @ai-sdk/openai dependency to use a patch version in package.json.
- Included @cherrystudio/ai-sdk-provider as a new dependency in the workspace.
* chore(dependencies): update peer dependencies and installation instructions
- Removed specific versions of @ai-sdk/anthropic and @ai-sdk/google from package.json and yarn.lock.
- Updated peer dependencies in package.json to include @ai-sdk/anthropic, @ai-sdk/google, and @ai-sdk/openai.
- Revised installation instructions in README.md to reflect the new dependencies.
---------
Co-authored-by: GitHub Action <action@github.com>