mod commands; mod db; mod mcp_inject; mod mcp_server; mod models; use git2; /// 创建不弹 CMD 窗口的子进程(Windows 专用 CREATE_NO_WINDOW 标志)。 /// 所有后台静默命令都应通过此函数创建,避免在 Windows 上频繁闪出黑框。 pub(crate) fn silent_cmd(program: &str) -> std::process::Command { let mut cmd = std::process::Command::new(program); #[cfg(target_os = "windows")] { use std::os::windows::process::CommandExt; const CREATE_NO_WINDOW: u32 = 0x0800_0000; cmd.creation_flags(CREATE_NO_WINDOW); } cmd } use commands::{activity::*, blueprint::*, buff::{apply_blueprint_buff, remove_blueprint_buff, get_buff_status, list_buffed_projects}, canvas::*, cicd::*, devtools::*, git_ops::*, git_repos::*, github::*, groups::*, mentor::{add_project_note, get_group_mentor_report, get_mentor_context, get_project_notes, get_startup_alerts, run_startup_health_scan}, network::{get_wsl_ip, sync_wsl_proxy, get_wsl_proxy_status, clear_wsl_proxy, test_wsl_proxy_ip, test_win_proxy_ip}, project_scan::*, project_tools::*, projects::{batch_create_projects, create_project, delete_project, get_project, get_projects, scan_subfolders, update_project, update_project_tags}, proxy::*, publish::*, settings::{check_mcp_health, detect_editors, get_settings, run_health_check, search_editor_path, update_settings}, shell::*, spaces::*, tags::*, templates::*}; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| { // 第二个实例启动时,激活已有窗口 use tauri::Manager; if let Some(w) = app.get_webview_window("main") { let _ = w.show(); let _ = w.unminimize(); let _ = w.set_focus(); } })) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_shell::init()) .setup(|app| { use tauri::{ menu::{Menu, MenuItem}, tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}, Manager, }; let data_dir = app.path().app_data_dir().expect("no app data dir"); db::init(data_dir.clone()); commands::blueprint::init_user_conventions_dir(data_dir); // 禁用 libgit2 目录所有者验证,允许访问 WSL UNC 路径(\\wsl.localhost\...) unsafe { let _ = git2::opts::set_verify_owner_validation(false); } // 种植内置模板(首次启动时执行) commands::templates::seed_builtin_templates(); // ── 启动 MCP Server ─────────────────────────────────────── let mcp_port = mcp_server::read_port(); tauri::async_runtime::spawn(mcp_server::start(mcp_port)); // ── 启动健康扫描(异步,不阻塞窗口渲染)──────────────── tauri::async_runtime::spawn(async { tokio::task::spawn_blocking(run_startup_health_scan).await.ok(); }); // ── 启动蓝图 Buff 后台轮询 ──────────────────────────── commands::buff::start_blueprint_watchers(app.handle().clone()); // ── 系统托盘 ────────────────────────────────────────────── let show_i = MenuItem::with_id(app, "show", "显示窗口", true, None::<&str>)?; let quit_i = MenuItem::with_id(app, "quit", "退出炼境", true, None::<&str>)?; let menu = Menu::with_items(app, &[&show_i, &quit_i])?; TrayIconBuilder::new() .icon(app.default_window_icon().unwrap().clone()) .menu(&menu) .show_menu_on_left_click(false) .tooltip("炼境") .on_menu_event(|app, event| match event.id.as_ref() { "quit" => app.exit(0), "show" => { if let Some(w) = app.get_webview_window("main") { let _ = w.show(); let _ = w.set_focus(); } } _ => {} }) .on_tray_icon_event(|tray, event| { // 左键单击托盘图标 → 显示/聚焦窗口 if let TrayIconEvent::Click { button: MouseButton::Left, button_state: MouseButtonState::Up, .. } = event { let app = tray.app_handle(); if let Some(w) = app.get_webview_window("main") { let _ = w.show(); let _ = w.set_focus(); } } }) .build(app)?; // ── 关闭窗口 → 最小化到托盘 ────────────────────────────── if let Some(window) = app.get_webview_window("main") { let win = window.clone(); window.on_window_event(move |event| { if let tauri::WindowEvent::CloseRequested { api, .. } = event { api.prevent_close(); let _ = win.hide(); } }); } Ok(()) }) .invoke_handler(tauri::generate_handler![ // projects get_projects, get_project, create_project, update_project, update_project_tags, delete_project, scan_subfolders, batch_create_projects, // activity get_activity, add_activity, // groups get_groups, create_group, update_group, delete_group, reorder_groups, get_group_maps, add_group_member, remove_group_member, // settings get_settings, update_settings, detect_editors, search_editor_path, check_mcp_health, run_health_check, // project tools get_project_tools, add_project_tool, update_project_tool, remove_project_tool, launch_tool, // global quick launch get_global_tools, add_global_tool, update_global_tool, remove_global_tool, // devtools scan_dev_tools, scan_wsl_dev_tools, get_dev_tools, save_dev_tools, delete_dev_tool, upsert_dev_tool, // wsl proxy get_wsl_ip, sync_wsl_proxy, get_wsl_proxy_status, clear_wsl_proxy, test_wsl_proxy_ip, test_win_proxy_ip, // v2rayn import scan_v2rayn_nodes, detect_v2rayn_db_path, get_active_v2rayn_node, // project env scan scan_project_env, get_project_env_tools, save_project_env_tools, // shell open_editor, open_terminal, // git ops git_clone, git_status, git_fetch, git_pull, git_push, git_head_commit, git_upstream_behind, git_create_branch, git_list_branches, git_checkout_branch, // github github_save_account, github_get_account, github_get_token, github_get_client_id, github_logout, github_start_oauth, github_poll_oauth, github_open_login_window, // spaces get_spaces, create_space, update_space, delete_space, set_current_space, get_deploy_commands, add_deploy_command, remove_deploy_command, execute_deploy, // git repos registry get_git_repos, import_git_repos, update_git_repo_deploy, mount_repo, delete_git_repo, // publish to github scan_local_git, github_create_repo, git_init_and_commit, git_remote_set, git_push_to_github, register_and_link_repo, write_gitignore, resolve_wsl_path, get_wsl_distros, // project templates list_templates, get_template, save_template, delete_template, create_project_from_template, // tags get_tags, create_tag, update_tag, delete_tag, get_project_tags, set_project_tags, get_all_project_tag_maps, // cicd get_cicd_config, save_cicd_config, generate_workflow, // blueprint get_blueprint, generate_blueprint_prompt, get_blueprint_status, sync_blueprint_rules, get_flywheel_stats, generate_muhe_prompt, archive_project_docs, get_user_conventions_status, save_user_conventions, reset_conventions_to_builtin, // canvas state get_canvas_state, save_canvas_state, // blueprint buff apply_blueprint_buff, remove_blueprint_buff, get_buff_status, list_buffed_projects, // mentor get_mentor_context, get_project_notes, add_project_note, get_group_mentor_report, get_startup_alerts, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }