Skip to content

Commit 504f487

Browse files
committed
merge: integrate 0.10.1 review branch
2 parents 679b447 + 8d5f25d commit 504f487

18 files changed

Lines changed: 458 additions & 71 deletions

File tree

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ All notable changes to CC Switch will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.10.1] - 2026-03-15
9+
10+
### Fixes / 修复
11+
12+
- Preserve stored Web credentials until a new API base login succeeds, and stop cross-origin username fallback from binding to the wrong account
13+
- Harden malformed OpenCode provider sync by skipping invalid entries deterministically during live additive sync
14+
- Persist provider snapshots after desktop `sync_current_providers_live` so sync results survive restart
15+
16+
### Tests / 测试
17+
18+
- Add targeted coverage for Web auth validation paths and OpenCode live-sync edge cases
19+
820
## [0.10.0] - 2026-03-14
921

1022
### Features / 新特性

README.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
English | [中文](README_ZH.md) | [Changelog](CHANGELOG.md)
1717

18-
> Recommended stable release: [v0.9.2](https://github.com/Laliet/cc-switch-web/releases/tag/v0.9.2)
19-
> `v0.10.0` is currently a prerelease for testing only
18+
> Recommended stable release: [v0.10.1](https://github.com/Laliet/cc-switch-web/releases/tag/v0.10.1)
19+
> `v0.10.1` is the current stable release
2020
2121
## About / 项目简介
2222

@@ -41,18 +41,18 @@ If you have any questions, you can contact me here https://linux.do/t/topic/1217
4141

4242
## What's New
4343

44-
### v0.9.2 - Current Stable Release
44+
### v0.10.1 - Current Stable Release
4545

4646
- Recommended for daily use and production
47-
- Download stable builds from: [v0.9.2](https://github.com/Laliet/cc-switch-web/releases/tag/v0.9.2)
47+
- Download stable builds from: [v0.10.1](https://github.com/Laliet/cc-switch-web/releases/tag/v0.10.1)
4848

49-
### v0.10.0 - Current Prerelease
49+
### v0.10.0 - Prerelease Milestone
5050

5151
- Add OpenCode provider management and automatic OpenCode config writing
5252
- Add oh-my-opencode (OMO) configuration management and plugin sync support
5353
- Allow updating Web-mode login username/password directly from Settings
5454
- Improve rollback safety for OMO/OpenCode linked writes and current-provider edits
55-
- `v0.10.0` is currently a prerelease and still needs more cross-machine validation
55+
- `v0.10.0` was the verification prerelease milestone for this release line
5656

5757
### v0.8.0 - Previous Stable Baseline
5858

@@ -113,8 +113,8 @@ Download precompiled server binary—no compilation required:
113113

114114
| Architecture | Download |
115115
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
116-
| **Linux x86_64 (glibc)** | [cc-switch-server-linux-x86_64](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/cc-switch-server-linux-x86_64) |
117-
| **Linux aarch64 (glibc)** | [cc-switch-server-linux-aarch64](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/cc-switch-server-linux-aarch64) |
116+
| **Linux x86_64 (glibc)** | [cc-switch-server-linux-x86_64](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/cc-switch-server-linux-x86_64) |
117+
| **Linux aarch64 (glibc)** | [cc-switch-server-linux-aarch64](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/cc-switch-server-linux-aarch64) |
118118

119119
> **Note (glibc)**: Binaries are built on Ubuntu 22.04 (glibc baseline).
120120
> If you see `GLIBC_2.xx not found`, use Docker or build from source.
@@ -229,11 +229,11 @@ Full-featured desktop app with graphical interface, built with Tauri.
229229

230230
| Platform | Download | Description |
231231
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
232-
| **Windows** | [CC-Switch-v0.9.2-Windows.msi](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Windows.msi) | Installer (current stable) |
233-
| | [CC-Switch-v0.9.2-Windows-Portable.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Windows-Portable.zip) | Portable (no install) |
234-
| **macOS** | [CC-Switch-v0.9.2-macOS.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-macOS.zip) | Universal binary (Intel + Apple Silicon) |
235-
| **Linux** | [CC-Switch-v0.9.2-Linux.AppImage](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Linux.AppImage) | AppImage (current stable) |
236-
| | [CC-Switch-v0.9.2-Linux.deb](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Linux.deb) | Debian/Ubuntu package |
232+
| **Windows** | [CC-Switch-v0.10.1-Windows.msi](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Windows.msi) | Installer (current stable) |
233+
| | [CC-Switch-v0.10.1-Windows-Portable.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Windows-Portable.zip) | Portable (no install) |
234+
| **macOS** | [CC-Switch-v0.10.1-macOS.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-macOS.zip) | Universal binary (Intel + Apple Silicon) |
235+
| **Linux** | [CC-Switch-v0.10.1-Linux.AppImage](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Linux.AppImage) | AppImage (current stable) |
236+
| | [CC-Switch-v0.10.1-Linux.deb](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Linux.deb) | Debian/Ubuntu package |
237237

238238
**macOS Note**: If you see "damaged" warning, run: `xattr -cr "/Applications/CC Switch.app"`
239239

@@ -257,7 +257,7 @@ This script will:
257257

258258
```bash
259259
# Install current stable version
260-
VERSION=v0.9.2 curl -fsSL https://...install.sh | bash
260+
VERSION=v0.10.1 curl -fsSL https://...install.sh | bash
261261

262262
# Skip checksum verification
263263
NO_CHECKSUM=1 curl -fsSL https://...install.sh | bash
@@ -359,7 +359,7 @@ pnpm test:unit
359359

360360
## Changelog
361361

362-
See [CHANGELOG.md](CHANGELOG.md) — Recommended stable version: **v0.9.2**
362+
See [CHANGELOG.md](CHANGELOG.md) — Recommended stable version: **v0.10.1**
363363

364364
---
365365

README_ZH.md

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515

1616
[English](README.md) | 中文 | [更新日志](CHANGELOG.md)
1717

18-
> 当前推荐稳定版本:[v0.9.2](https://github.com/Laliet/cc-switch-web/releases/tag/v0.9.2)
19-
> `v0.10.0` 当前为预发布版本,仅供测试使用
18+
> 当前推荐稳定版本:[v0.10.1](https://github.com/Laliet/cc-switch-web/releases/tag/v0.10.1)
19+
> `v0.10.1` 当前为正式稳定版本
2020
2121
---
2222

@@ -39,18 +39,18 @@
3939

4040
## 更新内容
4141

42-
### v0.9.2 - 当前稳定版
42+
### v0.10.1 - 当前稳定版
4343

4444
- 适合日常使用与生产环境
45-
- 稳定版下载地址:[v0.9.2](https://github.com/Laliet/cc-switch-web/releases/tag/v0.9.2)
45+
- 稳定版下载地址:[v0.10.1](https://github.com/Laliet/cc-switch-web/releases/tag/v0.10.1)
4646

47-
### v0.10.0 - 当前预发布版
47+
### v0.10.0 - 预发布里程碑
4848

4949
- 新增 OpenCode 供应商管理与自动写入 OpenCode 配置
5050
- 新增 oh-my-opencode(OMO)配置管理与插件联动支持
5151
- 支持在设置页直接修改 Web 模式登录用户名和密码
5252
- 改进 OMO / OpenCode 联动写入与当前供应商编辑时的回滚安全性
53-
- `v0.10.0` 当前仍为预发布版本,还需要更多跨机器验证
53+
- `v0.10.0` 是本发布线在正式稳定前使用的验证预发布版本
5454

5555
### v0.8.0 - 之前的稳定基线
5656

@@ -111,8 +111,8 @@ _配置供应商_
111111

112112
| 架构 | 下载链接 |
113113
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
114-
| **Linux x86_64 (glibc)** | [cc-switch-server-linux-x86_64](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/cc-switch-server-linux-x86_64) |
115-
| **Linux aarch64 (glibc)** | [cc-switch-server-linux-aarch64](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/cc-switch-server-linux-aarch64) |
114+
| **Linux x86_64 (glibc)** | [cc-switch-server-linux-x86_64](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/cc-switch-server-linux-x86_64) |
115+
| **Linux aarch64 (glibc)** | [cc-switch-server-linux-aarch64](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/cc-switch-server-linux-aarch64) |
116116

117117
> **glibc 说明**:预编译二进制基于 Ubuntu 22.04 构建。
118118
> 如果报 `GLIBC_2.xx not found`,请改用 Docker 或源码构建。
@@ -227,11 +227,11 @@ HOST=0.0.0.0 PORT=3000 ./target/release/examples/server
227227

228228
| 平台 | 下载链接 | 说明 |
229229
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
230-
| **Windows** | [CC-Switch-v0.9.2-Windows.msi](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Windows.msi) | 安装版(当前稳定版) |
231-
| | [CC-Switch-v0.9.2-Windows-Portable.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Windows-Portable.zip) | 绿色版(免安装) |
232-
| **macOS** | [CC-Switch-v0.9.2-macOS.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-macOS.zip) | 通用二进制(Intel + Apple Silicon) |
233-
| **Linux** | [CC-Switch-v0.9.2-Linux.AppImage](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Linux.AppImage) | AppImage(当前稳定版) |
234-
| | [CC-Switch-v0.9.2-Linux.deb](https://github.com/Laliet/cc-switch-web/releases/download/v0.9.2/CC-Switch-v0.9.2-Linux.deb) | Debian/Ubuntu 包 |
230+
| **Windows** | [CC-Switch-v0.10.1-Windows.msi](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Windows.msi) | 安装版(当前稳定版) |
231+
| | [CC-Switch-v0.10.1-Windows-Portable.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Windows-Portable.zip) | 绿色版(免安装) |
232+
| **macOS** | [CC-Switch-v0.10.1-macOS.zip](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-macOS.zip) | 通用二进制(Intel + Apple Silicon) |
233+
| **Linux** | [CC-Switch-v0.10.1-Linux.AppImage](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Linux.AppImage) | AppImage(当前稳定版) |
234+
| | [CC-Switch-v0.10.1-Linux.deb](https://github.com/Laliet/cc-switch-web/releases/download/v0.10.1/CC-Switch-v0.10.1-Linux.deb) | Debian/Ubuntu 包 |
235235

236236
**macOS 提示**:如遇"已损坏"警告,在终端执行:`xattr -cr "/Applications/CC Switch.app"`
237237

@@ -255,7 +255,7 @@ curl -fsSL https://raw.githubusercontent.com/Laliet/cc-switch-web/main/scripts/i
255255

256256
```bash
257257
# 安装当前稳定版本
258-
VERSION=v0.9.2 curl -fsSL https://...install.sh | bash
258+
VERSION=v0.10.1 curl -fsSL https://...install.sh | bash
259259

260260
# 跳过校验
261261
NO_CHECKSUM=1 curl -fsSL https://...install.sh | bash
@@ -357,7 +357,7 @@ pnpm test:unit
357357

358358
## 更新日志
359359

360-
参见 [CHANGELOG.md](CHANGELOG.md) — 当前推荐稳定版本:**v0.9.2**
360+
参见 [CHANGELOG.md](CHANGELOG.md) — 当前推荐稳定版本:**v0.10.1**
361361

362362
---
363363

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "cc-switch-web",
3-
"version": "0.10.0",
3+
"version": "0.10.1",
44
"description": "Cross-platform web-based All-in-One assistant tool for Claude Code, Codex & Gemini CLI",
55
"scripts": {
66
"dev": "pnpm tauri dev",

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cc-switch"
3-
version = "0.10.0"
3+
version = "0.10.1"
44
description = "Cross-platform web-based All-in-One assistant tool for Claude Code, Codex & Gemini CLI"
55
authors = ["Jason Young"]
66
license = "MIT"

src-tauri/src/commands/import_export.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub async fn sync_current_providers_live(state: State<'_, AppState>) -> Result<V
6363
ConfigService::sync_current_providers_to_live(&mut config_state)
6464
.map_err(|e| e.to_string())?;
6565
}
66+
state.save().map_err(|e| e.to_string())?;
6667

6768
Ok(json!({
6869
"success": true,

src-tauri/src/services/config.rs

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ impl ConfigService {
430430
}
431431

432432
fn sync_opencode_live(config: &mut MultiAppConfig) -> Result<(), AppError> {
433-
let providers: Vec<(String, Provider)> = config
433+
let mut providers: Vec<(String, Provider)> = config
434434
.get_manager(&AppType::Opencode)
435435
.map(|manager| {
436436
manager
@@ -441,19 +441,34 @@ impl ConfigService {
441441
})
442442
.unwrap_or_default();
443443

444+
providers.sort_by(|(left, _), (right, _)| left.cmp(right));
445+
444446
for (provider_id, provider) in providers {
445-
ProviderService::write_opencode_live(&provider)?;
446-
447-
let live_after = crate::opencode_config::read_opencode_config()?;
448-
let fragment = live_after
449-
.get("provider")
450-
.and_then(|value| value.get(&provider_id))
451-
.cloned()
452-
.unwrap_or_else(|| provider.settings_config.clone());
453-
454-
if let Some(manager) = config.get_manager_mut(&AppType::Opencode) {
455-
if let Some(target) = manager.providers.get_mut(&provider_id) {
456-
target.settings_config = fragment;
447+
let fragment_result = (|| -> Result<Value, AppError> {
448+
ProviderService::write_opencode_live(&provider)?;
449+
450+
let live_after = crate::opencode_config::read_opencode_config()?;
451+
Ok(live_after
452+
.get("provider")
453+
.and_then(|value| value.get(&provider_id))
454+
.cloned()
455+
.unwrap_or_else(|| provider.settings_config.clone()))
456+
})();
457+
458+
match fragment_result {
459+
Ok(fragment) => {
460+
if let Some(manager) = config.get_manager_mut(&AppType::Opencode) {
461+
if let Some(target) = manager.providers.get_mut(&provider_id) {
462+
target.settings_config = fragment;
463+
}
464+
}
465+
}
466+
Err(err) => {
467+
log::warn!(
468+
"Failed to sync OpenCode provider '{}' to live config: {}",
469+
provider_id,
470+
err
471+
);
457472
}
458473
}
459474
}

src-tauri/src/services/provider.rs

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,15 +2055,32 @@ impl ProviderService {
20552055
)
20562056
})?;
20572057

2058-
let fragment = if settings.contains_key("$schema") || settings.contains_key("provider") {
2059-
settings
2060-
.get("provider")
2061-
.and_then(|value| value.get(&provider.id))
2062-
.cloned()
2063-
.unwrap_or_else(|| provider.settings_config.clone())
2064-
} else {
2065-
provider.settings_config.clone()
2066-
};
2058+
let fragment =
2059+
if let Some(providers) = settings.get("provider").and_then(|value| value.as_object()) {
2060+
providers.get(&provider.id).cloned().ok_or_else(|| {
2061+
AppError::localized(
2062+
"provider.opencode.fragment.missing",
2063+
format!("OpenCode 配置缺少 provider.{}", provider.id),
2064+
format!("OpenCode configuration is missing provider.{}", provider.id),
2065+
)
2066+
})?
2067+
} else if settings.contains_key("$schema") {
2068+
return Err(AppError::localized(
2069+
"provider.opencode.fragment.missing",
2070+
format!("OpenCode 配置缺少 provider.{}", provider.id),
2071+
format!("OpenCode configuration is missing provider.{}", provider.id),
2072+
));
2073+
} else {
2074+
provider.settings_config.clone()
2075+
};
2076+
2077+
if !fragment.is_object() {
2078+
return Err(AppError::localized(
2079+
"provider.opencode.fragment.not_object",
2080+
format!("OpenCode provider.{} 必须是 JSON 对象", provider.id),
2081+
format!("OpenCode provider.{} must be a JSON object", provider.id),
2082+
));
2083+
}
20672084

20682085
crate::opencode_config::set_provider(&provider.id, fragment)?;
20692086
Ok(())

src-tauri/src/web_api/handlers/providers.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use serde::Deserialize;
1010

1111
use super::{parse_known_app_type, ApiError, ApiResult};
1212
use crate::{
13-
app_config::AppType,
1413
error::AppError,
1514
provider::{Provider, UsageResult},
1615
services::provider::ProviderSortUpdate,

src-tauri/src/web_api/mod.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![cfg(feature = "web-server")]
2-
31
use std::{
42
env, fs,
53
net::{IpAddr, Ipv4Addr, Ipv6Addr},
@@ -564,9 +562,8 @@ pub fn create_router_with_auth_state(state: SharedState, auth_state: SharedWebAu
564562
let mut root = Router::new()
565563
.nest(api_prefix.as_str(), router)
566564
.merge(static_router)
567-
.layer(middleware::from_fn({
568-
let hsts_enabled = hsts_enabled;
569-
move |req, next| add_hsts_header(hsts_enabled, req, next)
565+
.layer(middleware::from_fn(move |req, next| {
566+
add_hsts_header(hsts_enabled, req, next)
570567
}));
571568

572569
if global_concurrency > 0 {

0 commit comments

Comments
 (0)