Commit Graph

5676 Commits

Author SHA1 Message Date
亢奋猫
45edebe851 fix: add manual download option for macOS users with old code signing (#13378)
### What this PR does

Before this PR:
- macOS users with the old code signing Team ID (Q24M7JR***) cannot
auto-update to v1.8.0+ due to signing certificate change
- Update request headers lacked app identification information

After this PR:
- Detects old Team ID on macOS and shows a manual download button
directing users to the official website
- Adds `App-Name`, `App-Version`, and `OS` headers to update requests
for better server analytics
- Refactors duplicate headers into a shared `getCommonHeaders()`
function

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Using `codesign -dv` to detect the Team ID at runtime is simple and
reliable on macOS

The following alternatives were considered:
- Checking the app version instead of Team ID, but this wouldn't
correctly identify users who haven't updated in a while

### Breaking changes

None

### Special notes for your reviewer

The old Team ID `Q24M7JR2C4` is hardcoded as a constant. This is
intentional since it represents the previous signing certificate that
will no longer be used.

### 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
- [x] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
Add manual download option for macOS users who cannot auto-update due to code signing certificate change
```

---------

Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-03-18 19:26:14 +08:00
亢奋猫
622c39ea64 refactor(backup): enhance backup system with legacy backup and path security (#13587)
### What this PR does

Before this PR:
- Backup system used a complex nested structure that was harder to
maintain
- No support for legacy backup format (LAN transfer)
- Limited path security validation
- electron-store config.json was stored in userData root, not included
in backups

After this PR:
- Implements direct backup and restore methods for IndexedDB and Local
Storage
- Adds legacy backup (LAN transfer) functionality for backward
compatibility
- Implements startup restoration support
- Enhances path security with `resolveAndValidatePath` to prevent
directory traversal attacks
- Simplifies BackupManager constructor and methods
- Adds Joplin and Siyuan icons
- Updates backup metadata structure and progress handling
- Moves electron-store config.json to userData/Data directory so it's
included in backups
- Adds automatic migration from legacy config location

Fixes #

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Added path validation overhead for enhanced security
- Legacy backup format support increases code complexity but ensures
backward compatibility

The following alternatives were considered:
- Keeping the old backup structure, but it was harder to maintain and
extend

Links to places where the discussion took place: N/A

### Breaking changes

The backup format has been updated to a new version. Existing backups
created with older versions will still be supported through the legacy
backup functionality.

### Special notes for your reviewer

- The `resolveAndValidatePath` utility prevents path traversal attacks
by validating that resolved paths stay within expected directories
- The BasicDataSettings component was extracted to improve code
organization
- Tests have been updated to cover the new backup functionality
- electron-store config location changed from `userData/config.json` to
`userData/Data/config.json` with automatic migration

### 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.
- [ ] 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
Enhanced backup system with new format (v6), legacy backup support, improved path security, and config.json now included in backups
```

---------

Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-03-18 19:25:09 +08:00
亢奋猫
9a58028f74 feat(mcp): add whitelist auto-trust for protocol install servers (#13586)
### What this PR does

Before this PR:
MCP servers installed via protocol (e.g., `cherrystudio://`) always
require user confirmation to trust, even for well-known trusted sources
like WPS Notes.

After this PR:
Adds a whitelist mechanism to auto-trust specific MCP server URLs
without requiring user confirmation. Currently whitelisted:
- `http://127.0.0.1:18930/mcp` (WPS Notes)

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Hardcoded whitelist vs. user-configurable: Chose hardcoded for
security, as allowing user-defined whitelists could be exploited.

The following alternatives were considered:
- Making whitelist configurable via settings: Rejected due to security
concerns.

### Breaking changes

None

### Special notes for your reviewer

The whitelist only applies to SSE-type servers with matching `baseUrl`.
The implementation is minimal and focused.

### 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: kangfenmao <kangfenmao@qq.com>
2026-03-18 19:23:11 +08:00
kangfenmao
a4cc48a846 refactor: consolidate qwen model definitions and update related references 2026-03-18 19:09:48 +08:00
kangfenmao
57294ab7ac fix: update provider configurations and improve keyword matching logic 2026-03-18 17:21:24 +08:00
SuYao
68af452e3f feat: enhance gh-pr-review skill with multi-agent teams review and auto-fix (#13530)
### What this PR does

Before this PR:
The `gh-pr-review` skill was a simple single-agent PR review workflow
using the `gh-pr-review` CLI extension (`EurFelux/gh-pr-review`) for
structured inline comments. It only supported PR reviews.

After this PR:
The `gh-pr-review` skill is a comprehensive code review system inspired
by [Tencent/tgfx's
`.codebuddy/skills/cr`](https://github.com/Tencent/tgfx/tree/main/.codebuddy/skills/cr),
adapted for Claude Code's Agent tool. It now supports:
- **Multiple review modes**: local branch changes, PRs, commits, commit
ranges, and file paths
- **Multi-agent teams review**: parallel reviewer agents with an
adversarial verifier agent to reduce false positives
- **Risk-based auto-fix**: automatic fixing of low/medium/high risk
issues based on user-selected mode
- **Structured checklists**: code and document review checklists
tailored for the project's TypeScript/React/Electron stack, with
cross-references to `vercel-react-best-practices` for deeper
React/performance analysis
- **Self-diagnosis**: `/gh-pr-review diag` to analyze and improve the
skill itself
- **Checklist evolution**: mechanism to add new checklist items based on
recurring patterns
- **PR review via gh-pr-review extension**: retains the `gh-pr-review`
CLI extension for pending reviews with inline comments, preview, and
structured submission

### Why we need it and why it was done in this way

The previous skill was limited to PR-only review. The tgfx approach
provides a battle-tested, comprehensive review system with adversarial
verification (reviewer finds issues, verifier challenges them), which
significantly reduces false positives.

The following tradeoffs were made:
- Adapted CodeBuddy's `CreateTeam`/`SendMessage`/`TeamDelete` APIs to
Claude Code's `Agent` tool with parallel subagents
- Code checklist adapted for this project's specific stack (TypeScript,
React 19, Electron 38, Redux Toolkit, Dexie, AI SDK v5) instead of
tgfx's C++ focus
- Cross-references `vercel-react-best-practices` skill for
React/performance checks instead of duplicating those rules
- Added v2 refactoring block rules in judgment matrix (Redux state shape
/ IndexedDB schema changes always deferred)
- Retained `gh-pr-review` CLI extension for PR review comment submission
(pending review API with preview)

The following alternatives were considered:
- Creating a new `/cr` skill alongside `gh-pr-review` — rejected because
both serve code review and having two review skills would be confusing

Links to places where the discussion took place:
- Reference implementation:
https://github.com/Tencent/tgfx/tree/main/.codebuddy/skills/cr

### Breaking changes

None. The skill name and invocation (`/gh-pr-review`) remain the same.
The `gh-pr-review` CLI extension is still used for PR reviews. New
capabilities (local review, teams review, auto-fix) are additive.

### Special notes for your reviewer

- The new skill routes to different reference files based on context (PR
number, uncommitted changes, branch state, agent teams availability)
- `references/teams-review.md` is the most complex file — it
orchestrates multi-agent review with 6 phases
- All reference files are adapted from tgfx's implementation with
project-specific customizations
- Code checklist cross-references `vercel-react-best-practices` skill
for React/performance deep checks

### 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
NONE
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 15:08:42 +08:00
Phantom
21a8c625cb fix: add budgetTokens fallback for Agent thinking compatibility (#13575)
### What this PR does

Before this PR:

`getAnthropicReasoningParams()` could return `{ thinking: { type:
'enabled' } }` without `budgetTokens` when `findTokenLimit()` couldn't
determine a model's token limit. The Claude Agent SDK then silently
converted this to `--thinking adaptive`, which non-Anthropic upstream
providers (e.g., cherryin proxy) do not support, resulting in a 400
error: `"thinking type should be enabled or disabled"`.

After this PR:

1. Extract the shared budget computation logic into
`computeBudgetTokens()`, used by both `getThinkingBudget()` and the new
`getFallbackBudgetTokens()` to prevent drift.
2. When `getThinkingBudget()` returns `undefined`, fall back to
`getFallbackBudgetTokens()` which uses a conservative token limit (min:
1024, max: 16384) scaled by `EFFORT_RATIO`, producing values
proportional to the selected effort level.

Fixes #13573

### Why we need it and why it was done in this way

The following tradeoffs were made:

A conservative fallback max of `16384` was chosen — small enough to work
across most providers, large enough for meaningful reasoning at higher
effort levels.

The following alternatives were considered:

- Hardcoded fallback (e.g., `8192`) — rejected because it ignores effort
level and could be too large for `low` or too small for `high`.
- Modifying `getThinkingBudget()` signature to never return `undefined`
— rejected to avoid changing the existing contract for other callers.
- Skipping thinking options for non-Anthropic providers — rejected
because it would break thinking for providers that do support `enabled`
mode.

Links to places where the discussion took place: #13573, #13574

### Breaking changes

None.

### Special notes for your reviewer

- The root cause is a type mismatch between the Vercel AI SDK
(`AnthropicProviderOptions` where `budgetTokens` is optional) and the
Claude Agent SDK (where `budgetTokens` is effectively required for
`type: 'enabled'`). `getAnthropicReasoningParams` was designed for the
AI SDK but is reused in the Agent flow.
- Only `src/renderer/src/aiCore/utils/reasoning.ts` is modified.
- `getThinkingBudget()` signature and return type are unchanged.

### 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
- [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.
- [ ] 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 Agent thinking mode 400 error on non-Anthropic providers by ensuring `budgetTokens` fallback with effort-based computation when token limit is unknown.
```

---------

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:21:09 +08:00
Phantom
5602d820ff fix: disable thinking mode for LLM language detection (#13565) 2026-03-18 10:23:13 +08:00
Siin Xu
906c6b83cc fix: Windows Terminal launch fails on non-English systems (#13551)
## Summary
- Remove hardcoded  profile name from Windows Terminal launch args
- On localized Windows (e.g. Chinese), the profile is named differently,
causing error 0x80070002
- Also remove extra quotes around bat file path

## Fix
Use default Windows Terminal profile instead of hardcoding English
profile name.

Closes #13550

## Test plan
- [ ] Windows Terminal on English Windows
- [ ] Windows Terminal on Chinese Windows (previously failed)
- [ ] PowerShell / Command Prompt: no regression

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: George·Dong <98630204+GeorgeDong32@users.noreply.github.com>
2026-03-18 10:13:56 +08:00
Phantom
3f9cb07cbe fix: propagate actual stream errors instead of generic NoTextGeneratedError (#13542)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 21:49:37 +08:00
George·Dong
b6f2284546 fix(code-tools): launch errors on Windows & Qwen Code auth issue (#13400)
### What this PR does

Before this PR:
- CLI tools (qwen-code, Claude Code, GitHub Copilot CLI, etc.) fail to
start on Windows
- bun install's multiline output (e.g., "Resolving [1/4]\nBun
v1.2.9...") is misinterpreted by cmd.exe as separate commands
- Users see errors like "'Resolving' is not recognized as an internal or
external command"
- Windows Terminal launch failed
- Qwen Code auth type incorrect, in
[docs](https://qwenlm.github.io/qwen-code-docs/zh/users/configuration/model-providers/)

After this PR:
- Redirect bun install output to a log file on Windows
- Log file location: `userData/logs/cli-tools-install.log` (via
`loggerService.getLogsDir()`)
- Windows Terminal launch normally
- Qwen Code auth type set to "openai" when package version >= 0.12.3

Fixes #12985 #13442 #13473

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Using file redirection (`>> "logfile" 2>&1`) instead of `--silent`
flag to preserve debug information for troubleshooting
- Windows-only fix since macOS/Linux terminals correctly handle
multiline output

The following alternatives were considered:
- Using `bun install --silent`: Rejected because it would lose all debug
information

Links to places where the discussion took place: #12985

### Breaking changes

None

### Special notes for your reviewer

- The fix uses `loggerService.getLogsDir()` to ensure logs are written
to the same directory as other Cherry Studio logs
- Tested on Windows with qwen-code, GitHub Copilot CLI, and other
affected tools

### 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: 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 CLI tools failing to start on Windows by redirecting bun install output to log file
```
2026-03-17 20:46:39 +08:00
github-actions[bot]
cb335dbcf2 🤖 Daily Auto I18N Sync: Mar 17, 2026 (#13521)
Co-authored-by: kangfenmao <8253512+kangfenmao@users.noreply.github.com>
2026-03-17 11:45:11 +08:00
SuYao
300920c116 feat: add clickable file paths to agent tool outputs and inline code (#13465)
### What this PR does

Before this PR:
File paths displayed in agent tool outputs (Edit, Write, Read, Glob,
Grep, MultiEdit, NotebookEdit) and inline code blocks were plain,
non-interactive text.

After this PR:
File paths are clickable — clicking opens the file directly. An ellipsis
dropdown menu provides additional actions: "Reveal in Finder" and "Open
in Editor" (VS Code, Cursor, Zed).

### Why we need it and why it was done in this way

Clickable file paths improve developer workflow by allowing quick
navigation to files referenced in agent tool outputs without manual
copy-paste.

The following tradeoffs were made:
- A shared `ClickableFilePath` component is used across all agent tools
for consistency.
- Inline code file path detection uses a conservative regex
(`/^\/[\w.-]+(?:\/[\w.-]+)+$/`) to avoid false positives on non-path
inline code. This means some edge-case paths (e.g., with spaces or `@`)
won't be detected in inline code, but tool-output paths are always
clickable since they come from structured input.

The following alternatives were considered:
- Detecting file paths via a more permissive regex — rejected due to
high false-positive risk on inline code snippets.

### Breaking changes

None.

### Special notes for your reviewer

- The `ClickableFilePath` component reuses existing `useExternalApps`
hook and `window.api.file` IPC APIs.
- i18n keys added for `open_file`, `open_file_error`, `file_not_found`,
and `reveal_in_finder` across all locale files.
- Review fix: hardcoded `'Finder'` string on macOS was replaced with
`t()` for proper i18n compliance.
- Review fix: test mocks for `openPath`/`showInFolder` now return
Promises to avoid TypeError on `.catch()`.

### 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: 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

```release-note
Add clickable file paths in agent tool outputs — click to open files, with dropdown to reveal in Finder or open in external editors (VS Code, Cursor, Zed).
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 23:24:46 +08:00
SuYao
f7ceb47462 fix(ci): only trigger release build on PR merge, not on every push (#13512)
### What this PR does

Before this PR:
The `release.yml` workflow triggers on `pull_request_target` with
`opened` and `synchronize` event types. Every commit pushed to a release
PR (e.g. editing release notes in `electron-builder.yml`) re-triggers
the full 3-platform release build (macOS + Windows + Linux), wasting
significant CI resources.

After this PR:
The workflow only triggers when the release PR is **merged** into
`main`, not on every push. This is achieved by:
1. Changing `pull_request_target` types from `opened`/`synchronize` to
`closed`
2. Adding `github.event.pull_request.merged == true` to the job
condition

Fixes #

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Release builds no longer run during PR review phase. If a pre-merge
test build is needed, `workflow_dispatch` can be used manually.

The following alternatives were considered:
- **Remove `synchronize` only (keep `opened`)**: Would still trigger on
PR creation but not subsequent pushes. However, this loses automation on
merge.
- **Path filtering**: `pull_request_target` doesn't support `paths`
filter, would require a separate job to check changed files — more
complex for the same result.
- **Label-based triggering**: Adds manual steps, defeats automation
purpose.

### Breaking changes

None. The `tag push` and `workflow_dispatch` triggers remain unchanged.
The only behavioral change is that release builds now happen on merge
instead of on PR open/push.

### Special notes for your reviewer

- The `workflow_dispatch` trigger still allows manual release builds at
any time
- The `push: tags: v*.*.*` trigger is unaffected
- The removed `head.repo.full_name == github.repository` check is
redundant since `merged == true` already implies the PR was accepted

### 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
NONE
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 22:17:39 +08:00
SuYao
af51a27b9b fix(mcp): resolve hub tool auto-approve to underlying server (#13493)
### What this PR does

Before this PR:

When a user clicked "Auto-approve" on a hub tool (`invoke`/`exec`), the
`autoApprove` function looked for a server with `id === 'hub'`, found
none, and silently returned without confirming the tool or persisting
the auto-approve preference.

After this PR:

The `autoApprove` function resolves hub tools to their underlying server
via `resolveHubTool`, then correctly updates `disabledAutoApproveTools`
on the real server. If resolution fails or no server is found, the tool
action is still confirmed (instead of silently dropped).

fixes: #13481 

### Why we need it and why it was done in this way

Hub tools use a virtual `serverId` of `'hub'` which doesn't correspond
to any real MCP server entry. The fix resolves the underlying server and
tool name through the existing `window.api.mcp.resolveHubTool` IPC call,
which is already used elsewhere in the codebase (e.g.,
`aiCore/utils/mcp.ts`).

The following tradeoffs were made:

- Duplicated the `disabledAutoApproveTools` update logic in the hub
resolution branch for clarity. This keeps the hub path self-contained
and avoids restructuring the existing flow.

The following alternatives were considered:

- Refactoring to share the update logic between hub and non-hub paths.
Decided against it to keep the change minimal and focused on the bug
fix.

### Breaking changes

None.

### Special notes for your reviewer

- The `autoApprove` callback is now `async` (it already was via
`useCallback`, this just adds `await` for the IPC call).
- `toolResponse` was added to the `useCallback` dependency array since
it's now referenced inside the callback.
- Added comprehensive tests covering all hub resolution branches
(success, null result, IPC error, missing server, missing args).

### 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
NONE
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 20:57:19 +08:00
Phantom
65c9dcbdc8 fix: prevent horizontal scroll in agent chat messages container (#13508)
### What this PR does

Before this PR:
The `ChatNavigation` component at `AgentChat.tsx:103` causes an unwanted
horizontal scrollbar to appear in the agent chat messages container.

After this PR:
Added `overflow-x-hidden` to the messages container to prevent the
horizontal scrollbar caused by `ChatNavigation`.

### Why we need it and why it was done in this way

The messages container already had `overflow-y-auto` for vertical
scrolling, but lacked `overflow-x-hidden` to suppress the horizontal
scrollbar introduced by the `ChatNavigation` component. Adding this
single utility class is the minimal fix.

The following tradeoffs were made:
N/A

The following alternatives were considered:
N/A

### Breaking changes

None

### Special notes for your reviewer

One-line CSS change — adds `overflow-x-hidden` to the agent chat
messages container div.

### 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
NONE
```
2026-03-16 18:44:18 +08:00
cherry-ai-bot[bot]
83d7575695 fix(azure): keep dated api versions on chat transport (#13506)
## Summary

Fix the Azure OpenAI regression reported in #13499.

Dated Azure API versions such as `2024-12-01-preview` are intended to
stay on Cherry's chat / deployment-based path, while only generic
`preview` / `v1` should use the Responses API. The regression was that
aiCore's internal `azure` provider still defaulted to the Responses
transport, so deployment-based Azure requests could still generate
`/openai/deployments/<deployment>/responses` URLs and fail with 404.

This PR restores the intended split by:
- making the `azure` provider default to `provider.chat(...)`
- keeping `azure-responses` on `provider.responses(...)`
- aligning the registry's `azure-chat` fallback with the same chat
wrapper
- adding regression coverage for provider routing and registry behavior

## Verification

- `node node_modules/vitest/vitest.mjs run --project renderer
src/renderer/src/aiCore/provider/__tests__/providerConfig.test.ts`
- `node node_modules/vitest/vitest.mjs run --project aiCore
packages/aiCore/src/core/providers/__tests__/registry-functionality.test.ts`

Fixes #13499

Co-authored-by: cherryai002 <cherryai002@192.168.5.55>
2026-03-16 16:53:54 +08:00
kangfenmao
5bc235a95f feat(agents): enhance Navbar with localized title for agent states 2026-03-16 16:22:05 +08:00
beyondkmp
a5ab5c2e96 fix(agents): fix Zed URL scheme and redesign OpenExternalAppButton (#13501)
### What this PR does

Before this PR:
- Zed editor could not open directories because it used the same VSCode
URL scheme (`vscode://file/path?windowId=_blank`), which Zed does not
recognize.
- The "Open" button always showed the first detected editor's icon
regardless of which editor the user selected from the dropdown.
- The button displayed a text label ("Open") and used an ellipsis icon
(···) for the dropdown trigger.

After this PR:
- Zed now uses the correct URL format (`zed://file/path`) matching Zed's
`strip_prefix("zed://file")` parsing logic.
- The button icon and click action update to reflect the user's last
dropdown selection.
- The button is redesigned to icon-only with a tooltip ("Open in {editor
name}") and a chevron (▼) dropdown trigger, for a cleaner look.

### Why we need it and why it was done in this way

The Zed URL scheme fix is based on reading Zed's source code
(`open_listener.rs`), which parses URLs by stripping the `"zed://file"`
string prefix — unlike VSCode which uses standard URL parsing. This
means the URL format must be `zed://file/absolute/path` (no extra `/`
between `file` and the path, no query params).

The icon-only button redesign with tooltip follows common split-button
patterns for a more compact and intuitive UI.

The following alternatives were considered:
- Using `shell.openExternal` via IPC instead of `window.open()` —
unnecessary since `window.open()` works for all three editors.

### Breaking changes

None.

### Special notes for your reviewer

- The pre-existing typecheck failures in CI are unrelated to this PR
(they are in `aiCore/plugins`, `store/messageBlock.ts`, etc.).

### 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: 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

```release-note
Fix Zed editor unable to open directories from agent workspace, and redesign the "Open in editor" button to icon-only with tooltip and editor selection memory.
```

---------

Signed-off-by: beyondkmp <beyondkmp@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: SuYao <sy20010504@gmail.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Phantom <eurfelux@gmail.com>
2026-03-16 15:40:07 +08:00
亢奋猫
a2ac99c8da chore: release v1.8.0 (#13500)
### What this PR does

Release Cherry Studio v1.8.0 with new features, bug fixes, and
improvements.

### Release Notes

Cherry Studio 1.8.0 - Agents & Performance

 New Features
- [Agents] Added drag-and-drop manual sorting for agent and session
lists
- [Models] Added MiniMax M2.5 highspeed model support

🐛 Bug Fixes
- [Agents] Fixed deleting last accessible directory bug - delete button
now disabled when only one remains
- [UI] Fixed web search providers not showing for local models (e.g.,
Ollama) in chat toolbar
- [Models] Fixed reasoning effort and summary mode not applying for some
OpenAI-compatible providers
- [Gateway] Fixed gateway status detection for
crashed/externally-stopped gateways
- [Gateway] Improved gateway startup error messages with detailed
diagnostics
- [Poe] Fixed web_search parameter not being passed correctly when
built-in search is enabled

💄 Improvements
- [Agents] Added configurable maximum tool calls setting (1-100) in
assistant settings
- [UI] Added Windows Mica effect for better visual integration
- [Performance] Increased default request timeout from 10 to 30 minutes
for slow local models

### Included Commits

- 888ce83fc feat(streaming): replace fixed timeout with resettable idle
timeout
- 31cd13ae8 fix(agents): improve navbar layout for agent status screens
- 590815bbd fix(openclaw): improve gateway startup diagnostics and fix
UI polling loop
- 878861db8 fix(scripts): add fallback to GitCode mirror when GitHub
download fails
- 6eb461dd1 feat(skills): add vercel-react-best-practices skill
- 74c892fe1 fix(agents): prevent deleting the last accessible directory
- fe0678a20 chore: migrate .claude/skills to directory symlinks
- 19bd2cdd9 feat(ui): enable windows mica effect
- 8b98b8f9c fix(agents): use correct SWRInfinite cache key and add
optimistic update for session editing
- c6ce1deec fix(ui): show web search providers for all models
- e860dd448 feat(agents): add manual drag-and-drop sorting for agent and
session lists
- f0f04eeda docs: update agents.db path in CLAUDE.md after #13392
- 46ad0fa5d feat: add MiniMax-M2.5-highspeed model
- 774cb7a73 fix(openclaw): fix gateway status detection and improve
error reporting
- f3244c3e9 fix(aiCore): bypass AI SDK model ID allowlist for reasoning
detection
- d676b3b39 chore: add Zed editor settings example, clean up configs,
and improve dev guides
- aeae3be69 fix: increase default request timeout from 10 to 30 minutes
- 9c3c99036 feat: separate Agent into independent module with dedicated
page and route
- ea694c630 feat(assistant): add configurable max tool calls setting
- 97011c8bb feat(openclaw): binary download install, auto update check,
and gateway refactor
- 4aef24915 fix: correctly pass poe web_search via extra_body when
built-in search is enabled

### Review Checklist

- [ ] Review generated release notes in electron-builder.yml
- [ ] Verify version bump in package.json
- [ ] CI passes
- [ ] Merge to trigger release build

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: SuYao <sy20010504@gmail.com>
v1.8.0
2026-03-16 15:17:38 +08:00
Phantom
888ce83fc7 feat(streaming): replace fixed timeout with resettable idle timeout (#13497)
### What this PR does

Before this PR:

The streaming timeout used a fixed `AbortSignal.timeout()` that starts
counting from the initial request. For long-running SSE streams (e.g.,
complex reasoning or tool-calling chains), the request could be aborted
even while data was actively flowing.

After this PR:

Introduces an `IdleTimeoutController` that resets its countdown every
time a stream chunk is received. The timeout now only fires when the
stream is truly idle (no data received for the configured duration), not
based on total elapsed time.

Fixes #13489

### Why we need it and why it was done in this way

The following tradeoffs were made:

- The idle timeout controller is a simple utility class with `reset()`
and `cleanup()` methods, exposed via an `IdleTimeoutHandle` interface
and threaded through `ModernAiProviderConfig` to `AiSdkToChunkAdapter`.
- The `reset()` callback is invoked on every `reader.read()` return in
`readFullStream`, which is the natural place where SSE chunks are
consumed.
- `cleanup()` is called in the `finally` block to prevent timer leaks
when the stream ends normally or errors out.

The following alternatives were considered:

- Implementing idle timeout at the AI SDK level — not feasible as the AI
SDK does not support idle timeout natively.
- Using a wrapper around `reader.read()` with `Promise.race` — more
invasive and less clean than resetting a timer on each chunk.

### Breaking changes

None. The default timeout duration remains unchanged (30 minutes). The
only behavioral change is that the timeout now resets on each chunk
instead of being fixed from request start.

### Special notes for your reviewer

- The `IdleTimeoutController` is covered by 6 unit tests (fake timers).
- The new optional `idleTimeout` constructor parameter on
`AiSdkToChunkAdapter` is backward-compatible — existing callers (e.g.,
`messageThunk.ts`) are unaffected.

### 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/9780096809515/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
NONE
```

---------

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 15:02:08 +08:00
亢奋猫
31cd13ae8b fix(agents): improve navbar layout for agent status screens (#13494)
### What this PR does

Before this PR:
- Agent status screens (Disabled, Stopped, Empty) did not show the
Navbar component
- AgentSidePanel tabs had incorrect padding when navbar is at top
position
- AgentStatusScreen used motion animation which was unnecessary

<img width="1060" height="700" alt="image"
src="https://github.com/user-attachments/assets/ec90c9ed-f8a9-4c1d-a9a4-af2ef34ab772"
/>

After this PR:
- All agent status screens now consistently display the Navbar component
- AgentSidePanel tabs padding adjusts correctly based on navbar position
(adds `pt-0.5` when navbar is at top)
- Removed motion animation from AgentStatusScreen for cleaner code
- AgentNavbar is always shown regardless of navbar position setting

<img width="1060" height="700" alt="image"
src="https://github.com/user-attachments/assets/fee0aaa6-d49b-4dd8-819d-6f7a0b083945"
/>

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Removed motion animation to simplify the component; the animation was
brief and not critical to UX

The following alternatives were considered:
- Using CSS attribute selectors for navbar position styling, but using
the existing `useNavbarPosition` hook is more consistent with the
codebase

### Breaking changes

None

### Special notes for your reviewer

This is a UI layout fix to ensure consistent navbar display across all
agent page states.

### 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
- [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.
- [ ] 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
NONE
```

Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-03-16 14:28:57 +08:00
SuYao
590815bbd5 fix(openclaw): improve gateway startup diagnostics and fix UI polling loop (#13495)
### What this PR does

Before this PR:
- Gateway startup failures showed limited diagnostics (only stderr, no
stdout)
- OpenClawPage had infinite re-render loops caused by `setInterval` +
`dispatch` in `useEffect` deps
- Process exit with code 0 was not properly diagnosed when the
daemonized child failed

After this PR:
- Capture both stdout and stderr from the gateway process for better
failure diagnostics
- Replace `setInterval` polling with SWR for stable, dedup'd
status/health polling in the UI
- Improve error messages for gateway startup timeout (combine health,
stderr, stdout diagnostics)
- Handle edge case where gateway exits with code 0 but never becomes
healthy

### Why we need it and why it was done in this way

The infinite re-render loop in the renderer was the root cause of false
timeout errors during gateway health checks. Switching to SWR provides
stable polling without the pitfall of `setInterval` + `dispatch` in
`useEffect` deps.

The diagnostics improvements (stdout capture, combined error output) are
independent quality-of-life improvements that help debug gateway startup
failures.

### 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 and Keep it simple
- [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>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 14:28:30 +08:00
亢奋猫
878861db84 fix(scripts): add fallback to GitCode mirror when GitHub download fails (#13492)
## Summary
- When GitHub is inaccessible, the openclaw installation script now
automatically falls back to GitCode mirror instead of failing with error
code 103
- Added `downloadWithFallback` function that tries GitHub first, then
GitCode mirror
- If `OPENCLAW_USE_MIRROR=1` is set, the order is reversed (GitCode
first, then GitHub)

## Test plan
- [ ] Test installation with GitHub accessible
- [ ] Test installation with GitHub blocked (should fallback to GitCode
mirror)
- [ ] Test installation with `OPENCLAW_USE_MIRROR=1` environment
variable

Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-03-16 12:09:02 +08:00
SuYao
6eb461dd19 feat(skills): add vercel-react-best-practices skill (#13424)
### What this PR does

Before this PR:
No React/Next.js performance best practices skill available for AI
coding agents.

After this PR:
Adds the `vercel-react-best-practices` skill from
`vercel-labs/agent-skills`, providing 60+ React and Next.js performance
optimization rules covering rendering, re-renders, bundling, async
patterns, server components, and JS performance.

### Why we need it and why it was done in this way

The following tradeoffs were made:
- This skill includes ~8 Next.js server-specific rules (`server-*`,
`async-api-routes`) that are not applicable to our Electron + React
project. We chose to keep them rather than fork/trim the skill, since:
(1) AI agents will naturally ignore irrelevant rules based on context,
(2) keeping the full skill makes future upstream updates easier, and (3)
the ~50 React/JS/rendering/bundle rules provide significant value for
our codebase.

The following alternatives were considered:
- Forking the skill and removing Next.js-specific rules — rejected to
avoid maintenance burden and divergence from upstream.
- Writing a custom React-only skill — rejected as the Vercel skill
already covers the React patterns comprehensively.

Links to places where the discussion took place:
- Source: https://github.com/vercel-labs/agent-skills

### Breaking changes

None

### Special notes for your reviewer

- The skill is installed in
`.agents/skills/vercel-react-best-practices/` as the single source of
truth.
- `.claude/skills/vercel-react-best-practices` is a **directory
symlink** pointing to `.agents/skills/vercel-react-best-practices/`,
following the convention established in #13486. This replaces the
earlier approach of copying SKILL.md into a real directory.
- `public-skills.txt` was updated and `pnpm skills:sync` was run to
update `.gitignore` whitelists.
- Windows compatibility: Windows developers need symlink support enabled
(via `git config core.symlinks true` or Developer Mode). This is
consistent with the project-wide symlink convention adopted in #13486,
and confirmed working by @GeorgeDong32 on Windows 11 — Claude Code CLI
can load skills even when symlinks fall back to plaintext path files.
- The skill contains 60+ markdown rule files covering categories:
rendering, re-renders, bundle optimization, async patterns, server
components, client patterns, and JS performance.
- Rule applicability breakdown for our Electron + React project:

  | Category | Count | Applicable |
  |---|---|---|
  | `js-*` (JS perf) | 13 | Yes |
  | `rerender-*` (React) | 12 | Yes |
  | `rendering-*` | 11 | Mostly |
  | `bundle-*` | 5 | Partially |
  | `client-*` | 4 | Yes |
  | `advanced-*` | 3 | Yes |
  | `async-*` | 4 | Partially |
  | `server-*` (Next.js) | 8 | No |

### 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
NONE
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: icarus <eurfelux@gmail.com>
2026-03-16 11:57:21 +08:00
Phantom
74c892fe1a fix(agents): prevent deleting the last accessible directory (#13483)
### What this PR does

Before this PR:
Deleting the only accessible directory in Agent Settings fails silently
— `resolveAccessiblePaths()` treats `[]` the same as `undefined`,
replacing it with a default path. The directory reappears after
deletion.

After this PR:
- Backend: `AgentService.updateAgent()` and
`SessionService.updateSession()` reject empty `accessible_paths` with an
explicit error, enforcing the existing non-empty constraint.
- Frontend: The delete button is disabled (with a tooltip) when only one
accessible directory remains.

<img width="362" height="207" alt="image"
src="https://github.com/user-attachments/assets/4cd62081-ce77-46f7-bf0c-ca37be7f76cb"
/>


Fixes #13469

### Why we need it and why it was done in this way

The existing `resolveAccessiblePaths()` already assumes at least one
path (Claude Code session startup requires `accessible_paths[0]` as
cwd). Rather than changing this contract, we enforce it at both layers:

The following tradeoffs were made:
- Chose to disable the button rather than hide it, so users understand
the constraint.
- Used existing i18n key
`agent.session.accessible_paths.error.at_least_one` for the tooltip.

The following alternatives were considered:
- Allowing empty `accessible_paths` and handling it at runtime —
rejected because session startup already depends on non-empty paths, and
silently failing is worse UX.
- Only fixing backend or only frontend — rejected in favor of
defense-in-depth (frontend prevents the action, backend validates the
invariant).

### Breaking changes

None.

### Special notes for your reviewer

`resolveAccessiblePaths()` in `BaseService.ts` is intentionally **not**
modified — its existing behavior (fallback to default for both
`undefined` and `[]`) remains correct for the **creation** path. The fix
targets only the **update** path where `[]` should be rejected rather
than silently replaced.

### 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: 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

```release-note
Fixed a bug where deleting the last accessible directory in Agent Settings would fail silently. The delete button is now disabled when only one directory remains.
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 11:11:19 +08:00
Phantom
fe0678a206 chore: migrate .claude/skills to directory symlinks (#13486)
### What this PR does

Before this PR:

`.claude/skills/<name>/SKILL.md` files were **copied** from
`.agents/skills/<name>/SKILL.md` via `pnpm skills:sync`. A dedicated
`skills-check-windows` CI job ran on `windows-latest` to verify
cross-platform file-copy compatibility.

After this PR:

`.claude/skills/<name>` entries are **directory symlinks** pointing to
`../../.agents/skills/<name>`, following the Single Source of Truth
(SSoT) principle. The Windows-specific CI job is removed; Windows
developers are expected to enable symlink support.

### Why we need it and why it was done in this way

The following tradeoffs were made:

- Windows developers must now manually enable symlink support (Developer
Mode + `git config --global core.symlinks true`). This is acceptable
because:
1. The existing `AGENTS.md` is already a symlink, so Windows
compatibility was never fully enforced.
2. Symlinks eliminate the need for file-copy synchronization, reducing
maintenance complexity.
3. Contributors are expected to have sufficient technical capability to
configure their environments.

The following alternatives were considered:

- Keeping file-copy sync: rejected because it duplicates content and
requires extra CI to verify consistency.

### Breaking changes

Windows developers who clone without symlink support enabled will get
plain text files instead of symlinks. They must:
1. Enable Developer Mode or grant `SeCreateSymbolicLinkPrivilege`
2. Run `git config --global core.symlinks true`
3. Re-clone or run `pnpm skills:sync`

### Special notes for your reviewer

- The `.github/workflows/ci.yml` diff includes minor quote-style changes
(`'` → `"`) from the YAML formatter — these are cosmetic only.

### 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
- [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.
- [ ] 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
NONE
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 08:46:46 +08:00
Yaron
19bd2cdd93 feat(ui): enable windows mica effect (#13476) 2026-03-15 13:20:31 +08:00
Phantom
8b98b8f9c6 fix(agents): use correct SWRInfinite cache key and add optimistic update for session editing
Fixes SWRInfinite cache key usage and adds optimistic updates for session editing.
2026-03-15 11:32:13 +08:00
Phantom
c6ce1deecd fix(ui): show web search providers for all models (#13472)
### What this PR does

Before this PR:
Web search provider options (Tavily, SearXNG, etc.) were only shown for
models matching `isFunctionCallingModel()` or when the user explicitly
set prompt tool-use mode. Local LLM models (e.g. Ollama) showed an empty
web search panel.

After this PR:
Web search provider options are always available for all models.

Fixes #13466

### Why we need it and why it was done in this way

At runtime, models that lack native function-calling support
automatically fall back to prompt-based tool use
(`ApiService.ts:254-256`), so web search providers work regardless of
model capability. The UI gate was unnecessarily restrictive and out of
sync with runtime behavior.

The following tradeoffs were made:
- This removes the UI-level capability check entirely. A discussion
point is whether users should be informed that prompt-based tool use is
being used as a fallback (no visual indicator currently exists).

The following alternatives were considered:
- Matching the gate to the runtime fallback condition
(`isFunctionCallingModel || isToolUseModeFunction`) — rejected because
prompt mode has almost no model restrictions, making any gate
unnecessary.

### Breaking changes

None.

### Special notes for your reviewer

**Behavior change**: selecting a web search provider on a
non-function-calling model now silently triggers prompt-based tool use
at runtime (this fallback already existed but was previously unreachable
from the UI). Please consider whether this implicit fallback is
acceptable or if it needs a user-visible indicator.

### 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: N/A
- [x] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
Fixed web search provider options not showing for local LLM models (e.g. Ollama) in the chat input toolbar.
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 09:49:20 +08:00
Phantom
e860dd448f feat(agents): add manual drag-and-drop sorting for agent and session lists (#13460)
### What this PR does

Before this PR:
Agents and sessions in the sidebar are listed in fixed order with no way
to manually reorder them.

After this PR:
Both agents and sessions can be reordered via drag-and-drop. The order
is persisted to the SQLite database via a new `sort_order` column, and
new items are automatically placed at the top of the list. Session
sorting is scoped per-agent (each agent's sessions are independently
sortable).

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Used `sort_order` integer column in SQLite (backend persistence)
rather than Redux/localStorage, because agents/sessions data lives in
the backend DB — consistent with the existing architecture.
- New agents/sessions get `sort_order = 0` and all existing items are
shifted up by 1, matching the assistant list behavior where new items
appear at the top.
- Reused `DraggableList` component for agents and `DraggableVirtualList`
for sessions (both using `@hello-pangea/dnd`) for consistency with
existing drag-and-drop patterns.
- Added dedicated `PUT /v1/agents/reorder` and `PUT
/v1/agents/{agentId}/sessions/reorder` endpoints rather than updating
sort_order through individual PATCH calls, to ensure atomic reorder
operations.

The following alternatives were considered:
- Storing order in Redux/localStorage — rejected because agents/sessions
are fetched from the backend SQLite DB via HTTP API, so the order would
diverge.
- Using `@dnd-kit/sortable` instead of `@hello-pangea/dnd` — rejected to
maintain consistency with existing components.

### Breaking changes

None. The new `sort_order` column defaults to `0` for all existing
agents and sessions, so they will share the same sort order initially
and fall back to `created_at DESC` as tie-breaker.

### Special notes for your reviewer

**Database migration:**
- `0003_slippery_wild_pack.sql` adds `sort_order INTEGER NOT NULL
DEFAULT 0` to both `agents` and `sessions` tables
- Schema defines indexes (`idx_agents_sort_order`,
`idx_sessions_sort_order`) for query performance
- Existing rows get `sort_order = 0` by default; the first reorder
operation will assign proper values

**API changes:**
- `PUT /v1/agents/reorder` — accepts `{ ordered_ids: string[] }` to
reorder agents
- `PUT /v1/agents/{agentId}/sessions/reorder` — accepts `{ ordered_ids:
string[] }` to reorder sessions (scoped to agent)
- `GET /v1/agents` — default sort changed to `sort_order ASC, created_at
DESC`
- `GET /v1/agents/{agentId}/sessions` — default sort changed to
`sort_order ASC, created_at DESC`

**Frontend:**
- `useAgents` hook exposes `reorderAgents()` with optimistic SWR cache
update
- `useSessions` hook exposes `reorderSessions()` with optimistic
SWRInfinite cache update (preserves real total for pagination)
- `AgentSidePanel` uses `DraggableList` for agent drag-and-drop
- `Sessions` component swapped from `DynamicVirtualList` to
`DraggableVirtualList` for session drag-and-drop

**Atomicity:**
- `createSession` wraps sort_order shift + insert in a transaction
- `reorderAgents` and `reorderSessions` both use transactions

### 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
Added drag-and-drop manual sorting for agent and session lists in the sidebar panel.
```

---------

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
2026-03-15 09:41:11 +08:00
Phantom
f0f04eeda0 docs: update agents.db path in CLAUDE.md after #13392 (#13471)
### What this PR does

Before this PR:

CLAUDE.md described agents.db path as `~/.cherrystudio/data/agents.db`
(dev) / `userData/agents.db` (prod), which is outdated after #13392.

After this PR:

Updated to reflect the unified path `{userData}/Data/agents.db` with
macOS examples for both dev and prod.

Fixes #

N/A

### Why we need it and why it was done in this way

The following tradeoffs were made:

None. Straightforward documentation update.

The following alternatives were considered:

N/A

Links to places where the discussion took place:

https://github.com/CherryHQ/cherry-studio/pull/13392

### Breaking changes

None.

### Special notes for your reviewer

N/A

### 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
NONE
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 23:02:35 +08:00
Octopus
46ad0fa5d8 feat: add MiniMax-M2.5-highspeed model (#13470)
## Summary

Add the `MiniMax-M2.5-highspeed` model to both `minimax` (CN) and
`minimax-global` provider model lists.

## Changes

- Add `MiniMax-M2.5-highspeed` model entry to the `minimax` provider
model list
- Add `MiniMax-M2.5-highspeed` model entry to the `minimax-global`
provider model list

## Context

`MiniMax-M2.5-highspeed` is an officially available MiniMax model that
offers the same performance as `MiniMax-M2.5` but with faster inference
speed and more agility. It supports 204,800 tokens context window.

- API Documentation:
https://platform.minimax.io/docs/api-reference/text-openai-api

Signed-off-by: octo-patch <octo-patch@users.noreply.github.com>
Co-authored-by: octo-patch <octo-patch@users.noreply.github.com>
2026-03-14 22:56:25 +08:00
SuYao
774cb7a73c fix(openclaw): fix gateway status detection and improve error reporting (#13433)
### What this PR does

Before this PR:

- `getStatus` only probed health when status was `stopped` or `error`.
If the gateway crashed while status was `running`, the UI would never
detect the crash and keep showing "运行中" (running).
- `checkHealth` probed the gateway but never updated `gatewayStatus`, so
a failed health check had no lasting effect.
- `startAndWaitForGateway` spawned the process with `stdio: 'ignore'`,
discarding stderr. On startup failure, the user only saw "gateway exited
with code 1" with no actionable detail.
- `parseUpdateStatus` matched any update channel (npm, pkg, binary),
causing false positives for binary-installed users when only an npm/pkg
update was available.

After this PR:

- `getStatus` probes health in all non-`starting` states, transitioning
`running → stopped` when the gateway is unreachable.
- `checkHealth` syncs `gatewayStatus` to `stopped` when the probe
returns unhealthy.
- `startAndWaitForGateway` pipes stderr and extracts the first 3 lines
of error output for meaningful error messages.
- `parseUpdateStatus` only matches binary-channel updates, ignoring
npm/pkg channels.
- 29 new state-machine tests cover all gateway status transitions and
lifecycle scenarios.

Fixes #

### Why we need it and why it was done in this way

The gateway status was a one-way latch: once set to `running`, it could
only be changed by an explicit `stopGateway` call. External crashes
(process killed, config errors, port conflicts) left the UI in an
incorrect state.

The following tradeoffs were made:

- `getStatus` now always calls `probeGatewayHealth` (except during
`starting`). This adds a small overhead per status poll, but is
necessary for correctness since the gateway process lifecycle is
independent (detached).
- stderr capture uses `['ignore', 'ignore', 'pipe']` instead of full
`'pipe'` to minimize resource usage — we only need stderr for error
diagnostics.

The following alternatives were considered:

- Keeping a persistent health-check interval timer — rejected as
over-engineered for the current polling-based UI.
- Parsing the full `openclaw update status` table structure — rejected
in favor of simple regex matching on the `binary` channel keyword.

### Breaking changes

None.

### Special notes for your reviewer

- The `parseUpdateStatus` change means users who installed OpenClaw via
npm will no longer see update notifications in Cherry Studio. This is
intentional — Cherry Studio only manages binary installations.
- The test file grew significantly (from 90 lines to 595 lines) because
this is the first time the `OpenClawService` class has state-machine
test coverage.

### 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: 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(openclaw): gateway status now correctly detects crashed/externally-stopped gateways; startup errors show detailed messages instead of generic exit codes; update checker only reports binary-channel updates
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
2026-03-14 21:25:53 +08:00
Phantom
f3244c3e9e fix(aiCore): bypass AI SDK model ID allowlist for reasoning detection (#13463)
### What this PR does

Before this PR:

When using reasoning models (e.g., GPT-5.2) through third-party
OpenAI-compatible providers that use the Responses API endpoint,
`reasoningEffort` and `reasoningSummary` settings from the UI are
silently ignored. The AI SDK logs a warning: `reasoningEffort is not
supported for non-reasoning models`.

After this PR:

Reasoning parameters are correctly included in the Responses API request
body for all providers, regardless of model ID format.

Fixes #13454

### Why we need it and why it was done in this way

The following tradeoffs were made:

The `@ai-sdk/openai` Responses model uses a hardcoded model ID allowlist
(`modelId.startsWith('gpt-5')`, etc.) to determine if a model supports
reasoning. Third-party providers often use non-canonical model IDs
(e.g., `openai/gpt-5.2`) that fail these checks, causing reasoning
params to be silently dropped.

The fix uses `forceReasoning: true` — a bypass mechanism provided by the
AI SDK — when Cherry Studio's own `isReasoningModel()` detects the model
as a reasoning model. This is semantically correct: Cherry Studio's
model detection is more comprehensive than the AI SDK's allowlist.

The following alternatives were considered:

- Migrating to `@ai-sdk/open-responses` (tracked in #13462) — better
long-term solution but larger scope
- Stripping model ID prefixes before passing to the AI SDK — fragile and
provider-specific
- Using `openai-compatible` provider with manual reasoning parameter
handling — would lose Responses API features

### Breaking changes

None.

### Testing

- [x] Manual test passed: confirmed `reasoning.effort` and
`reasoning.summary` are now correctly included in the Responses API
request body when using a third-party provider with non-canonical model
IDs.

### Special notes for your reviewer

- The `forceReasoning` option is an official AI SDK feature, not a hack.
It's documented for exactly this use case: "stealth" reasoning models
where the model ID is not recognized by the SDK's allowlist.
- `isReasoningModel(model)` is used instead of `enableReasoning` because
`forceReasoning` should reflect model capability, not user preference.
- A TODO comment links to #13462 for the longer-term migration to
`@ai-sdk/open-responses`.

### 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: 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
fix: reasoning effort and summary mode settings now correctly apply for third-party OpenAI-compatible providers using the Responses API endpoint
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 19:25:14 +08:00
Phantom
d676b3b39a chore: add Zed editor settings example, clean up configs, and improve dev guides (#13457)
### What this PR does

Before this PR:
- No Zed editor configuration example existed for contributors using Zed
- Several config files had inconsistent JSON array formatting
- `biome.jsonc` had redundant exclude rules
- Contributing guides did not reference the development guide
- `development.md` (zh) was not translated to Chinese
- Node.js and pnpm versions were hardcoded in the development guide

After this PR:
- Added `.zed/settings.json.example` with Biome formatter,
oxc/eslint/biome fixAll, and import organization
- Cleaned up redundant Biome exclude rules and unified JSON array
formatting
- Added "Setting Up Your Development Environment" section to
`CONTRIBUTING.md` (en/zh) linking to the development guide
- Added Zed editor setup guide to `development.md` (en/zh)
- Translated `docs/zh/guides/development.md` to Chinese
- Node.js version now references `.node-version`; pnpm version
references `packageManager` in `package.json`
- VSCode extensions now reference `.vscode/extensions.json`

### Why we need it and why it was done in this way

The following tradeoffs were made:
- The Zed settings file is provided as an `.example` rather than a
direct `.zed/settings.json` to avoid overriding individual contributor
preferences.
- Versions reference their source of truth files rather than being
hardcoded, so docs stay in sync automatically.

The following alternatives were considered:
- N/A

### Breaking changes

None

### Special notes for your reviewer

- The JSON formatting changes are purely cosmetic — no behavior changes.
They align with Biome's default formatting rules.
- The `.zed/settings.json.example` includes `source.fixAll.eslint` and
`source.fixAll.oxc` alongside Biome, matching the project's
triple-linter setup.

### 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
- [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

```release-note
NONE
```

---------

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 18:03:54 +08:00
Phantom
aeae3be69c fix: increase default request timeout from 10 to 30 minutes (#13453)
### What this PR does

Before this PR:

The default request timeout for LLM API calls was 10 minutes. When using
local models (e.g., LM Studio with Qwen 3.5 28b), the model may take
longer than 10 minutes to process input data, causing a `TimeoutError` /
`AbortError` before the model finishes responding.

After this PR:

The default request timeout is increased to 30 minutes, giving local
models enough time to complete inference.

Fixes #13452

### Why we need it and why it was done in this way

Local models running on consumer hardware (e.g., via LM Studio, Ollama)
can take significantly longer to process requests compared to cloud
APIs. The previous 10-minute timeout was insufficient for large local
models like Qwen 3.5 28b.

The following tradeoffs were made:

This is a temporary fix as discussed in the issue. User-configurable
timeout settings will be available after v2.0.0.

The following alternatives were considered:

- Per-provider timeout configuration (deferred to v2)
- Separate timeout for local vs cloud providers (unnecessary complexity
for a temporary fix)

### Breaking changes

None.

### Special notes for your reviewer

The `DEFAULT_TIMEOUT` constant is used across both the new AI Core path
(`parameterBuilder.ts`) and the legacy client path (`BaseApiClient.ts`).
The flex service tier timeout (15 min) is now shorter than the default
(30 min), but flex tier models are cloud-hosted and unlikely to need
more than 15 minutes.

### 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: 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
Increased the default request timeout from 10 minutes to 30 minutes, preventing premature timeout errors when using slow local models (e.g., LM Studio, Ollama).
```

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 17:35:39 +08:00
Phantom
9c3c990365 feat: separate Agent into independent module with dedicated page and route (#13420)
### What this PR does

Before this PR:
Agent and Assistant were mixed in a single `UnifiedList` in the home
page sidebar. Users had difficulty discovering the Agent entry. The two
have fundamentally different data models (Redux vs SQLite), interaction
patterns (topic vs session), and component hierarchies, yet shared the
same UI components and Redux state (`activeTopicOrSession`).

After this PR:
Agent is separated into an independent module with its own sidebar
entry, route (`/agents`), page, navbar, and side panel. The home page
only handles Assistants. Navigation between the two is handled via
sidebar icons and routes, not Redux state.

Fixes #13329

### Why we need it and why it was done in this way

The following tradeoffs were made:
- `AgentSettingsTab` was moved to `pages/agents/` and is used by the
`AgentChatNavbar/Tools/SettingsButton` drawer.
- `Unified*` components were renamed to `Assistant*` (via `git mv`)
rather than just removing agent code, to make naming accurate and
improve readability.
- `activeTopicOrSession` was removed from Redux runtime store entirely,
replaced by route-based detection where needed, avoiding stale state
issues.

The following alternatives were considered:
- Keeping a shared `UnifiedList` with a filter — rejected because the
data models and interaction patterns are too different, leading to
excessive conditional logic.
- Using a tab within the home page — rejected per issue spec; agents
need their own sidebar entry and dedicated page for discoverability.

### Breaking changes

None. This is an internal UI refactoring. The Redux migration (v200 →
v201) automatically adds the `'agents'` sidebar icon to existing user
configurations.

### Special notes for your reviewer

**New directory structure — `pages/agents/`:**
- `AgentPage.tsx` — Top-level page with apiServer.enabled guard (early
return with alert when server disabled)
- `AgentChat.tsx` — Chat area with loading state management (Spin during
initialization, alerts for select/create states)
- `AgentNavbar.tsx` — Top navbar for left-sidebar layout mode
- `AgentSidePanel.tsx` — Left panel with agent list and sessions tabs
- `AgentSettingsTab.tsx` — Moved from home, used by AgentChatNavbar
settings drawer
- `components/AgentChatNavbar/` — Mirrors `home/components/ChatNavBar/`
structure:
  - `index.tsx` — Sidebar toggle buttons + content wrapper
- `AgentContent.tsx` — Agent → Session → Model → Workspace breadcrumb
navigation
- `Tools/` — Agent-specific toolbar with `SettingsButton` (uses
`AgentSettingsTab`)
- `OpenExternalAppButton.tsx`, `SessionWorkspaceMeta.tsx` —
AgentContent-only components
- `components/` — Migrated agent-only components: `AgentItem`,
`AgentSessionInputbar`, `AgentSessionMessages`,
`SelectAgentBaseModelButton`, `SessionItem`, `Sessions`

**Hook consolidation:**
- Merged two duplicate `useActiveAgent` hooks into one at
`hooks/agents/useActiveAgent` — now returns both `{ agent, error,
isLoading, setActiveAgentId }`
- Deleted `home/Tabs/hooks/useActiveAgent.ts`

**Loading state improvements:**
- `AgentPage` top-level guard prevents all child components from
rendering when apiServer is disabled
- `AgentChat` tracks `isInitializing` covering: server starting → agents
loading → agent loading → session initializing → auto-select pending
- `useAgentSessionInitializer` now distinguishes `undefined` (not
initialized) vs `null` (initialized, no sessions) in
`activeSessionIdMap`, preventing premature "create session" alerts

**Shared component extraction:**
- `AddButton` moved from `home/Tabs/components/` to
`renderer/src/components/` (used by both pages)

### 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
Added a dedicated "Agents" page accessible from the sidebar, separating Agents from the Assistants list for improved discoverability and clearer navigation.
```

---------

Signed-off-by: icarus <eurfelux@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
2026-03-14 17:05:22 +08:00
George·Dong
ea694c630c feat(assistant): add configurable max tool calls setting (#13398)
### What this PR does

**Before this PR:**
The MCP tool call limit was hard-coded to 20 in `parameterBuilder.ts`:
```typescript
stopWhen: stepCountIs(20)
```
Users could not customize this limit, which was reported in #13370 as a
limitation for workflows requiring more tool calls.

**After this PR:**
- Added configurable `maxToolCalls` setting (range: 1-100) in Assistant
Settings → Model Settings
- Added `enableMaxToolCalls` toggle to control the feature
- Default behavior unchanged: 20 tool calls limit (matching AI SDK
default)
- Users can increase the limit if their workflow requires more tool
calls
- All i18n translations added for 11 languages

Fixes #13370

### Why we need it and why it was done in this way

**Tradeoffs:**
- Default value kept at 20 to prevent infinite loops and maintain
backward compatibility
- Range limited to 1-100 to prevent excessive token usage and API costs

**Alternatives considered:**
- Setting default to "unlimited" - rejected because AI SDK designed 20
as default for safety
- Making it a global setting - rejected because different assistants may
need different limits

### Breaking changes

None. Default behavior remains unchanged (20 tool calls). Existing users
will continue to have the same experience.

### Special notes for your reviewer

- The `enableMaxToolCalls` field defaults to `true` to maintain the
original 20-call behavior
- When disabled, it still uses 20 (AI SDK's default), not unlimited
- `getAssistantSettings()` properly returns the new fields for
consistent access

### 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
- [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

```release-note
Added configurable maximum tool calls setting for assistants. Users can now customize the tool call limit (1-100) in Assistant Settings → Model Settings. Default remains at 20 calls to prevent infinite loops, matching AI SDK's design.
```

---------

Co-authored-by: icarus <eurfelux@gmail.com>
2026-03-13 23:39:31 +08:00
亢奋猫
97011c8bb2 feat(openclaw): binary download install, auto update check, and gateway refactor (#13440)
### What this PR does

Refactors OpenClaw installation to use direct binary downloads instead
of npm, adds auto update detection, and delegates gateway lifecycle to
OS service manager CLI commands.

**Binary download install (replaces npm install):**
- Download pre-built binaries from GitHub releases (or gitcode.com
mirror for China users)
- Install to `~/.cherrystudio/bin/` — no npm/Node.js dependency required
- Uninstall by simply deleting the binary file
- Detect old npm-installed versions and prompt migration

**Auto update check:**
- Automatically check for updates via `openclaw update status` when
entering the OpenClaw page
- Show info alert with version details when an update is available
- Perform update via `openclaw update` command (stops gateway first if
running)
- Version parsing extracted to `services/utils/openClawParsers.ts` with
inline snapshot tests

**Gateway lifecycle refactor:**
- Gateway lifecycle delegated to OS service manager via `openclaw
gateway` CLI commands
- Removes in-process `ChildProcess` management, `node:net` Socket
probing, and `killProcess` helper
- Health checks use `openclaw gateway health` CLI command
- `getStatus` is now async and probes health to detect
externally-started gateways
- Return type unified to discriminated union `OperationResult`

**Windows-specific handling:**
- Skip `gateway install/uninstall` (scheduled task integration has
upstream bugs)
- Gateway started via `openclaw gateway start --force`
- Port conflict detection before startup with clear error messages

**UI improvements:**
- Auto update alert with "Reinstall" button when new version detected
- Copy button on install/uninstall log container and error alerts

### Why we need it and why it was done in this way

- Binary download is faster, more reliable, and removes the npm/Node.js
dependency for end users
- `openclaw update` leverages the tool's built-in update mechanism
rather than re-downloading
- Delegating to OS service management (launchd/systemd) is more robust —
the gateway survives app restarts
- Version parsers are pure functions with snapshot tests to prevent
regressions

### Breaking changes

None. Internal refactoring only — no user-facing API changes.

### Special notes for your reviewer

- New IPC channels: `OpenClaw_CheckUpdate`, `OpenClaw_PerformUpdate`
- New file: `src/main/services/utils/openClawParsers.ts` (pure parsing
functions)
- New test: `src/main/services/__tests__/OpenClawService.test.ts` (16
snapshot tests)
- i18n: added `openclaw.update.*` and
`openclaw.quick_actions.check_update` keys (all locales synced)
- Windows: no service registration, gateway started with `--force`, port
checked before startup
- macOS/Linux: full service lifecycle via CLI commands

### 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: 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.
- [x] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
feat(openclaw): switch to binary download install and add auto update check
fix(openclaw): gateway start or stop exception
```

---------

Co-authored-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 18:12:21 +08:00
Konv Suu
4aef249151 fix: correctly pass poe web_search via extra_body when built-in search is enabled (#13434)
Fix #13305 

>
https://creator.poe.com/docs/external-applications/openai-compatible-api#using-custom-parameters-with-extra_body

```js
import OpenAI from "openai";

const client = new OpenAI({
    apiKey: process.env.POE_API_KEY,
    baseURL: "https://api.poe.com/v1",
});

// Example: Using web search and thinking level with Gemini models
const response = await client.chat.completions.create({
    model: "Gemini-3-Pro",
    messages: [{ role: "user", content: "What are the latest developments in quantum computing?" }],
    extra_body: {
        web_search: true,
        thinking_level: "high"
    }
});
```

```release-note
fix(poe): correctly pass poe web_search via extra_body when built-in search is enabled
```
2026-03-13 17:02:39 +08:00
亢奋猫
8dd42eb8ba chore: release v1.7.25 (#13438)
### What this PR does

Before this PR:
- Version is 1.7.24

After this PR:
- Version is 1.7.25
- Release notes updated in `electron-builder.yml`

### Why we need it and why it was done in this way

Standard release workflow: collect commits since v1.7.24, generate
bilingual release notes, bump version.

The following tradeoffs were made:
N/A

The following alternatives were considered:
N/A

### Breaking changes

**Action Required**: The built-in filesystem MCP server now requires
manual approval for write/edit/delete operations by default.

### Special notes for your reviewer

**Included commits since v1.7.24:**

 New Features:
- feat(websearch): add Querit search provider (#13050)
- feat(minapp,provider): add MiniMax Agent, IMA mini apps and MiniMax
Global, Z.ai providers (#13099)
- feat(provider): add agent support filter for provider list (#11932)
- feat(agent): add custom environment variables to agent configuration
(#13357)
- feat: add GPT-5.4 support (#13293)
- feat(gemini): add thought signature persistence (#13100)

🐛 Bug Fixes:
- fix: secure built-in filesystem MCP root handling (#13294)
- fix: check underlying tool permissions for hub invoke/exec (#13282)
- fix: remove approval countdown timers and add system notifications
(#13281)
- fix: agent tool status not stopping on abort (#13111)
- fix: resolve spawn ENOENT on Windows for Code Tools (#13405)
- fix: Use default assistant for topic auto-renaming (#13387)
- fix(backup): defer auto backup during streaming response (#13307)
- fix(ui): fix Move To submenu overflow (#13399)
- fix: render xml fenced svg blocks as svg previews (#13431)
- fix: correct Gemini reasoning params (#13388)
- fix: improve Qwen 3.5 reasoning model detection (#13235)
- fix: upgrade xAI web search to Responses API (#12812)
- fix(api-server): relax chat completion validation (#13279)
- fix: install or uninstall button state issues (#13114)
- fix: improve update dialog behavior (#13363)
- fix: auto-convert reasoning_effort to reasoningEffort (#12831)

### 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.
- [x] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
See release notes in electron-builder.yml
```

---------

Signed-off-by: kangfenmao <kangfenmao@qq.com>
v1.7.25
2026-03-13 16:48:15 +08:00
亢奋猫
5463c83ee2 refactor(openclaw): unify package to openclaw, remove openclaw-zh (#13436)
### What this PR does

Before this PR:
- OpenClaw installation used different npm packages based on user
location: `@qingchencloud/openclaw-zh@latest` for China users and
`openclaw@latest` for others

After this PR:
- All users install the unified `openclaw@latest` package
- China users still get npm mirror acceleration via `--registry` flag
- Uninstall removes both `openclaw` and legacy
`@qingchencloud/openclaw-zh` packages to clean up old installations

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Simplified package management by using a single package for all
regions

The following alternatives were considered:
- N/A

### Breaking changes

None.

### Special notes for your reviewer

N/A

### 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: A user-guide update was considered and is present
(link) or not required.
- [ ] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
NONE
```

Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-03-13 16:03:48 +08:00
kangfenmao
df4b214295 Revert "feat(openclaw): binary download install, auto update check, and gateway refactor (#13165)"
This reverts commit 74c0c907b8.
2026-03-13 15:52:27 +08:00
Konv Suu
7f3763bae8 fix: render xml fenced svg blocks as svg previews (#13431)
Fix #13409 


After:

<img width="462" alt="CleanShot 2026-03-13 at 10 54 11@2x"
src="https://github.com/user-attachments/assets/25c336c4-74c8-4532-9533-30911db93608"
/>

```release-note
render xml fenced svg blocks as svg previews
```
2026-03-13 12:13:05 +08:00
Phantom
134280a862 fix: use i18nKey for error display and add timeout enforcement (#12164)
### What this PR does

Before this PR:
- Abort/pause-related errors overwrote `message` with raw i18n keys
(e.g. `'pause_placeholder'`), losing the original error info for
debugging.
- Timeout errors (`DOMException` with `name === 'TimeoutError'`) were
not distinguished from user-initiated aborts, causing timeouts to
display as "Paused" in the UI.
- No `AbortSignal.timeout()` enforcement existed in the modern AI SDK
path (`parameterBuilder.ts`); `messageThunk.ts` passed `timeout: 30000`
in `requestOptions` but it was never used to create an abort signal —
effectively dead code.
- No localized timeout error message existed.
- The timeout constant `defaultTimeout` used camelCase, inconsistent
with other exported constants.
- The streaming-only behavior of the modern AI SDK path was not
documented.

After this PR:
- Use `i18nKey` field on `SerializedError` (instead of overwriting
`message`) for translated error display, preserving original error info
for the detail modal.
- Rename i18n key `pause_placeholder` → `stream_paused` and extract as a
named constant (`ERROR_I18N_KEY_STREAM_PAUSED`).
- Add `isTimeoutError()` utility to distinguish `DOMException
TimeoutError` from user-initiated `AbortError`, checking both `error`
and `error.cause`.
- Update `isAbortError()` to explicitly exclude timeout errors.
- Add `AbortSignal.timeout(DEFAULT_TIMEOUT)` (10 min) in
`parameterBuilder.ts`, combined with the external signal via
`AbortSignal.any()`.
- Remove the unused `timeout: 30000` from `messageThunk.ts`,
establishing `parameterBuilder.ts` as the single timeout control point.
- Rename constant `defaultTimeout` → `DEFAULT_TIMEOUT`
(SCREAMING_SNAKE_CASE) across all import sites.
- Add localized `request_timeout` i18n key
(`ERROR_I18N_KEY_REQUEST_TIMEOUT`) for all supported languages.
- Add JSDoc to `SerializedError` documenting known dynamic properties
(`i18nKey`, `providerId`).
- Add documentation notes clarifying the `streamText`-only path in
`index_new.ts` and `ApiService.ts`.

Fixes # (not applicable; relates to #12016)

### Why we need it and why it was done in this way

This PR attempts to address #12016, but per the upstream limitation
described in https://github.com/vercel/ai/issues/9655, the root cause is
not solvable purely from the client side. The changes here document the
streaming-only behavior, improve error handling, and add proper timeout
enforcement via `AbortSignal.timeout()`.

The following tradeoffs were made:
- Keep behavior changes minimal to avoid impacting existing request
flows.
- Use `i18nKey` field (already supported by `ErrorBlock.tsx` and
`ErrorHandlerMiddleware.ts`) instead of overwriting `message` — this
preserves original error info for the detail modal while enabling proper
i18n display.
- Establish `parameterBuilder.ts` as the single timeout control point
rather than allowing callers to pass their own timeout values, since no
caller currently provides a custom timeout.

The following alternatives were considered:
- Switching to a non-streaming path (`generateText`), but that is not
used in this runtime path and does not address the upstream limitation.
- Overwriting `message` with i18n keys (original approach) — rejected
because it loses debugging context and creates an implicit contract
between producers and consumers.
- Adding `i18nKey` as an explicit optional property on `SerializedError`
— rejected due to TypeScript's index signature constraint (`string |
undefined` is incompatible with `[key: string]: Serializable`);
documented via JSDoc instead.

Links to places where the discussion took place:
https://github.com/vercel/ai/issues/9655

### Breaking changes

None.

### Special notes for your reviewer

- This PR is a partial mitigation for #12016; the underlying issue is
upstream per the linked Vercel AI SDK issue.
- The `i18nKey` pattern on `SerializedError` is already used by
`ErrorHandlerMiddleware.ts` for auth/quota errors. This PR extends the
same pattern to abort and timeout errors.
- `isTimeoutError()` checks both `error` and `error.cause` for
`DOMException` with `name === 'TimeoutError'` to handle cases where the
AI SDK wraps the original timeout error.
- The `timeout: 30000` removed from `messageThunk.ts` was effectively
dead code — `parameterBuilder.ts` previously only passed through
`requestOptions.signal` but never used `requestOptions.timeout` for
abort signal creation.

### 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: A user-guide update was considered and is present
(link) or not required.

### Release note

```release-note
Improve streaming error handling: use i18nKey for localized error display while preserving original error info, add isTimeoutError utility with localized timeout messages, enforce timeout via AbortSignal.timeout() in the modern AI SDK path, and rename pause_placeholder to stream_paused.
```

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-13 10:06:14 +08:00
SuYao
ea6b2f83b9 fix: resolve single-conversation memory leaks in renderer process (#13113)
### What this PR does

Before this PR:
Long-running single-conversation agent sessions with many MCP tool calls
cause unbounded memory growth in the renderer process (1 GB → 4 GB+),
eventually crashing with OOM / white screen.

<img width="960" height="607" alt="image"
src="https://github.com/user-attachments/assets/e11203a0-5f16-43af-a952-5572c38fb044"
/>


After this PR:
Four previously-leaked resource categories are properly cleaned up
during normal operation and on stream abort:
1. **blockUpdateThrottlers LRU** – evicted throttlers now cancel their
pending work and associated `requestAnimationFrame` callbacks.
2. **messagePersistThrottlers LRU** – evicted agent-message persist
throttlers are cancelled on eviction.
3. **toolPermissions Redux state** – pending tool permission requests
are cleared when a stream errors or is aborted.
4. **partialArguments in tool metadata** – the redundant streaming JSON
buffer is stripped from completed tool blocks, avoiding duplicate large
strings in Redux and IndexedDB.

<img width="732" height="831" alt="image"
src="https://github.com/user-attachments/assets/15f2383d-b1e5-47b2-b311-2c1545574ab4"
/>


Fixes #12974

### Why we need it and why it was done in this way

The following tradeoffs were made:
- `toolPermissionsActions.clearAll()` is dispatched on every stream
error/abort. This is safe because each stream owns its own set of
permission requests, and a new stream will create fresh entries.
- `partialArguments` is set to `undefined` rather than deleted, since
the spread merge makes `delete` ineffective.

The following alternatives were considered:
- Scoped cleanup per tool call ID instead of `clearAll` for tool
permissions. Rejected because the existing `removeByToolCallId` already
handles per-call cleanup; the gap was only on abort where all pending
requests should be discarded.

Links to places where the discussion took place:
- Companion PR for multi-conversation fixes: #12975

### Breaking changes

None.

### Special notes for your reviewer

This PR is designed to complement #12975 (which addresses
multi-conversation leaks like topic cache eviction, abort controller
cleanup, and `globalActiveToolCalls` cleanup). There is zero overlap
between the two PRs.

### 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 memory management fix with
no user-facing behavior 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>
2026-03-13 10:04:28 +08:00
SuYao
da10cca0ed fix: secure built-in filesystem MCP root handling (#13294)
### What this PR does

Before this PR:
- The built-in filesystem MCP server accepted absolute paths outside the
configured workspace root.
- The in-memory filesystem server only read `WORKSPACE_ROOT`, so roots
configured via `args` were ignored.
- The server registered tool handlers asynchronously, which could cause
first-load `mcp:list-tools` failures.
- Sensitive filesystem tools could be auto-approved by default.

<img width="929" height="641" alt="image"
src="https://github.com/user-attachments/assets/1ec4ba6d-f274-40df-a8df-7d9c54e3e8fc"
/>


After this PR:
- Filesystem MCP paths are constrained to the configured workspace root
after realpath resolution.
- The built-in filesystem server resolves its root from `WORKSPACE_ROOT`
or the configured `args`.
- Tool handlers are registered before async directory initialization
starts.
- Built-in filesystem `write`, `edit`, and `delete` require manual
approval by default, including a backfill for existing configs.

<img width="996" height="667" alt="image"
src="https://github.com/user-attachments/assets/44ef44cc-7e50-4244-80b0-ec742df2af0a"
/>


Fixes #12447

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Existing filesystem MCP configurations now default to safer approval
behavior for destructive tools.
- Path validation resolves symlinks and nearest existing ancestors to
block directory escapes for both existing and newly created paths.

The following alternatives were considered:
- Trusting UI configuration alone without enforcing the root in the
filesystem tool layer.
- Keeping auto-approve defaults unchanged and relying on users to
disable risky tools manually.
- Waiting for async initialization to finish before serving requests
instead of registering handlers immediately.

Links to places where the discussion took place: #12447, #13280

### Breaking changes

The built-in filesystem MCP server now requires manual approval for
`write`, `edit`, and `delete` by default. Users who relied on automatic
approval for these tools need to re-enable auto-approve explicitly.

### Special notes for your reviewer

- This PR does not change Redux state shape or IndexedDB schema.
- Added regression coverage for root resolution, path escapes, symlink
escapes, and filesystem approval defaults.

### 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
action required: The built-in filesystem MCP server now enforces the configured workspace root and requires manual approval for write, edit, and delete operations by default.
```

---------

Signed-off-by: suyao <sy20010504@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:02:21 +08:00
亢奋猫
d0ce48ee61 fix: improve update dialog behavior and prevent unexpected auto-updates (#13363)
### What this PR does

Before this PR:
- When user clicks "Check for Update" and download completes, the update
dialog does not show automatically
- `autoInstallOnAppQuit` was tied to `autoDownload` setting, causing
unexpected auto-updates when app restarts or system shuts down
- Force shutdown during auto-install could corrupt or uninstall the app
- Update installation required user to click through the installer
wizard (Next → Next → Finish)

After this PR:
- Update dialog automatically shows when user manually checks for
updates and download completes
- Background automatic checks won't show the dialog to avoid disturbing
users
- `autoInstallOnAppQuit` is always `false` - users must explicitly click
"Install Now" to trigger update installation
- Update installation is now one-click: clicking "Install Now" will
silently install and auto-restart the app

### Why we need it and why it was done in this way

The following tradeoffs were made:
- Added `manualCheck` field to `UpdateState` to track whether the update
check was triggered by user action
- This allows distinguishing between manual checks (should show dialog)
and automatic background checks (should not disturb user)

The following alternatives were considered:
- Using URL hash check
(`window.location.hash.includes('settings/about')`) - rejected because
user might navigate away during download
- Always showing dialog on download complete - rejected because it would
disturb users during automatic background checks

### Breaking changes

None. This is a behavior improvement that makes updates more
user-friendly and safer.

### Special notes for your reviewer

Four separate commits for related but distinct fixes:
1. `fix: auto show update dialog when user manually checks for updates`
- Shows dialog only for manual checks
2. `fix: disable autoInstallOnAppQuit to prevent unexpected updates` -
Prevents auto-install on app quit
3. `fix: reset manualCheck state on update check completion and error` -
Properly resets state after check
4. `fix: ensure forced installation on quit in quitAndInstall method` -
Uses `quitAndInstall(true, true)` for silent installation with
auto-restart (Windows)

### 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
- [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: Update dialog now automatically shows when user manually checks for updates. Also fixed an issue where the app would unexpectedly auto-update on restart or system shutdown - users must now explicitly click "Install Now" to install updates. On Windows, the update installation is now one-click (silent install with auto-restart).
```

---------

Signed-off-by: kangfenmao <kangfenmao@qq.com>
2026-03-13 09:53:09 +08:00
SuYao
74c0c907b8 feat(openclaw): binary download install, auto update check, and gateway refactor (#13165)
### What this PR does

Refactors OpenClaw installation to use direct binary downloads instead
of npm, adds auto update detection, and delegates gateway lifecycle to
OS service manager CLI commands.

**Binary download install (replaces npm install):**
- Download pre-built binaries from GitHub releases (or gitcode.com
mirror for China users)
- Install to `~/.cherrystudio/bin/` — no npm/Node.js dependency required
- Uninstall by simply deleting the binary file
- Detect old npm-installed versions and prompt migration

**Auto update check:**
- Automatically check for updates via `openclaw update status` when
entering the OpenClaw page
- Show info alert with version details when an update is available
- Perform update via `openclaw update` command (stops gateway first if
running)
- Version parsing extracted to `services/utils/openClawParsers.ts` with
inline snapshot tests

**Gateway lifecycle refactor:**
- Gateway lifecycle delegated to OS service manager via `openclaw
gateway` CLI commands
- Removes in-process `ChildProcess` management, `node:net` Socket
probing, and `killProcess` helper
- Health checks use `openclaw gateway health` CLI command
- `getStatus` is now async and probes health to detect
externally-started gateways
- Return type unified to discriminated union `OperationResult`

**Windows-specific handling:**
- Skip `gateway install/uninstall` (scheduled task integration has
upstream bugs)
- Gateway started via `openclaw gateway start --force`
- Port conflict detection before startup with clear error messages

**UI improvements:**
- Auto update alert with "Reinstall" button when new version detected
- Copy button on install/uninstall log container and error alerts

### Why we need it and why it was done in this way

- Binary download is faster, more reliable, and removes the npm/Node.js
dependency for end users
- `openclaw update` leverages the tool's built-in update mechanism
rather than re-downloading
- Delegating to OS service management (launchd/systemd) is more robust —
the gateway survives app restarts
- Version parsers are pure functions with snapshot tests to prevent
regressions

### Breaking changes

None. Internal refactoring only — no user-facing API changes.

### Special notes for your reviewer

- New IPC channels: `OpenClaw_CheckUpdate`, `OpenClaw_PerformUpdate`
- New file: `src/main/services/utils/openClawParsers.ts` (pure parsing
functions)
- New test: `src/main/services/__tests__/OpenClawService.test.ts` (16
snapshot tests)
- i18n: added `openclaw.update.*` and
`openclaw.quick_actions.check_update` keys (all locales synced)
- Windows: no service registration, gateway started with `--force`, port
checked before startup
- macOS/Linux: full service lifecycle via CLI commands

### 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: 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.
- [x] Self-review: I have reviewed my own code before requesting review
from others

### Release note

```release-note
feat(openclaw): switch to binary download install and add auto update check
fix(openclaw): gateway start or stop exception
```

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: kangfenmao <kangfenmao@qq.com>
2026-03-13 09:49:35 +08:00