mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-05 21:50:46 +08:00
refactor/code-cli
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
26508591f8 |
refactor(paintings): migrate to v2 data layer and UI (#15154)
Co-authored-by: jidan745le <420511176@qq.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: SuYao <sy20010504@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com> Signed-off-by: jidan745le <420511176@qq.com> Signed-off-by: suyao <sy20010504@gmail.com> |
||
|
|
26d877e0fa |
hotfix(image-generation): fix gpt-image-2 / gpt-image-1.5 failures and stuck pending placeholder (#14578)
<!-- 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 #14485 Fixes #14540 Fixes #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> |
||
|
|
6b14fcd5ce |
refactor: bump AI SDK deps and fix provider API host formatting
- Bump @ai-sdk/* packages to latest versions and update patches
- Fix newapi provider: defer API version suffix to build phase so gemini
endpoints get /v1beta instead of /v1
- Fix Azure provider: split host formatting so azure-anthropic (Claude)
endpoints don't get the /openai suffix meant for Azure OpenAI
- Re-add @ai-sdk/google getModelPath patch (includes("models/") check)
- Support azure-openai provider type in Claude Code agent service by
auto-constructing the /anthropic base URL for Claude models
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: suyao <sy20010504@gmail.com>
|