dev-manager-tauri/src-tauri/src/lib.rs
lanrtop 8a64b29445 feat(gitea): G6 远端轮询采集——公网 Gitea + 内网炼境拓扑的观测面方案
- poll_all_repos:后台线程每 10 分钟出站拉取所有绑定仓库最新 commit
  (GET /repos/:owner/:repo/commits),record_commit 幂等写入,与本地
  watcher / 全量导入三路径共存不重复计数
- gitea_poll_now 命令 + GiteaPanel「立即拉取」按钮与拓扑说明
- 决策记录:webhook 仅作同网补充,否决 frp 全端口映射(MCP 路由无鉴权,
  27190 保持零公网暴露);飞轮为统计系统,10 分钟延迟无影响

验证:cargo test 67 passed(新增轮询解析 2 测试)、typecheck 全绿

Rules-Applied: R01, R07
2026-07-02 16:36:18 +09:00

390 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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::*, claude_config::get_beast_global_status, devtools::*, git_ops::*, git_repos::*, 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));
// ── Gitea 远端轮询G6每 10 分钟拉取绑定仓库 commit ───
// 出站 HTTPS 采集,适配公网 Gitea + 内网炼境拓扑webhook 不可达时的降级)
std::thread::spawn(|| {
std::thread::sleep(std::time::Duration::from_secs(30)); // 等 DB 与网络就绪
loop {
let _ = commands::gitea::poll_all_repos();
std::thread::sleep(std::time::Duration::from_secs(600));
}
});
// ── 启动健康扫描(异步,不阻塞窗口渲染)────────────────
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,
// 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,
// 本地 git 工具
scan_local_git,
git_init_and_commit,
git_remote_set,
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,
// onboarding pack
commands::onboarding::apply_onboarding_pack,
// agent infrastructure
commands::agent_infra::scan_agent_infra_stack,
commands::agent_infra::generate_agent_infra_files,
commands::agent_infra::scan_doc_freshness,
commands::agent_infra::get_doc_freshness_cache,
commands::agent_infra::get_agent_health,
commands::commit_metrics::get_commit_stats,
commands::commit_metrics::ingest_full_git_history,
commands::commit_metrics::get_project_commit_health,
commands::commit_metrics::get_all_commit_health,
// mentor
get_mentor_context,
get_project_notes,
add_project_note,
get_group_mentor_report,
get_startup_alerts,
// user todos
commands::user_todos::get_user_todos,
commands::user_todos::add_user_todo,
commands::user_todos::toggle_user_todo,
commands::user_todos::delete_user_todo,
// servers
commands::servers::get_servers,
commands::servers::add_server,
commands::servers::edit_server,
commands::servers::delete_server,
commands::servers::link_server,
commands::servers::unlink_server,
commands::servers::get_project_server_links,
commands::servers::get_server_project_links,
// ssh config & vscode remote
commands::ssh_config::sync_ssh_config,
commands::ssh_config::get_ssh_config_status,
commands::ssh_config::check_vscode_status,
commands::ssh_config::open_vscode_remote,
commands::ssh_config::open_server_terminal,
commands::ssh_config::parse_ssh_config_entries,
commands::ssh_config::import_ssh_config_entries,
// server software & mirrors
commands::server_software::get_github_mirrors,
commands::server_software::add_github_mirror,
commands::server_software::delete_github_mirror,
commands::server_software::test_mirror_local,
commands::server_software::get_server_network_config,
commands::server_software::set_server_mirror,
commands::server_software::get_server_software_list,
commands::server_software::add_server_software,
commands::server_software::update_server_software,
commands::server_software::delete_server_software,
commands::server_software::generate_install_command,
commands::server_software::get_software_categories,
commands::server_software::add_software_category,
commands::server_software::update_software_category,
commands::server_software::delete_software_category,
// api keys
commands::api_keys::get_api_keys,
commands::api_keys::add_api_key,
commands::api_keys::edit_api_key,
commands::api_keys::delete_api_key,
// host apps
commands::host_apps::get_host_apps,
commands::host_apps::add_host_app,
commands::host_apps::edit_host_app,
commands::host_apps::delete_host_app,
// server service configs
commands::service_config::get_service_configs,
commands::service_config::add_service_config,
commands::service_config::edit_service_config,
commands::service_config::delete_service_config,
// gitea integration
commands::gitea::gitea_save_instance,
commands::gitea::gitea_list_instances,
commands::gitea::gitea_delete_instance,
commands::gitea::gitea_update_instance,
commands::gitea::gitea_test_connection,
commands::gitea::gitea_list_linked_repos,
commands::gitea::gitea_get_repo_link,
commands::gitea::gitea_create_repo,
commands::gitea::gitea_migrate_repo,
commands::gitea::gitea_link_repo,
commands::gitea::gitea_setup_webhook,
commands::gitea::gitea_unlink_repo,
commands::gitea::gitea_poll_now,
// beast status (read-only)
get_beast_global_status,
// source library
commands::source_library::get_source_categories,
commands::source_library::create_source_category,
commands::source_library::update_source_category,
commands::source_library::delete_source_category,
commands::source_library::get_source_projects,
commands::source_library::create_source_project,
commands::source_library::update_source_project,
commands::source_library::delete_source_project,
commands::source_library::get_source_versions,
commands::source_library::add_source_version,
commands::source_library::set_primary_version,
commands::source_library::delete_source_version,
commands::source_library::update_version_notes,
commands::source_library::scan_source_dir_tree,
commands::source_library::reveal_source_in_explorer,
commands::source_library::copy_source_to,
// cloud products
commands::cloud_products::get_cloud_products,
commands::cloud_products::add_cloud_product,
commands::cloud_products::edit_cloud_product,
commands::cloud_products::delete_cloud_product,
// cloud db databases
commands::cloud_db_databases::get_cloud_databases,
commands::cloud_db_databases::add_cloud_database,
commands::cloud_db_databases::edit_cloud_database,
commands::cloud_db_databases::delete_cloud_database,
// docker apps
commands::docker_apps::get_docker_apps,
commands::docker_apps::add_docker_app,
commands::docker_apps::edit_docker_app,
commands::docker_apps::delete_docker_app,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}