mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-06 22:55:56 +08:00
refactor/code-cli
40 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9b9570116a | refactor(db): replace libsql with better-sqlite3 + sqlite-vec (#16626) | ||
|
|
65c54e5ce5 |
chore(deps): bump @openrouter/ai-sdk-provider to ^2.10.0 (#16467)
Signed-off-by: Robinnnnn <12162433+Robinnnnn@users.noreply.github.com> |
||
|
|
611944599f |
refactor(deps): replace lodash with es-toolkit/compat and drop it (#16528)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: suyao <sy20010504@gmail.com> |
||
|
|
0665ce7270 |
fix(anthropic): strip unsupported JSON Schema keywords from tool schemas (#16480)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com> Signed-off-by: suyao <sy20010504@gmail.com> |
||
|
|
eb2622e9af |
refactor(ui): remove antd dependency (#16336)
Co-authored-by: gujiaming <52187003+AtomsH4@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> Signed-off-by: kangfenmao <kangfenmao@qq.com> Signed-off-by: gujiaming <52187003+AtomsH4@users.noreply.github.com> |
||
|
|
22ffb62f62 |
feat(richeditor): native @tiptap/markdown AST on Tiptap 3.26.1 (#16118)
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com> Signed-off-by: suyao <sy20010504@gmail.com> |
||
|
|
1382a8dd7c |
feat(knowledge): route embeddings and reranking through the AI service (#15796)
### What this PR does Before this PR: - Knowledge embeddings and reranking ran through the legacy embedjs-based knowledgeV1 stack with their own provider clients, independent of the app's AI service. - File-processing intake accepted several heterogeneous input shapes, and knowledge file items were tracked by FileEntry ids, coupling file content to the file-manager entry/cache. After this PR: - Embeddings and reranking are routed through the unified `AiService` (with cherryin rerank support) and guarded by strict embedding-dimension validation that rejects stale/mismatched vectors. - File-processing intake is collapsed to a single path-based model; knowledge file items are stored by base-relative path under the knowledge-base directory, and v1 uploads are copied into the v2 base dir during migration so migrated items stay reindexable/restorable. - Legacy `knowledgeV1` is removed; the orchestration services were renamed to `KnowledgeService` / `FileProcessingService`. - Chat -> knowledge attach is temporarily disconnected (tracked TODO) while the v2 file-manager bridge is rebuilt. Fixes #N/A (no linked issue) ### Why we need it and why it was done in this way Routing embeddings/rerank through `AiService` unifies provider handling and credentials and removes the parallel embedjs client stack and its v1 coupling. Storing knowledge files by base-relative path (instead of FileEntry ids) makes each knowledge base self-contained and portable. The following tradeoffs were made: - A large, coordinated refactor plus a migration step that physically copies v1 uploads into the v2 base dir, in exchange for removing the parallel client stack and making bases self-contained. - Base-relative path storage required a fail-fast/dedup strategy for same-named files and a guard for blank legacy filenames. The following alternatives were considered: - Keeping the embedjs stack behind an adapter — rejected; perpetuates the parallel client and v1 coupling. - Keeping FileEntry-id storage — rejected; couples knowledge files to the file-manager cache and blocks portability. ### Breaking changes - `knowledgeV1` is removed. Legacy v1 knowledge data reaches v2 only through the v2 migrators; there is no v1 fallback. - The v2 knowledge HTTP API (API gateway) now returns v2-native per-entry fields (`embeddingModelId`, `createdAt` on base entries; `chunkId`, `scoreKind`, `rank` on search results). The response envelope (`knowledge_bases`, `searched_bases`, `total`) is unchanged. See `v2-refactor-temp/docs/breaking-changes/2026-06-05-knowledge-api-v2.md`. ### Special notes for your reviewer - This branch went through several rounds of multi-agent code review. The most recent 6 commits address review findings: directory-import path collisions, migrated-file source copying + blank `relativePath` guard, addItems rollback error preservation, eager `document_to_markdown` output-target validation, a `CompletedKnowledgeBase` type guard, and breaking-changes doc corrections. - Chat -> knowledge attach is intentionally disconnected for now (tracked in `v2-refactor-temp/docs/knowledge/knowledge-todo.md`). - Local full `pnpm lint`/`pnpm test` was not run per the project's review conventions; please rely on CI / `pnpm build:check`. ### Checklist - [x] Branch: This PR targets the correct branch — `main` for active development, `v1` for v1 maintenance fixes - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [ ] Documentation: A user-guide update was considered and is present (link) or not required. - [x] Self-review: I have reviewed my own code before requesting review from others ### Release note ```release-note NONE ``` --------- Signed-off-by: eeee0717 <chentao020717Work@outlook.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com> |
||
|
|
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> |
||
|
|
fa5bbb7607 | Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 | ||
|
|
0b697210bd |
fix: support Grok 4.3 reasoning effort in xAI responses (#15137)
### What this PR does Before this PR: - Grok 4.3 did not fully support reasoning effort through the xAI responses path. - Cherry Studio did not expose the Grok 4.3 reasoning options consistently in model configuration. - The local @ai-sdk/xai patch could fail pnpm install after manual patch edits. After this PR: - Grok 4.3 correctly maps `reasoning_effort` to xAI responses with `none`, `low`, `medium`, and `high`. - The renderer exposes Grok 4.3 as a supported reasoning model with the correct option set. - The local @ai-sdk/xai patch is regenerated and narrowed to the responses path so pnpm install succeeds. Fixes # N/A ### Why we need it and why it was done in this way The following tradeoffs were made: - The change is scoped to the xAI responses path because Grok is already routed to `xai-responses` in this repository. - A local patch is still required because the latest stable `@ai-sdk/xai` release does not yet support `none` for xAI responses `reasoningEffort`. - The patch was narrowed to responses-only to avoid widening behavior for the base xAI chat path. The following alternatives were considered: - Upgrading directly to the latest stable `@ai-sdk/xai`, but the latest stable release still does not support `none` for responses `reasoningEffort`. - Broadening the patch to cover xAI chat options as well, but that would expand behavior beyond the required Grok 4.3 responses path. Links to places where the discussion took place: None ### Breaking changes None. If this PR introduces breaking changes, please describe the changes and the impact on users. ### Special notes for your reviewer - Focused validation passed with `pnpm install`, `pnpm typecheck:web`, and targeted Vitest suites for xAI/Grok reasoning and model config. - Full `pnpm test` on Windows still has unrelated baseline failures outside this change set. ### 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 - [x] 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 Fixed Grok 4.3 reasoning effort support in xAI responses so Cherry Studio now correctly exposes and applies the `none`, `low`, `medium`, and `high` reasoning levels. ``` --------- Signed-off-by: ousugo <dkzydkzyxh@gmail.com> Co-authored-by: ousugo <dkzydkzyxh@gmail.com> Co-authored-by: SuYao <sy20010504@gmail.com> |
||
|
|
7b556cf786 | Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 | ||
|
|
72bb96ed71 |
fix(knowledge): preserve HTTP URLs in knowledge base documents (#14983)
### What this PR does Before this PR: When adding Markdown documents to a knowledge base, all HTTP/HTTPS/FTP URLs are silently stripped from the indexed content. Searching the knowledge base returns text with all links removed. After this PR: URLs in knowledge base documents are preserved in the indexed chunks, so searches return the full original content including links. Fixes #14956 #14962 ### Why we need it and why it was done in this way **Root cause:** The `@cherrystudio/embedjs-loader-web` package (forked from upstream `@llm-tools/embedjs`) contains a regex in `WebLoader` that unconditionally strips all URLs from text content: ```js .replace(/(?:https?|ftp):\/\/[\n\S]+/g, '') ``` This was originally designed for web scraping — removing noisy navigation/footer URLs when crawling web pages. In the upstream's primary use case (crawling web pages for RAG), this is reasonable behavior since navigation bars, footers, and sidebars produce many irrelevant URLs that add noise to embeddings. So this is not a bug in the upstream library — it's a difference in usage context. Cherry Studio uses these loaders for user-provided Markdown documents where URLs are intentional, meaningful content authored by the user. However, `MarkdownLoader` delegates to `WebLoader` (Markdown → HTML via micromark → WebLoader), so Markdown file URLs get caught by the same regex and removed. The `CherryHQ/embed-js` fork inherited this behavior as-is from upstream `@llm-tools/embedjs` — the fork only changed the `@llm-tools/` namespace to `@cherrystudio/` with no functional modifications to the loader logic. **Why pnpm patch instead of fixing the fork repo:** 1. This is not an upstream bug but a usage context mismatch — submitting an upstream PR to change this behavior could break the upstream's intended web-scraping use case. 2. The `CherryHQ/embed-js` fork periodically syncs with upstream (e.g., `chore: sync to upstream` commits), so any fork-side change would be overwritten on next sync. 3. The fork has been intentionally kept minimal — only namespace renames — to make syncing straightforward. 4. Using `pnpm patch` is consistent with the project's existing pattern (22+ patches already in `patches/`). The following alternatives were considered: - Fixing the `CherryHQ/embed-js` fork directly — rejected due to the sync-overwrite risk described above. - Adding a `keepUrls` constructor option to `WebLoader` — rejected as more invasive than needed for a hotfix. ### Breaking changes None. The only behavior change is that URLs are now preserved in knowledge base chunks instead of being silently removed. This is the expected/correct behavior. ### Special notes for your reviewer - The patch removes the URL-stripping regex from both `web-loader.js` (ESM) and `web-loader.cjs` (CommonJS). - The `MarkdownLoader` bracket-stripping regex (`[[\](){}]`) is a separate cosmetic issue not addressed in this hotfix — with URLs preserved, `text [https://url]` becomes `text https://url` after bracket stripping, so the URL itself is intact. - Users who have already added Markdown files to their knowledge base will need to re-index those files to get URLs in the indexed content. ### Checklist - [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 ```release-note Fixed a bug where all HTTP/HTTPS/FTP URLs were stripped from Markdown documents when adding them to a knowledge base, causing search results to lose all links. ``` --------- Signed-off-by: raymond <13162938362@163.com> Co-authored-by: SuYao <sy20010504@gmail.com> |
||
|
|
1afd70b372 | Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 | ||
|
|
794698f527 |
fix: refresh openrouter provider patch (#14750)
<!-- 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: The `@openrouter/ai-sdk-provider` pnpm patch no longer applied cleanly to the current `2.3.3` package contents, causing install-time patch warnings. After this PR: The patch has been refreshed for the current package layout, keeps `strictJsonSchema` support for OpenRouter tool schemas, strips that internal option from API request bodies, and updates the pnpm patch hash. <!-- (optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: --> Fixes # ### Why we need it and why it was done in this way The following tradeoffs were made: This keeps the dependency version unchanged and only refreshes the existing patch, minimizing scope for the `main` branch. The following alternatives were considered: Upgrading `@openrouter/ai-sdk-provider` was avoided because this PR only needs to restore the existing patch behavior. Links to places where the discussion took place: N/A ### Breaking changes None. If this PR introduces breaking changes, please describe the changes and the impact on users. ### Special notes for your reviewer Validated with `pnpm install --ignore-scripts`, `pnpm lint`, `pnpm test`, `pnpm format`, and `git diff --check`. ### 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 NONE ``` Signed-off-by: zhibisora <73344387+zhibisora@users.noreply.github.com> |
||
|
|
7ddceb698f |
fix(deps): omit max_tokens for non-Anthropic models in @ai-sdk/anthropic (#14749)
### What this PR does
Before this PR:
When `@ai-sdk/anthropic`'s `AnthropicMessagesLanguageModel` was used as
transport for non-Anthropic models (e.g. NewAPI configured with
`endpointType: 'anthropic'` routing non-Claude models, or any gateway
proxying non-Claude models through an Anthropic-compatible API), the SDK
silently injected a default `max_tokens` value (4096 for unknown models,
model-specific for Claude). This overrode the user's intent when they
had disabled `enableMaxTokens` in assistant settings — Cherry Studio's
`getMaxTokens` deliberately returns `undefined` in that case.
After this PR:
`max_tokens` is only emitted when either (a) the user has explicitly set
it, or (b) the model is actually a Claude model (`isKnownModel ||
modelId.startsWith("claude-")`). For non-Anthropic models routed through
the Anthropic SDK, the field is omitted, respecting the user's choice.
The fix lives in `patches/@ai-sdk__anthropic.patch`:
1. Make the fallback to `maxOutputTokensForModel` Claude-only.
2. Use a conditional spread for `max_tokens` in `baseArgs` so it's
omitted when undefined.
3. Guard the thinking-budget addition (`maxTokens + thinkingBudget`) so
it doesn't compute `NaN`.
Fixes #
### Why we need it and why it was done in this way
The Anthropic API itself requires `max_tokens`, so the SDK's default
fallback is correct for actual Claude requests. But the same SDK class
is reused as a transport for non-Anthropic backends in NewAPI /
aggregator providers, and there the silent default leaks through and
caps generation.
The following tradeoffs were made:
- Patched the upstream package via the existing `pnpm patch` workflow
rather than wrapping/intercepting the SDK at the call site, because the
field is constructed deep inside `getArgs()` and forking that path would
duplicate a lot of logic.
The following alternatives were considered:
- Setting `maxOutputTokens` explicitly per-provider in `getMaxTokens`.
Rejected because we want `undefined` to mean "let the server decide" for
non-Anthropic backends, and there is no generic safe default.
- Pre-stripping `max_tokens` after the SDK builds the body. Rejected:
the SDK posts directly via `postJsonToApi`; there is no public hook
between body construction and request dispatch.
Links to places where the discussion took place: N/A
### Breaking changes
None. Behavior for real Anthropic Claude requests is unchanged (the
default is still applied). The change only affects requests where the
SDK is used against a non-Claude model and the user has not set
`maxOutputTokens` — previously they got a silent 4096 cap, now they get
whatever the upstream server defaults to.
### Special notes for your reviewer
- The patch is regenerated via `pnpm patch @ai-sdk/anthropic@3.0.71` +
`pnpm patch-commit`, so the hash in `pnpm-lock.yaml` updates
accordingly.
- Existing 28 tests in
`src/renderer/src/aiCore/prepareParams/__tests__/model-parameters.test.ts`
still pass.
- Hotfix branch per the post-2026-04-03 main-branch policy. No
refactoring included.
### Checklist
- [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
```release-note
fix(deps): prevent @ai-sdk/anthropic from injecting a default max_tokens when used as transport for non-Anthropic models (e.g. NewAPI with anthropic endpoint type for non-Claude models). User's choice to disable max tokens is now respected on those backends.
```
Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
06f93a0d2f |
fix(deps): bump @ai-sdk/deepseek to 2.0.30 (#14718)
### What this PR does Before this PR: - `@ai-sdk/deepseek` was pinned to `2.0.29`, missing an upstream fix for `deepseek-v4` reasoning content in multi-turn conversations. After this PR: - Bumps `@ai-sdk/deepseek` from `2.0.29` to `2.0.30` (latest stable). - Renames the local patch file to `@ai-sdk__deepseek@2.0.30.patch` and updates the `pnpm.patchedDependencies` key. The patch (which adds the `reasoning_effort` option for `high`/`max`) re-applies cleanly because the patched regions are unchanged in `2.0.30`. Fixes # ### Why we need it and why it was done in this way Upstream `2.0.30` ships a single fix from vercel/ai commit `0498012`: `fix(provider/deepseek): preserve reasoning_content for deepseek-v4 in multi-turn requests`. It threads the `modelId` into `convertToDeepSeekChatMessages`, stops dropping `reasoning` blocks before the last user message for `deepseek-v4`, and ensures `reasoning_content` is at least `""` rather than `undefined` so the field is preserved across turns. Keeping the local patch in sync with upstream prevents drift and unblocks future DeepSeek model rollouts. The following tradeoffs were made: - Patch file content is byte-identical; only the filename and `pnpm.patchedDependencies` key are updated. This avoids gratuitous diff churn while keeping the patch addressable to the new version. The following alternatives were considered: - Wait for a larger DeepSeek change before bumping — rejected; the upstream fix is small, isolated, and there is no reason to delay. - Move to `3.0.0-beta.x` — rejected; betas track AI SDK v6 and are out of scope for the `main` branch hotfix lane. Links to places where the discussion took place: N/A ### Breaking changes None. Public API surface, exported types, and the `reasoning_effort` patch behavior are unchanged. ### Special notes for your reviewer - Verified the patch applied to `2.0.30` in `node_modules` — both the local addition (`reasoning_effort`) and the upstream fix (`isDeepSeekV4`) are present after `pnpm install`. - `pnpm build:check` passes locally (4199 tests, 0 errors). - This change is restricted to `main` per the code-freeze policy and is delivered from a `hotfix/*` branch with no refactoring. ### Checklist - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [ ] Documentation: A user-guide update 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 before requesting review from others ### Release note ```release-note NONE ``` --------- Signed-off-by: suyao <sy20010504@gmail.com> |
||
|
|
6a6b47562b | Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 | ||
|
|
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> |
||
|
|
4e1e4548bb |
hotfix(deepseek): forward reasoning effort for DeepSeek V4+ via Claude endpoint (#14572)
### What this PR does
Before this PR:
- For DeepSeek V4+ models served through a Claude-compatible endpoint,
`getAnthropicReasoningParams` returned only `{ thinking: { type:
'enabled', budgetTokens } }`. The requested `reasoning_effort` was
dropped before the request left the client, so `high` / `xhigh` behaved
identically to default.
- `@ai-sdk/deepseek` had no `reasoning_effort` field on its Zod options
schema, so even if the effort were forwarded the SDK would strip it from
the request body.
- `@ai-sdk/anthropic` silently omitted the `thinking` field when
thinking was turned off, preventing downstream providers that require an
explicit `{ type: 'disabled' }` from honoring the disable.
After this PR:
- Non-Anthropic Claude-endpoint models (Kimi, MiniMax, DeepSeek V4+,
etc.) receive `sendReasoning: true` so reasoning output is actually
streamed back.
- DeepSeek V4+ additionally receives `effort: 'max'` when the user picks
`xhigh`, otherwise `effort: 'high'`.
- `@ai-sdk/deepseek@2.0.29` is patched to accept `reasoning_effort` on
its language-model options schema and forward it into the request body.
- `@ai-sdk/anthropic` is patched to emit an explicit `thinking: { type:
'disabled' }` when thinking is disabled.
- Updated one existing `getAnthropicReasoningParams` unit test to assert
the new `sendReasoning: true` payload, and added a new V4+ reasoning
test suite.
Fixes #
### Why we need it and why it was done in this way
Follow-up to #14551, which introduced `isDeepSeekV4PlusModel` and the
`deepseek_v4` reasoning category but did not wire the selected effort
into the outgoing request for the Claude-compatible endpoint path.
Without this PR the `high` / `xhigh` options are cosmetic for V4+.
The following tradeoffs were made:
- Patched upstream SDKs (`@ai-sdk/deepseek`, `@ai-sdk/anthropic`)
instead of waiting for upstream releases, so the fix ships on `main`'s
code freeze window. Patches are narrow (single field additions).
- Kept all non-Anthropic Claude-endpoint models on `sendReasoning: true`
rather than gating per-provider — the field is harmless for providers
that don't emit reasoning and restores visibility for those that do.
The following alternatives were considered:
- Upstreaming the `reasoning_effort` change to `@ai-sdk/deepseek` —
rejected for timing; patch is mechanical and easy to drop once upstream
lands.
- Sending effort via a custom header — rejected; DeepSeek documents
`reasoning_effort` in the request body.
Links to places where the discussion took place:
### Breaking changes
None. The added fields (`sendReasoning`, `effort`, `reasoning_effort`)
are additive and only take effect for models already routed through the
Claude-compatible path with reasoning enabled.
### Special notes for your reviewer
- Two new patch files under `patches/` are registered in
`package.json#pnpm.patchedDependencies`; they are narrow dist-only
additions.
- The implementation change is localized to
`getAnthropicReasoningParams` in
`src/renderer/src/aiCore/utils/reasoning.ts`.
- Targeting `main` via `hotfix/*` branch per the branch-strategy rule,
since this restores intended V4+ behavior shipped in #14551 and contains
no refactoring.
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [x] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [x] Documentation: A user-guide update 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 before requesting review
from others
### Release note
```release-note
Fix: DeepSeek V4+ reasoning effort (high / xhigh) is now actually forwarded to the API when the model is served via a Claude-compatible endpoint; reasoning output is also streamed back to the UI.
```
---------
Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|
|
5ec8696fd2 | Merge branch 'main' of github.com:CherryHQ/cherry-studio into v2 | ||
|
|
c0b3c880e3 |
hotfix(ai-sdk/openai): patch @ai-sdk/openai to support gpt-image-2 (#14488)
### What this PR does
Before this PR:
Calling the newly-released `gpt-image-2` model (shipped 2026-04-21) via
OpenAI image generation fails with `400 Unknown parameter:
'response_format'`. `@ai-sdk/openai@3.0.49` (our current AI SDK v6 line
dep) unconditionally sends `response_format: 'b64_json'` for any model
not in its `defaultResponseFormatPrefixes` allow-list, and `gpt-image-2`
is not in that list.
After this PR:
`@ai-sdk/openai@3.0.49` is patched to add `gpt-image-2` to both
`modelMaxImagesPerCall` and `defaultResponseFormatPrefixes` in all four
compiled dist entry points (`dist/index.{js,mjs}`,
`dist/internal/index.{js,mjs}`). This mirrors vercel/ai#14680, which was
backported to `release-v6.0` via vercel/ai#14682 on 2026-04-21 but has
not yet been published to npm. The patch is registered in
`pnpm.patchedDependencies` alongside the existing AI SDK patches.
Fixes #14485
### Why we need it and why it was done in this way
The upstream fix (vercel/ai#14680 / #14682) is already merged into the
`release-v6.0` branch, so a patch is a stable, low-risk equivalent of
the forthcoming `@ai-sdk/openai@3.0.54+`. Once that version ships on
npm, this patch can be dropped and replaced with a dependency bump.
The following tradeoffs were made:
- Patching compiled `dist/` files instead of source: matches the
repository's existing convention (see
`patches/@ai-sdk__google@3.0.55.patch`,
`patches/@ai-sdk__openai-compatible@2.0.37.patch`) and avoids rebuilding
the package.
- Not touching `.d.ts` type declarations: the upstream
`OpenAIImageModelId` union already accepts `(string & {})`, so runtime
behavior is the only thing that needs correcting.
The following alternatives were considered:
- Waiting for the npm release of `@ai-sdk/openai@3.0.54` — rejected
because users are actively hitting the bug today.
- Using a pnpm `overrides` entry pointing at the `release-v6.0` git
branch — rejected because it pulls an unversioned moving target and
conflicts with the locked semver range.
- Stripping `response_format` in an `aiCore` plugin — rejected because
the fix belongs at the provider layer and a plugin would permanently
mask similar issues for other models.
Links to places where the discussion took place: vercel/ai#14680,
vercel/ai#14682
### Breaking changes
None.
### Special notes for your reviewer
- The patch adds `gpt-image-2` at the expected positions in each of the
four dist files; diff is small and mechanical. Verified locally:
`node_modules/@ai-sdk/openai/dist/index.js:1753,1761` now contain
`gpt-image-2` after `pnpm install`.
- UI model picker changes are intentionally out of scope. Users select
`gpt-image-2` by model ID today; once upstream publishes, a follow-up
can refresh `src/renderer/src/config/models/default.ts` and friends.
### Checklist
- [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
```release-note
fix(ai-sdk/openai): patch @ai-sdk/openai to support OpenAI's gpt-image-2 model, resolving "Unknown parameter: 'response_format'" errors.
```
---------
Signed-off-by: suyao <sy20010504@gmail.com>
|
||
|
|
8f9bf0b516 |
fix(data): patch @libsql/client to replay PRAGMAs after transaction()
`Sqlite3Client.transaction()` nullifies its internal connection (`this.#db = null`), causing the next operation to create a new connection with default PRAGMAs. This resets `synchronous` from NORMAL back to FULL — roughly 2x write performance degradation. Patch `@libsql/client@0.15.15` to add `setPragma()` which registers per-connection PRAGMAs and replays them in `#getDb()` and `reconnect()` whenever a new connection is created. Pattern borrowed from upstream PR #328's ATTACH replay mechanism. Update DbService and MigrationDbService to use `createClient()` + `setPragma()` instead of `db.run(sql\`PRAGMA ...\`)` for per-connection settings. Upstream issues (still open, no official fix): - tursodatabase/libsql-client-ts#229 - tursodatabase/libsql-client-ts#288 Signed-off-by: fullex <0xfullex@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>
|
||
|
|
a58bbf52fd |
refactor: migrate to ai sdk v6 Phase 3 (#12235)
Continued from #12227 ## Summary Phase 3 of AI SDK v6 migration: - **Image generation**: Migrate to native AI SDK `generateImage`/`editImage`, remove legacy image middleware - **Embedding**: Migrate to AI SDK `embedMany`, remove legacy embedding clients - **Model listing**: Refactor `ModelListService` to Strategy Registry pattern (`listModels.ts`), consolidate 7 schema files into one `schemas.ts` - **OpenRouter image**: Bump `@openrouter/ai-sdk-provider` to 2.3.3 with native image endpoint support, remove `isNativeImageGenerationProvider` guard - **GitHub Copilot**: Simplify extension by removing `ProviderV2` cast and `wrapProvider` - **Legacy removal**: Delete all legacy API clients, middleware pipeline, and barrel `index.ts` - **Rename**: `index_new.ts` → `AiProvider.ts`, `ModelListService.ts` → `listModels.ts` ## Manual Test Plan ### P0 — Core paths + PR change focus #### 1. Core Chat - [ ] OpenAI model (e.g. GPT-4o): send text, verify streaming output - [ ] Anthropic model (e.g. Claude Sonnet): verify chat works - [ ] Gemini model: verify chat works - [ ] DeepSeek model: verify chat works - [ ] Reasoning mode (o3-mini, DeepSeek R1): verify thinking process displays - [ ] Send message with image (multimodal): verify model recognizes image - [ ] Abort mid-stream: verify clean termination, no errors #### 2. Image Generation (key change area) - [ ] DALL-E 3 / GPT-Image-1: verify image generation works - [ ] OpenRouter image model: verify **native image endpoint** is used (no longer chat completions) - [ ] Image editing: upload image + text prompt, verify editImage path - [ ] Verify generated images display correctly (both base64 and URL formats) #### 3. Model Listing (refactored area) - [ ] Sync OpenAI models: verify names and groups - [ ] Sync Gemini models: verify `models/` prefix stripped - [ ] Sync Ollama models (local): verify display - [ ] Sync OpenRouter models: verify chat + embedding models both appear - [ ] Sync SiliconFlow models: verify grouping (e.g. `deepseek-ai/`) - [ ] Sync GitHub Models - [ ] Sync Together models - [ ] Sync NewAPI service (e.g. CherryIn) - [ ] Sync PPIO models: verify chat + embedding + reranker endpoints merged ### P1 — Affected by refactor #### 4. Provider Extensions - [ ] GitHub Copilot: verify chat works (simplified wrapProvider logic) - [ ] Ollama: verify chat works - [ ] Vertex AI / Bedrock: verify chat works (if configured) #### 5. MCP Tool Calling - [ ] Enable MCP server, send tool-requiring message, verify tool execution - [ ] Verify both prompt tool use and function calling modes #### 6. Auxiliary Functions - [ ] Auto topic title generation (fetchMessagesSummary) - [ ] Note summary (fetchNoteSummary) - [ ] Translation/generation (fetchGenerate) - [ ] API check (click "Check" button in settings) ### P2 — Indirect impact #### 7. Knowledge Base - [ ] Create knowledge base, associate with assistant, verify RAG retrieval and embedding #### 8. Web Search - [ ] Enable native web search (Gemini/Perplexity), verify search results in response #### 9. Tracing - [ ] Enable developer mode, send message, verify trace spans recorded and displayed --------- Signed-off-by: suyao <sy20010504@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: icarus <eurfelux@gmail.com> Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com> |
||
|
|
f990e200a7 |
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>
|
||
|
|
1c0a5a95fa |
refactor: migrate to ai sdk v6 Phase 3 (#12235)
Continued from #12227 ## Summary Phase 3 of AI SDK v6 migration: - **Image generation**: Migrate to native AI SDK `generateImage`/`editImage`, remove legacy image middleware - **Embedding**: Migrate to AI SDK `embedMany`, remove legacy embedding clients - **Model listing**: Refactor `ModelListService` to Strategy Registry pattern (`listModels.ts`), consolidate 7 schema files into one `schemas.ts` - **OpenRouter image**: Bump `@openrouter/ai-sdk-provider` to 2.3.3 with native image endpoint support, remove `isNativeImageGenerationProvider` guard - **GitHub Copilot**: Simplify extension by removing `ProviderV2` cast and `wrapProvider` - **Legacy removal**: Delete all legacy API clients, middleware pipeline, and barrel `index.ts` - **Rename**: `index_new.ts` → `AiProvider.ts`, `ModelListService.ts` → `listModels.ts` ## Manual Test Plan ### P0 — Core paths + PR change focus #### 1. Core Chat - [ ] OpenAI model (e.g. GPT-4o): send text, verify streaming output - [ ] Anthropic model (e.g. Claude Sonnet): verify chat works - [ ] Gemini model: verify chat works - [ ] DeepSeek model: verify chat works - [ ] Reasoning mode (o3-mini, DeepSeek R1): verify thinking process displays - [ ] Send message with image (multimodal): verify model recognizes image - [ ] Abort mid-stream: verify clean termination, no errors #### 2. Image Generation (key change area) - [ ] DALL-E 3 / GPT-Image-1: verify image generation works - [ ] OpenRouter image model: verify **native image endpoint** is used (no longer chat completions) - [ ] Image editing: upload image + text prompt, verify editImage path - [ ] Verify generated images display correctly (both base64 and URL formats) #### 3. Model Listing (refactored area) - [ ] Sync OpenAI models: verify names and groups - [ ] Sync Gemini models: verify `models/` prefix stripped - [ ] Sync Ollama models (local): verify display - [ ] Sync OpenRouter models: verify chat + embedding models both appear - [ ] Sync SiliconFlow models: verify grouping (e.g. `deepseek-ai/`) - [ ] Sync GitHub Models - [ ] Sync Together models - [ ] Sync NewAPI service (e.g. CherryIn) - [ ] Sync PPIO models: verify chat + embedding + reranker endpoints merged ### P1 — Affected by refactor #### 4. Provider Extensions - [ ] GitHub Copilot: verify chat works (simplified wrapProvider logic) - [ ] Ollama: verify chat works - [ ] Vertex AI / Bedrock: verify chat works (if configured) #### 5. MCP Tool Calling - [ ] Enable MCP server, send tool-requiring message, verify tool execution - [ ] Verify both prompt tool use and function calling modes #### 6. Auxiliary Functions - [ ] Auto topic title generation (fetchMessagesSummary) - [ ] Note summary (fetchNoteSummary) - [ ] Translation/generation (fetchGenerate) - [ ] API check (click "Check" button in settings) ### P2 — Indirect impact #### 7. Knowledge Base - [ ] Create knowledge base, associate with assistant, verify RAG retrieval and embedding #### 8. Web Search - [ ] Enable native web search (Gemini/Perplexity), verify search results in response #### 9. Tracing - [ ] Enable developer mode, send message, verify trace spans recorded and displayed --------- Signed-off-by: suyao <sy20010504@gmail.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com> Co-authored-by: icarus <eurfelux@gmail.com> Co-authored-by: fullex <106392080+0xfullex@users.noreply.github.com> |
||
|
|
adc1c27221 |
fix(models): strip models/ prefix from Google API model IDs (#13861)
### What this PR does Before this PR: Google API returns model IDs with a `models/` prefix (e.g. `models/gemini-flash-latest`). This prefix was stored as-is and passed to `@ai-sdk/google`. The SDK's `prepareTools` function uses strict equality to check model names against an unprefixed allowlist, so it failed to recognize the model as Gemini 2+ and routed web search to the deprecated `google_search_retrieval` API, causing the error: `google_search_retrieval is not supported. Please use google_search tool instead.` After this PR: The `models/` prefix is stripped at the model adapter layer (`adaptSdkModel`), so all downstream consumers receive consistent unprefixed model IDs. Web search is correctly routed to the `google_search` API. ### Why we need it and why it was done in this way The fix is applied at the `ModelAdapter` layer because it is the single entry point where SDK model responses are normalized into the app's `Model` type. This ensures all consumers (SDK tool routing, app-level model detection functions like `isGemini3FlashModel`) work with consistent IDs without needing per-consumer workarounds. The following alternatives were considered: - Patching `@ai-sdk/google`'s `prepareTools` to handle the prefix — rejected because it's better to normalize data at ingestion rather than patching every consumer. ### Breaking changes None. ### Checklist - [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) - [ ] Upgrade: N/A - [ ] Documentation: Not required (internal bug fix) - [x] Self-review: I have reviewed my own code before requesting review from others ### Release note ```release-note Fix Google Gemini web search failing with "google_search_retrieval is not supported" error for models fetched from Google API (e.g. gemini-flash-latest). ``` --------- Signed-off-by: suyao <sy20010504@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
65271f386e | fix: route copilot gpt-5.4 models to responses (#13632) | ||
|
|
781e04145c |
chore: upgrade @anthropic-ai/claude-agent-sdk from 0.2.56 to 0.2.71 (#13339)
### What this PR does Before this PR: `@anthropic-ai/claude-agent-sdk` was pinned at version 0.2.56. After this PR: Upgraded to 0.2.71. The postinstall regex patch (spawn→fork for IPC) applies successfully on the new version (3/3 patches matched). Also fixed `cli.js` resolution since the new version removed `./cli.js` from its `exports` field. ### Why we need it and why it was done in this way Keep the SDK up to date with the latest bug fixes and improvements from Anthropic. The following tradeoffs were made: N/A The following alternatives were considered: N/A ### Breaking changes None. The SDK's Node engine requirement (≥18) is compatible with the project. The `cli.js` file still exists in the package — only the `exports` mapping was removed, so the resolution path was updated to use `path.join(path.dirname(require.resolve(...)), 'cli.js')`. ### Special notes for your reviewer - The postinstall script (`scripts/patch-claude-agent-sdk.ts`) applies 3 regex patches to `sdk.mjs`. All 3 matched successfully on version 0.2.71. - `cli.js` resolution in `ClaudeCodeService` constructor was updated since the new SDK version no longer lists `./cli.js` in its package.json `exports` field. ### Checklist - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [ ] Documentation: Not required — no user-facing feature or behavior change - [x] Self-review: I have reviewed my own code before requesting review from others ### Release note ```release-note NONE ``` --------- Signed-off-by: Vaayne <liu.vaayne@gmail.com> |
||
|
|
e72bde30eb |
refactor: replace static pnpm patch with postinstall script for claude-agent-sdk (#13139)
### What this PR does
Before this PR:
`claude-agent-sdk` is patched via a static pnpm `.patch` file that
replaces entire minified lines. This breaks every time the SDK is
upgraded because obfuscated variable names change with each
minification.
After this PR:
A Node.js postinstall script (`scripts/patch-claude-agent-sdk.mjs`) uses
semantic regex patterns to apply the same 3 patches. Since it matches
structural patterns (not variable names), it survives SDK version bumps
as long as the code structure remains the same.
### Why we need it and why it was done in this way
The following tradeoffs were made:
- Regex-based patching is slightly less precise than a static `.patch`
file, but far more resilient to minified code changes.
- The script validates all 3 patches applied and exits with error if
patterns don't match, so SDK structure changes are caught immediately.
The following alternatives were considered:
- Keeping the pnpm patch approach — rejected because it requires manual
regeneration on every SDK upgrade.
- Using AST-based patching — rejected as overkill for 3 targeted
replacements in minified code.
### Breaking changes
None. The same 3 modifications are applied (spawn→fork, remove command
destructuring, IPC stdio), just via a different mechanism.
### Special notes for your reviewer
The 3 patches applied by the script:
1. `import{spawn as X}` → `import{fork as X}` — enables IPC channel
2. Remove `command:VAR,` from `spawnLocalProcess` destructuring
3. Rewrite spawn call to `fork(args[0], args.slice(1), ...)` with IPC
stdio, removing `windowsHide:!0`
43 unit tests cover: variable name variations, idempotency, partial
matches, and no-match detection.
### Checklist
- [x] PR: The PR description is expressive enough and will help future
contributors
- [x] Code: Write code that humans can understand and Keep it simple
- [x] Refactor: You have left the code cleaner than you found it (Boy
Scout Rule)
- [ ] Upgrade: Impact of this change on upgrade flows was considered and
addressed if required
- [ ] Documentation: Not required — internal build tooling change
- [x] Self-review: I have reviewed my own code before requesting review
from others
### Release note
```release-note
NONE
```
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
|
||
|
|
a9656674ff |
fix: upgrade ollama provider to 3.3.1 (#13085)
<!-- 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 Before this PR: After this PR: <!-- (optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: --> continue #12526 Fix #11612 Fix #12642 Fix #13083 ### Why we need it and why it was done in this way The following tradeoffs were made: Bump ollama-ai-provider-v2 from 1.5.5 to 3.3.1 and update its patch filename. Update pnpm lock entries for the new provider version and related provider deps. Adjust compiled dist files to expose ollama provider option types and add support for the expanded "think" option (boolean | 'low' | 'medium' | 'high'). Add a new ollamaReasoningOrderMiddleware to reorder reasoning stream parts ahead of text/tool parts and wire it into AiSdkMiddlewareBuilder when reasoning is enabled. Update options builder to use OllamaProviderOptions and map assistant reasoning_effort (including explicitly disabling thinking when reasoning is off). The following alternatives were considered: Links to places where the discussion took place: <!-- optional: slack, other GH issue, mailinglist, ... --> ### Breaking changes <!-- optional --> If this PR introduces breaking changes, please describe the changes and the impact on users. ### Special notes for your reviewer <!-- optional --> ### 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) - [ ] 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(ollama): reasoning order ``` --------- Co-authored-by: suyao <sy20010504@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
842ccf0272 |
refactor: migrate to aisdk v6 Phase 1 (#12078)
<!-- 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> |
||
|
|
ef27726fa1 |
chore(deps): fix security vulnerabilities in edge dependencies (#13054)
- fast-xml-parser: ^5.2.0 → ^5.3.5 (critical, entity encoding bypass) - tar: ^7.4.3 → ^7.5.9 (high, path traversal via hardlink) - diff: ^8.0.2 → ^8.0.3 (low, ReDoS in parsePatch/applyPatch) - markdown-it: ^14.1.0 → ^14.1.1 (moderate, ReDoS) - add pnpm overrides for tar@7.5.9 and fast-xml-parser@5.4.1 to patch transitive deps --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: icarus <eurfelux@gmail.com> |
||
|
|
a734a74b6f |
chore(deps): bump @anthropic-ai/claude-agent-sdk from 0.1.76 to 0.2.56 (#13044)
### What this PR does Before this PR: `@anthropic-ai/claude-agent-sdk` was pinned at v0.1.76 with a patch to replace `spawn` with `fork` for IPC support. After this PR: `@anthropic-ai/claude-agent-sdk` is upgraded to v0.2.56 with the same `spawn→fork` patch regenerated for the new version. ### Why we need it and why it was done in this way The following tradeoffs were made: N/A The following alternatives were considered: N/A fix this problem via bump: https://github.com/anthropics/claude-code/issues/8430 ### Breaking changes None. The patch applies the same `spawn→fork` transformation as before, just targeting the updated minified code in v0.2.56. ### Special notes for your reviewer - The old patch file `patches/@anthropic-ai__claude-agent-sdk@0.1.76.patch` is no longer referenced but was not deleted (pnpm removed the reference automatically). - The new patch `patches/@anthropic-ai__claude-agent-sdk.patch` is large in bytes because it diffs minified single-line JS, but the logical change is small (spawn→fork, add IPC stdio, remove windowsHide). ### Checklist - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule) - [x] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [ ] Documentation: Not required ### Release note ```release-note NONE ``` Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
486ed0f148 |
fix: handle Gemini OpenAI-compatible thought signatures and missing tool_call index (#12769)
* fix: Handle missing providerOptions in Gemini thought signature skip * fix: Update @ai-sdk/openai-compatible patch for tool call schema Add support for reasoning_content field and make tool call index optional with default value * fix: add thought_signature support for tool-call parts in OpenAI-compatible path - Add PartWithProviderOptions interface for type safety - Handle tool-call parts that need thought_signature for Gemini OpenAI-compatible API - When a message has thinking indicators, add extra_content.google.thought_signature to all tool-call parts for the OpenAI-compatible path - Reference: https://ai.google.dev/gemini-api/docs/thought-signatures#openai Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: Skip Gemini thought signature for all tool calls --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
5e2bdf4591 | fix: correct openai-compatible strictJsonSchema patch (#12762) | ||
|
|
c7c380d706 |
fix: disable strict JSON schema for OpenRouter to support MCP tools (#12415)
* fix: update dependencies and patch files for strict JSON schema compliance - Updated `@ai-sdk/openai-compatible` to include version 1.0.30 and adjusted related patch files. - Removed obsolete patch for `@ai-sdk/openai-compatible@1.0.28`. - Added new patch for `@openrouter/ai-sdk-provider` to support strict JSON schema options. - Modified `options.ts` to set `strictJsonSchema` to false for OpenAI models. - Enhanced OpenAI compatible provider options to include `sendReasoning` and `strictJsonSchema`. - Updated lockfile to reflect changes in patched dependencies and their hashes. * fix: filter strictJsonSchema from request body in OpenRouter patch - Destructure and remove strictJsonSchema from openrouterOptions before spreading into request body - This prevents sending the internal option to the OpenRouter API Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
9b8420f9b9 |
fix: restore patch for claude-agent-sdk (#12391)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com> |
||
|
|
ed3401a016 |
⬆️ chore(deps): upgrade @anthropic-ai/claude-agent-sdk to 0.1.76 (#12317)
- Upgrade from 0.1.62 to 0.1.76 (latest stable) - Remove version-specific patch (no longer needed) |
||
|
|
2a31fa2ad5 |
refactor: switch yarn to pnpm (#12260)
* refactor: switch workflows from yarn to pnpm
Replace Yarn usage with pnpm in CI workflows to standardize package
management and leverage pnpm's store/cache behavior.
- Use pnpm/action-setup to install pnpm (v) instead of enabling corepack
and preparing Yarn.
- Retrieve pnpm store path and update cache actions to cache the pnpm
store and use pnpm-lock.yaml for cache keys and restores.
- Replace yarn commands with pnpm equivalents across workflows:
install, i18n:sync/translate, format, build:* and tsx invocation.
- Avoid committing lockfile changes by resetting pnpm-lock.yaml instead
of yarn.lock when checking for changes.
- Update install flags: use pnpm install --frozen-lockfile / --install
semantics where appropriate.
These changes unify dependency tooling, improve caching correctness,
and ensure CI uses pnpm-specific lockfile and cache paths.
* build: switch pre-commit hook to pnpm lint-staged
Update .husky/pre-commit to run pnpm lint-staged instead of yarn.
This aligns the pre-commit hook with the project's package manager
and ensures lint-staged runs using pnpm's environment and caching.
* chore(ci): remove pinned pnpm version from GH Action steps
Remove the explicit `with: version: 9` lines from multiple GitHub Actions workflows
(auto-i18n.yml, nightly-build.yml, pr-ci.yml, update-app-upgrade-config.yml,
sync-to-gitcode.yml, release.yml). The workflows still call `pnpm/action-setup@v4`
but no longer hardcode a pnpm version.
This simplifies maintenance and allows the action to resolve an appropriate pnpm
version (or use its default) without needing updates whenever the pinned
version becomes outdated. It reduces churn when bumping pnpm across CI configs
and prevents accidental pin drift between workflow files.
* build: Update pnpm to 10.27.0 and add onlyBuiltDependencies config
* Update @cherrystudio/openai to 6.15.0 and consolidate overrides
* Add @langchain/core to overrides
* Add override for openai-compatible 1.0.27
* build: optimize pnpm config and add missing dependencies
- Comment out shamefully-hoist in .npmrc for better pnpm compatibility
- Add React-related packages to optimizeDeps in electron.vite.config.ts
- Add missing peer dependencies and packages that were previously hoisted
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* build: refine pnpm configuration and dependency management
- Simplify .npmrc to only essential electron mirror config
- Move platform-specific dependencies to devDependencies
- Pin sharp version to 0.34.3 for consistency
- Update sharp-libvips versions to 1.2.4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
* reduce app size
* format
* build: remove unnecessary disableOxcRecommendation option from react plugin configuration
* docs: Replace yarn commands with pnpm in documentation and scripts
* Revert "build: optimize pnpm config and add missing dependencies"
This reverts commit
|