diff --git a/architecture/notes/nebula_app/ai_hook/2026-09-20-wsl-hook-transport.md b/architecture/notes/nebula_app/platform/wsl_hooks/2026-09-20-wsl-hook-transport.md similarity index 100% rename from architecture/notes/nebula_app/ai_hook/2026-09-20-wsl-hook-transport.md rename to architecture/notes/nebula_app/platform/wsl_hooks/2026-09-20-wsl-hook-transport.md diff --git a/nebula_app/src/ai_hook.rs b/nebula_app/src/ai_hook.rs index 1426016..d50fc39 100644 --- a/nebula_app/src/ai_hook.rs +++ b/nebula_app/src/ai_hook.rs @@ -18,8 +18,6 @@ mod ordering; mod payload; mod protocol; pub(crate) mod remote; -#[cfg(windows)] -pub(crate) mod wsl; pub(crate) use event::CodexHookMode; pub use event::{ diff --git a/nebula_app/src/gpui_shell/terminal/session.rs b/nebula_app/src/gpui_shell/terminal/session.rs index 0e9b064..4d0870c 100644 --- a/nebula_app/src/gpui_shell/terminal/session.rs +++ b/nebula_app/src/gpui_shell/terminal/session.rs @@ -158,8 +158,7 @@ pub(super) fn local_options( // 身份契约必须最后写:它以环境表里 `WSLENV` 的现值为基准合并,才能同时 // 保住上面那段的 cwd 上报条目。见 [`crate::agent_env`]。 crate::agent_env::apply(&mut options.env, pane_id); - #[cfg(windows)] - crate::ai_hook::wsl::prepare(&mut options); + crate::platform::wsl_hooks::prepare(&mut options); options } diff --git a/nebula_app/src/main.rs b/nebula_app/src/main.rs index d48397d..0199ab6 100644 --- a/nebula_app/src/main.rs +++ b/nebula_app/src/main.rs @@ -256,7 +256,7 @@ fn main() -> Result<(), Box> { #[cfg(windows)] Some(Subcommands::SetupAi(options)) => { if let Some(distro) = &options.wsl { - std::process::exit(crate::ai_hook::wsl::setup_cli( + std::process::exit(crate::platform::wsl_hooks::setup_cli( distro, options.wsl_user.as_deref(), options.remove, diff --git a/nebula_app/src/notify.rs b/nebula_app/src/notify.rs index 31f8392..efb4154 100644 --- a/nebula_app/src/notify.rs +++ b/nebula_app/src/notify.rs @@ -517,14 +517,7 @@ fn spawn_actionable_toast( activation: Option, actions: Vec, ) { - #[cfg(windows)] - crate::platform::notifications::toast_actionable(&title, &body, activation, actions); - #[cfg(not(windows))] - if let Err(error) = std::thread::Builder::new().name("pebrel-toast".into()).spawn(move || { - crate::platform::notifications::toast_actionable(&title, &body, activation, actions) - }) { - log::warn!("notify: failed to spawn toast thread: {error}"); - } + crate::platform::notifications::dispatch(title, body, activation, actions); } #[cfg(test)] diff --git a/nebula_app/src/platform/mod.rs b/nebula_app/src/platform/mod.rs index c92d34d..a82c44a 100644 --- a/nebula_app/src/platform/mod.rs +++ b/nebula_app/src/platform/mod.rs @@ -36,6 +36,7 @@ pub mod startup; pub(crate) mod update_installation; #[cfg(feature = "gpui-shell")] pub(crate) mod window_chrome; +pub(crate) mod wsl_hooks; pub use capabilities::CAPABILITIES; diff --git a/nebula_app/src/platform/notifications.rs b/nebula_app/src/platform/notifications.rs index a857479..b95b751 100644 --- a/nebula_app/src/platform/notifications.rs +++ b/nebula_app/src/platform/notifications.rs @@ -16,6 +16,25 @@ pub(crate) fn toast_clickable(title: &str, body: &str, activation: Option, + actions: Vec, +) { + #[cfg(windows)] + toast_actionable(&title, &body, activation, actions); + #[cfg(not(windows))] + if let Err(error) = std::thread::Builder::new() + .name("pebrel-toast".into()) + .spawn(move || toast_actionable(&title, &body, activation, actions)) + { + log::warn!("notify: failed to spawn toast thread: {error}"); + } +} + #[cfg(target_os = "macos")] static MACOS_READY: std::sync::OnceLock = std::sync::OnceLock::new(); diff --git a/nebula_app/src/platform/wsl_hooks.rs b/nebula_app/src/platform/wsl_hooks.rs new file mode 100644 index 0000000..2bf9942 --- /dev/null +++ b/nebula_app/src/platform/wsl_hooks.rs @@ -0,0 +1,8 @@ +//! Guest hook setup is a Windows transport capability. Provider policy stays in ai_hook. +#[cfg(windows)] +mod windows; +#[cfg(windows)] +pub(crate) use windows::{prepare, setup_cli}; + +#[cfg(not(windows))] +pub(crate) fn prepare(_options: &mut nebula_terminal::tty::Options) {} diff --git a/nebula_app/src/ai_hook/wsl.rs b/nebula_app/src/platform/wsl_hooks/windows.rs similarity index 99% rename from nebula_app/src/ai_hook/wsl.rs rename to nebula_app/src/platform/wsl_hooks/windows.rs index 3190f30..8aac37c 100644 --- a/nebula_app/src/ai_hook/wsl.rs +++ b/nebula_app/src/platform/wsl_hooks/windows.rs @@ -13,7 +13,7 @@ use std::time::{Duration, Instant}; use nebula_terminal::tty; use serde_json::json; -use super::remote::{self, Action, Snapshot}; +use crate::ai_hook::remote::{self, Action, Snapshot}; const BUDGET: Duration = Duration::from_secs(8); const MAX_OUTPUT: u64 = 20 * 1024 * 1024;