fix: update dependencies and enhance process management in the desktop application

This commit is contained in:
Bohdan Triapitsyn
2025-12-07 21:26:54 +02:00
parent b5e6837939
commit 310bc75613
6 changed files with 59 additions and 39 deletions
+12 -1
View File
@@ -2847,7 +2847,7 @@ dependencies = [
[[package]] [[package]]
name = "openchamber-desktop" name = "openchamber-desktop"
version = "1.0.2" version = "1.0.3"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"axum", "axum",
@@ -2875,6 +2875,7 @@ dependencies = [
"tauri-plugin-fs", "tauri-plugin-fs",
"tauri-plugin-log", "tauri-plugin-log",
"tauri-plugin-notification", "tauri-plugin-notification",
"tauri-plugin-process",
"tauri-plugin-shell", "tauri-plugin-shell",
"tauri-plugin-updater", "tauri-plugin-updater",
"tokio", "tokio",
@@ -4721,6 +4722,16 @@ dependencies = [
"url", "url",
] ]
[[package]]
name = "tauri-plugin-process"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d55511a7bf6cd70c8767b02c97bf8134fa434daf3926cfc1be0a0f94132d165a"
dependencies = [
"tauri",
"tauri-plugin",
]
[[package]] [[package]]
name = "tauri-plugin-shell" name = "tauri-plugin-shell"
version = "2.3.3" version = "2.3.3"
+1
View File
@@ -44,6 +44,7 @@ uuid = { version = "1.18.1", features = ["v4"] }
tokio-util = { version = "0.7", features = ["io"] } tokio-util = { version = "0.7", features = ["io"] }
tauri-plugin-notification = "2.3.3" tauri-plugin-notification = "2.3.3"
tauri-plugin-updater = "2" tauri-plugin-updater = "2"
tauri-plugin-process = "2"
[build-dependencies] [build-dependencies]
tauri-build = { version = "2.5.3", features = [] } tauri-build = { version = "2.5.3", features = [] }
@@ -38,6 +38,6 @@
"updater:default", "updater:default",
"updater:allow-check", "updater:allow-check",
"updater:allow-download-and-install", "updater:allow-download-and-install",
"process:allow-relaunch" "process:allow-restart"
] ]
} }
+35 -36
View File
@@ -79,23 +79,11 @@ pub(crate) struct DesktopRuntime {
} }
impl DesktopRuntime { impl DesktopRuntime {
async fn initialize() -> Result<Self> { fn initialize_sync() -> Result<Self> {
let settings = Arc::new(SettingsStore::new()?); let settings = Arc::new(SettingsStore::new()?);
let initial_dir = tauri::async_runtime::block_on(settings.last_directory()).ok().flatten();
// Read lastDirectory from settings before starting OpenCode
let initial_dir = settings.last_directory().await.ok().flatten();
let opencode = Arc::new(OpenCodeManager::new_with_directory(initial_dir.clone())); let opencode = Arc::new(OpenCodeManager::new_with_directory(initial_dir.clone()));
// Try to start OpenCode if CLI is available
if opencode.is_cli_available() {
if let Err(e) = opencode.ensure_running().await {
warn!("[desktop] Failed to start OpenCode: {}", e);
}
} else {
info!("[desktop] OpenCode CLI not available - running in limited mode");
}
let client = Client::builder().build()?; let client = Client::builder().build()?;
let (shutdown_tx, shutdown_rx) = broadcast::channel(2); let (shutdown_tx, shutdown_rx) = broadcast::channel(2);
@@ -119,6 +107,16 @@ impl DesktopRuntime {
}) })
} }
async fn start_opencode(&self) {
if self.opencode.is_cli_available() {
if let Err(e) = self.opencode.ensure_running().await {
warn!("[desktop] Failed to start OpenCode: {}", e);
}
} else {
info!("[desktop] OpenCode CLI not available - running in limited mode");
}
}
async fn shutdown(&self) { async fn shutdown(&self) {
let _ = self.shutdown_tx.send(()); let _ = self.shutdown_tx.send(());
let _ = self.opencode.shutdown().await; let _ = self.opencode.shutdown().await;
@@ -257,18 +255,17 @@ fn main() {
.plugin(fs_plugin()) .plugin(fs_plugin())
.plugin(notification_plugin()) .plugin(notification_plugin())
.plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_updater::Builder::new().build())
.plugin(tauri_plugin_process::init())
.plugin(log_builder.build()) .plugin(log_builder.build())
.setup(|app| { .setup(|app| {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
prevent_app_nap(); prevent_app_nap();
let runtime = tauri::async_runtime::block_on(DesktopRuntime::initialize())?; app.manage(TerminalState::new());
app.manage(runtime.clone());
// Background assistant completion notifications (SSE) independent of the webview lifecycle let stored_state = tauri::async_runtime::block_on(load_window_state()).unwrap_or(None);
let app_handle = app.app_handle(); let manager = WindowStateManager::new(stored_state.clone().unwrap_or_default());
spawn_assistant_notifications(app_handle.clone(), runtime.clone()); app.manage(manager.clone());
spawn_session_activity_tracker(app_handle.clone(), runtime.clone());
if let Some(window) = app.get_webview_window("main") { if let Some(window) = app.get_webview_window("main") {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
@@ -281,30 +278,32 @@ fn main() {
info!("[desktop:vibrancy] Applied macOS Sidebar vibrancy to main window"); info!("[desktop:vibrancy] Applied macOS Sidebar vibrancy to main window");
} }
} }
}
app.manage(TerminalState::new());
let stored_state = tauri::async_runtime::block_on(load_window_state()).unwrap_or(None); if let Some(saved) = &stored_state {
let manager = WindowStateManager::new(stored_state.clone().unwrap_or_default()); let _ = window_state::apply_window_state(&window, saved);
app.manage(manager.clone());
if let Some(saved) = stored_state {
if let Some(window) = app.get_webview_window("main") {
let _ = window_state::apply_window_state(&window, &saved);
} }
let _ = window.show();
} }
// Restore bookmarks on startup (macOS security-scoped access) let runtime = DesktopRuntime::initialize_sync()?;
// We'll do this synchronously within the setup to avoid lifetime issues app.manage(runtime.clone());
tauri::async_runtime::block_on(async {
if let Err(e) = let app_handle = app.app_handle().clone();
restore_bookmarks_on_startup(app.state::<DesktopRuntime>().clone()).await let runtime_clone = runtime.clone();
{ tauri::async_runtime::spawn(async move {
runtime_clone.start_opencode().await;
if let Err(e) = restore_bookmarks_on_startup(app_handle.state::<DesktopRuntime>().clone()).await {
warn!("Failed to restore bookmarks on startup: {}", e); warn!("Failed to restore bookmarks on startup: {}", e);
} }
let _ = app_handle.emit("openchamber:runtime-ready", ());
}); });
spawn_assistant_notifications(app.app_handle().clone(), runtime.clone());
spawn_session_activity_tracker(app.app_handle().clone(), runtime.clone());
Ok(()) Ok(())
}) })
.invoke_handler(tauri::generate_handler![ .invoke_handler(tauri::generate_handler![
+1 -1
View File
@@ -26,7 +26,7 @@
"x": 17, "x": 17,
"y": 26 "y": 26
}, },
"visible": true, "visible": false,
"backgroundThrottling": "disabled" "backgroundThrottling": "disabled"
} }
], ],
+9
View File
@@ -237,6 +237,15 @@ if (typeof window !== 'undefined') {
}); });
} }
const runtimeReady = new Promise<void>((resolve) => {
listen('openchamber:runtime-ready', () => {
console.info('[main] Runtime ready event received');
resolve();
});
});
await runtimeReady;
try { try {
await import('@openchamber/ui/main'); await import('@openchamber/ui/main');
} catch (error) { } catch (error) {