fix(tamagotchi): exit child process when tauri exit (#172)
This commit is contained in:
@@ -18,3 +18,20 @@ pub async fn open_settings_window(app: tauri::AppHandle) {
|
||||
.build()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn open_chat_window(app: tauri::AppHandle) {
|
||||
if let Some(window) = app.get_webview_window("chat") {
|
||||
let _ = window.show();
|
||||
return;
|
||||
}
|
||||
|
||||
let _ = WebviewWindowBuilder::new(
|
||||
&app,
|
||||
"chat",
|
||||
WebviewUrl::App(Path::new("#/chat").to_path_buf()),
|
||||
)
|
||||
.title("chat")
|
||||
.build()
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use std::path::Path;
|
||||
use tauri::menu::{Menu, MenuItem};
|
||||
use tauri::tray::TrayIconBuilder;
|
||||
use tauri::RunEvent;
|
||||
#[cfg(target_os = "macos")]
|
||||
use tauri::{ActivationPolicy, TitleBarStyle};
|
||||
use tauri::{Manager, WebviewUrl, WebviewWindowBuilder};
|
||||
@@ -57,6 +58,7 @@ pub fn run() {
|
||||
.menu(&menu)
|
||||
.on_menu_event(|app, event| match event.id().as_ref() {
|
||||
"quit" => {
|
||||
app.cleanup_before_exit();
|
||||
app.exit(0);
|
||||
}
|
||||
"settings" => {
|
||||
@@ -90,10 +92,20 @@ pub fn run() {
|
||||
.show_menu_on_left_click(true)
|
||||
.build(app)
|
||||
.unwrap();
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![commands::open_settings_window])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::open_settings_window,
|
||||
commands::open_chat_window
|
||||
])
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while building tauri application")
|
||||
.run(|app_handle, event| match event {
|
||||
RunEvent::ExitRequested { .. } => {
|
||||
println!("Exiting app");
|
||||
tauri_plugin_mcp::destroy(app_handle);
|
||||
println!("Exited app");
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,4 +60,9 @@ export default defineConfig({
|
||||
Download('https://dist.ayaka.moe/live2d-models/hiyori_free_zh.zip', 'hiyori_free_zh.zip', 'assets/live2d/models'),
|
||||
Download('https://dist.ayaka.moe/live2d-models/hiyori_pro_zh.zip', 'hiyori_pro_zh.zip', 'assets/live2d/models'),
|
||||
],
|
||||
server: {
|
||||
watch: {
|
||||
ignored: ['**/src-tauri/**'],
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
use std::process::Stdio;
|
||||
|
||||
use rmcp::model::CallToolRequestParam;
|
||||
use rmcp::{
|
||||
model::{CallToolResult, Tool},
|
||||
@@ -6,11 +8,11 @@ use rmcp::{
|
||||
RoleClient, ServiceExt,
|
||||
};
|
||||
use serde_json::{Map, Value};
|
||||
use tauri::State;
|
||||
use tauri::{
|
||||
plugin::{self, TauriPlugin},
|
||||
Manager, Runtime,
|
||||
};
|
||||
use tauri::{AppHandle, State};
|
||||
use tokio::process::Command;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
@@ -18,6 +20,24 @@ pub struct McpState {
|
||||
pub client: Option<RunningService<RoleClient, ()>>,
|
||||
}
|
||||
|
||||
pub fn destroy<R: Runtime>(app_handle: &AppHandle<R>) {
|
||||
println!("Destroying MCP plugin");
|
||||
tokio::runtime::Runtime::new().unwrap().block_on(async {
|
||||
let state = app_handle.state::<Mutex<McpState>>();
|
||||
let mut state = state.lock().await;
|
||||
if state.client.is_none() {
|
||||
println!("MCP plugin not connected, no need to disconnect");
|
||||
return;
|
||||
}
|
||||
|
||||
let client = state.client.take().unwrap();
|
||||
client.cancel().await.unwrap();
|
||||
// client.waiting().await.unwrap();
|
||||
state.client = None;
|
||||
});
|
||||
println!("MCP plugin destroyed");
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn connect_server(
|
||||
state: State<'_, Mutex<McpState>>,
|
||||
@@ -30,7 +50,13 @@ async fn connect_server(
|
||||
return Err("Client already connected".to_string());
|
||||
}
|
||||
|
||||
let child_process = TokioChildProcess::new(Command::new(command).args(args)).unwrap();
|
||||
let child_process = TokioChildProcess::new(
|
||||
Command::new(command)
|
||||
.args(args)
|
||||
.stderr(Stdio::inherit())
|
||||
.stdout(Stdio::inherit()),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let service: RunningService<RoleClient, ()> = ().serve(child_process).await.unwrap();
|
||||
|
||||
@@ -46,9 +72,13 @@ async fn disconnect_server(state: State<'_, Mutex<McpState>>) -> Result<(), Stri
|
||||
return Err("Client not connected".to_string());
|
||||
}
|
||||
|
||||
state.client.take().unwrap().cancel().await.unwrap();
|
||||
let cancel_result = state.client.take().unwrap().cancel().await;
|
||||
println!("Cancel result: {:?}", cancel_result);
|
||||
// state.client.take().unwrap().waiting().await.unwrap();
|
||||
state.client = None;
|
||||
|
||||
println!("Disconnected from MCP server");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -64,7 +94,7 @@ async fn list_tools(state: State<'_, Mutex<McpState>>) -> Result<Vec<Tool>, Stri
|
||||
.unwrap()
|
||||
.list_tools(Default::default())
|
||||
.await
|
||||
.unwrap();
|
||||
.unwrap(); // TODO: handle error
|
||||
let tools = list_tools_result.tools;
|
||||
|
||||
Ok(tools)
|
||||
@@ -117,6 +147,9 @@ impl Builder {
|
||||
app_handle.manage(Mutex::new(McpState { client: None }));
|
||||
Ok(())
|
||||
})
|
||||
.on_drop(|app_handle: AppHandle<R>| {
|
||||
destroy(&app_handle);
|
||||
})
|
||||
.build()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user