Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
cfd5ce6
chore: exclude local opencode reference dir from git, eslint and vitest
rayn1314 Aug 28, 2026
1642cae
feat(wsl): backend server management commands for Windows desktop
rayn1314 Aug 30, 2026
d32b641
feat(wsl): frontend server sync, settings UI and connections integration
rayn1314 Aug 30, 2026
b5a2166
fix(wsl): sidebar group and SSE follow WSL server registered after boot
rayn1314 Aug 30, 2026
68afa5b
perf(wsl): 按需预热——启动零探测、设置页意图驱动、在线目录 TTL 缓存
rayn1314 Sep 1, 2026
59885c1
perf(sessions): 修复启动级联——未注册服务器过滤、upsert 短路、订阅集合增量管理
rayn1314 Sep 1, 2026
3e7110e
fix(sidebar): 会话列表加载态与错误态——重试间隙不再闪现空态文案
rayn1314 Sep 1, 2026
0659e11
fix(wsl): 评审修正——在线目录 revalidate 去重、prewarm 跳过就绪服务器、测试门控简化
rayn1314 Sep 1, 2026
e0601b7
fix(sessions): 评审修正——过滤后兜底 active server、enabled 关闭中断重试、去除空 catch
rayn1314 Sep 1, 2026
7096f48
fix(config): 评审修正——清理 PR 内本地配置与行尾噪音
rayn1314 Sep 15, 2026
d8a946e
fix(events): 评审修正——非活动服务器端点变化不再迁移 SSE 订阅
rayn1314 Sep 15, 2026
24ef877
fix(store): 评审修正——删除服务器时回收默认指针与 WSL 绑定
rayn1314 Sep 15, 2026
4b9ed33
fix(tauri): 评审修正——轮询单调时钟、sidecar 句柄归属与安装容错
rayn1314 Sep 15, 2026
3ea9192
fix(events): 评审修正——服务器变化事件按 reason 门控消费
rayn1314 Sep 15, 2026
31f95a6
fix(ui): 评审修正——WSL 界面语义色、图标一致性与可达性
rayn1314 Sep 15, 2026
3221502
fix(store): 评审修正——sidecar 复活不再劫持用户主动切换
rayn1314 Sep 15, 2026
92eb319
fix(ui): 评审修正——生命周期圆点与 Wi-Fi 探测图标分离
rayn1314 Sep 15, 2026
b168c40
fix(tauri): 评审修正——应用退出兜底回收 WSL sidecar
rayn1314 Sep 15, 2026
8b870dc
fix(store): 评审 N1——实时事件落地后丢弃迟到的陈旧初始快照
rayn1314 Sep 16, 2026
526db88
refactor(store): 评审 N3——门控抽成共享纯函数谓词,8 个消费点统一语义
rayn1314 Sep 16, 2026
23cf65a
fix(ui): 评审 N2——BottomPanel 终端恢复门控改比对自身绑定服务器
rayn1314 Sep 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"clsx": "^2.1.1",
"diff": "^8.0.4",
"dompurify": "^3.4.11",
"fuzzysort": "^4.0.2",
"i18next": "^26.0.1",
"i18next-browser-languagedetector": "^8.2.1",
"katex": "^0.16.38",
Expand Down
4 changes: 4 additions & 0 deletions src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ futures-util = "0.3"
log = "0.4"
papaya = "0.2.3"
rapidhash = { version = "4.4.1", features = ["unsafe"] }
regex = "1"
reqwest = { version = "0.12", default-features = false, features = [
"rustls-tls",
"stream"
Expand All @@ -32,8 +33,10 @@ tauri-plugin-log = "2"
tauri-plugin-notification = "2"
tauri-plugin-opener = "2"
tauri-plugin-single-instance = "2"
tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "sync", "time", "process"] }
tokio-tungstenite = { version = "0.24", features = ["rustls-tls-webpki-roots"] }
tokio-util = "0.7"
uuid = { version = "1", features = ["v4"] }

[build-dependencies]
tauri-build = { version = "2", features = [] }
Expand Down
6 changes: 6 additions & 0 deletions src-tauri/src/app/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ pub mod bridge;
pub mod opencode;
#[cfg(not(target_os = "android"))]
pub mod utils;
#[cfg(target_os = "windows")]
pub mod wsl_types;
#[cfg(target_os = "windows")]
pub mod wsl_runtime;
#[cfg(target_os = "windows")]
pub mod wsl_commands;
54 changes: 44 additions & 10 deletions src-tauri/src/app/commands/opencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,46 @@ struct SpawnedOpencodeServe {

/// 检查 opencode 服务是否在运行(通过 health endpoint)
pub async fn is_service_running(url: &str) -> bool {
let health_url = format!("{}/global/health", url.trim_end_matches('/'));
match reqwest::Client::builder()
is_service_running_with_auth(url, None).await
}

/// 带可选 Basic 鉴权的健康检查,对齐官方实现:
/// 依次尝试 /api/health 与 /global/health;WSL 侧 serve 启用了密码保护,
/// 不带凭据会收到 401 而误判为未就绪。
pub async fn is_service_running_with_auth(url: &str, auth: Option<(&str, &str)>) -> bool {
let base = url.trim_end_matches('/');
let client = match reqwest::Client::builder()
.connect_timeout(Duration::from_secs(3))
.build()
{
Ok(client) => client
.get(&health_url)
.timeout(Duration::from_secs(5))
.send()
.await
.map(|r| r.status().is_success())
.unwrap_or(false),
Err(_) => false,
Ok(c) => c,
Err(_) => return false,
};

let mut request = client.get(format!("{}/api/health", base));
if let Some((username, password)) = auth {
request = request.basic_auth(username, Some(password));
}
if request
.timeout(Duration::from_secs(5))
.send()
.await
.map(|r| r.status().is_success())
.unwrap_or(false)
{
return true;
}

let mut request = client.get(format!("{}/global/health", base));
if let Some((username, password)) = auth {
request = request.basic_auth(username, Some(password));
}
request
.timeout(Duration::from_secs(5))
.send()
.await
.map(|r| r.status().is_success())
.unwrap_or(false)
}

/// 启动 opencode serve 进程
Expand Down Expand Up @@ -371,6 +397,14 @@ pub async fn confirm_close_app(
state: State<'_, ServiceState>,
stop_service: bool,
) -> Result<(), String> {
// 我们启动的 WSL 内 opencode 进程随应用退出统一清理,避免后台残留
#[cfg(target_os = "windows")]
{
use tauri::Manager;
let wsl_state = window.app_handle().state::<super::wsl_commands::WslState>();
super::wsl_commands::stop_all_wsl_servers(&wsl_state).await;
}

if stop_service {
let pid = state.child_pid.swap(0, Ordering::SeqCst);
if pid > 0 {
Expand Down
Loading
Loading