From f017b87abd8adfd19221aeb1229b5aef29a24c90 Mon Sep 17 00:00:00 2001 From: Thorsten Sommer Date: Wed, 10 Jun 2026 21:31:02 +0200 Subject: [PATCH] Fixed an issue where AI Studio could be started multiple times (#803) --- AGENTS.md | 6 ++-- .../wwwroot/changelog/v26.6.1.md | 1 + runtime/Cargo.lock | 34 ++++++++++++++----- runtime/Cargo.toml | 1 + runtime/src/app_window.rs | 20 +++++++++++ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 48a25021..7217a83c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -7,7 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co MindWork AI Studio is a cross-platform desktop application for interacting with Large Language Models (LLMs). The app uses a hybrid architecture combining a Rust Tauri runtime (for the native desktop shell) with a .NET Blazor Server web application (for the UI and business logic). **Key Architecture Points:** -- **Runtime:** Rust-based Tauri v1.8 application providing the native window, system integration, and IPC layer +- **Runtime:** Rust-based Tauri v2 application providing the native window, system integration, and IPC layer - **App:** .NET 9 Blazor Server application providing the UI and core functionality - **Communication:** The Rust runtime and .NET app communicate via HTTPS with TLS certificates generated at startup - **Providers:** Multi-provider architecture supporting OpenAI, Anthropic, Google, Mistral, Perplexity, self-hosted models, and others @@ -18,7 +18,7 @@ MindWork AI Studio is a cross-platform desktop application for interacting with ### Prerequisites - .NET 9 SDK - Rust toolchain (stable) -- Tauri v1.6.2 CLI: `cargo install --version 1.6.2 tauri-cli` +- Tauri v2 CLI - Tauri prerequisites (platform-specific dependencies) - **Note:** Development on Linux is discouraged due to complex Tauri dependencies that vary by distribution @@ -151,7 +151,7 @@ Multi-level confidence scheme allows users to control which providers see which ## Dependencies and Frameworks **Rust:** -- Tauri 1.8 - Desktop application framework +- Tauri 2 - Desktop application framework - Axum - HTTPS API server - tokio - Async runtime - keyring - OS keyring integration diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.6.1.md b/app/MindWork AI Studio/wwwroot/changelog/v26.6.1.md index 6bbb8f6b..89155f28 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.6.1.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.6.1.md @@ -14,4 +14,5 @@ - Fixed an issue where renamed chat templates and profiles continued to show their old names in the chat toolbar until the app was restarted. - Fixed workspace creation and renaming to prevent new workspaces from using an existing name. - Fixed an issue on Microsoft Windows where reading attached documents could briefly open a terminal window while processing files. +- Fixed an issue where AI Studio could be started multiple times on Microsoft Windows by launching it from different virtual desktops. - Upgraded dependencies. \ No newline at end of file diff --git a/runtime/Cargo.lock b/runtime/Cargo.lock index ffc6b325..673fed58 100644 --- a/runtime/Cargo.lock +++ b/runtime/Cargo.lock @@ -214,7 +214,7 @@ dependencies = [ "objc2-foundation 0.3.2", "parking_lot", "percent-encoding", - "windows-sys 0.59.0", + "windows-sys 0.60.2", "x11rb", ] @@ -1769,7 +1769,7 @@ dependencies = [ "libc", "option-ext", "redox_users", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -2066,7 +2066,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -3828,7 +3828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -4041,6 +4041,7 @@ dependencies = [ "tauri-plugin-global-shortcut", "tauri-plugin-opener", "tauri-plugin-shell", + "tauri-plugin-single-instance", "tauri-plugin-updater", "tauri-plugin-window-state", "tempfile", @@ -4350,7 +4351,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.117", @@ -5393,7 +5394,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -5813,7 +5814,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -5872,7 +5873,7 @@ dependencies = [ "security-framework", "security-framework-sys", "webpki-root-certs", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7005,6 +7006,21 @@ dependencies = [ "tokio", ] +[[package]] +name = "tauri-plugin-single-instance" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8f29386f5e9fdc699182388a33ee80a56de436d91b67459e86afef426282af" +dependencies = [ + "serde", + "serde_json", + "tauri", + "thiserror 2.0.18", + "tracing", + "windows-sys 0.60.2", + "zbus", +] + [[package]] name = "tauri-plugin-updater" version = "2.10.1" @@ -7163,7 +7179,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix 1.1.4", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 01f582c6..960b2a98 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -14,6 +14,7 @@ tauri-plugin-window-state = { version = "2.4.1" } tauri-plugin-shell = "2.3.5" tauri-plugin-dialog = "2.7.1" tauri-plugin-opener = "2.5.4" +tauri-plugin-single-instance = "2" serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.150" keyring-core = "1.0.0" diff --git a/runtime/src/app_window.rs b/runtime/src/app_window.rs index f2d9c304..d1e31add 100644 --- a/runtime/src/app_window.rs +++ b/runtime/src/app_window.rs @@ -85,6 +85,26 @@ pub fn start_tauri() { }); let app = tauri::Builder::default() + .plugin(tauri_plugin_single_instance::init(|app, args, cwd| { + info!(Source = "Tauri"; "Prevented second app instance from starting. cwd='{cwd}', args={args:?}"); + + let Some(window) = app.get_webview_window("main") else { + warn!(Source = "Tauri"; "Second app instance was blocked, but the main window was not available for activation."); + return; + }; + + if let Err(error) = window.show() { + warn!(Source = "Tauri"; "Failed to show main window after second app start: {error}"); + } + + if let Err(error) = window.unminimize() { + warn!(Source = "Tauri"; "Failed to unminimize main window after second app start: {error}"); + } + + if let Err(error) = window.set_focus() { + warn!(Source = "Tauri"; "Failed to focus main window after second app start: {error}"); + } + })) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_shell::init()) .plugin(tauri_plugin_opener::init())