mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
41652665f5
## Summary - wrap OSC 9 notifications in tmux's DCS passthrough so terminal notifications make it through tmux - use codex-terminal-detection for OSC 9 auto-selection so tmux sessions inherit the underlying client terminal support - add focused notification backend tests for plain OSC 9 and tmux-wrapped output ## Stack - base PR: #18479 - review order: #18479, then this PR ## Why Tmux does not forward OSC 9 notifications directly; the sequence has to be wrapped in tmux's DCS passthrough envelope. Codex also had local notification heuristics that could miss supported terminals when running under tmux, even though codex-terminal-detection already knows how to attribute tmux sessions to the client terminal. ## Validation - `just fmt` - `cargo test -p codex-tui` *(currently blocked by an unrelated existing compile error in `app-server/src/message_processor.rs:754` referencing `connection_id` out of scope; not caused by this change)* Co-authored-by: Codex <noreply@openai.com>
136 lines
3.6 KiB
Rust
136 lines
3.6 KiB
Rust
mod bel;
|
|
mod osc9;
|
|
|
|
use std::io;
|
|
|
|
use bel::BelBackend;
|
|
use codex_config::types::NotificationMethod;
|
|
use codex_terminal_detection::TerminalInfo;
|
|
use codex_terminal_detection::TerminalName;
|
|
use codex_terminal_detection::terminal_info;
|
|
use osc9::Osc9Backend;
|
|
|
|
#[derive(Debug)]
|
|
pub enum DesktopNotificationBackend {
|
|
Osc9(Osc9Backend),
|
|
Bel(BelBackend),
|
|
}
|
|
|
|
impl DesktopNotificationBackend {
|
|
pub fn for_method(method: NotificationMethod) -> Self {
|
|
match method {
|
|
NotificationMethod::Auto => {
|
|
if supports_osc9(&terminal_info()) {
|
|
Self::Osc9(Osc9Backend::new())
|
|
} else {
|
|
Self::Bel(BelBackend)
|
|
}
|
|
}
|
|
NotificationMethod::Osc9 => Self::Osc9(Osc9Backend::new()),
|
|
NotificationMethod::Bel => Self::Bel(BelBackend),
|
|
}
|
|
}
|
|
|
|
pub fn method(&self) -> NotificationMethod {
|
|
match self {
|
|
DesktopNotificationBackend::Osc9(_) => NotificationMethod::Osc9,
|
|
DesktopNotificationBackend::Bel(_) => NotificationMethod::Bel,
|
|
}
|
|
}
|
|
|
|
pub fn notify(&mut self, message: &str) -> io::Result<()> {
|
|
match self {
|
|
DesktopNotificationBackend::Osc9(backend) => backend.notify(message),
|
|
DesktopNotificationBackend::Bel(backend) => backend.notify(message),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn detect_backend(method: NotificationMethod) -> DesktopNotificationBackend {
|
|
DesktopNotificationBackend::for_method(method)
|
|
}
|
|
|
|
fn supports_osc9(terminal: &TerminalInfo) -> bool {
|
|
matches!(
|
|
terminal.name,
|
|
TerminalName::Ghostty
|
|
| TerminalName::Iterm2
|
|
| TerminalName::Kitty
|
|
| TerminalName::WarpTerminal
|
|
| TerminalName::WezTerm
|
|
)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::detect_backend;
|
|
use super::supports_osc9;
|
|
use codex_config::types::NotificationMethod;
|
|
use codex_terminal_detection::TerminalInfo;
|
|
use codex_terminal_detection::TerminalName;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
fn test_terminal(name: TerminalName) -> TerminalInfo {
|
|
TerminalInfo {
|
|
name,
|
|
term_program: None,
|
|
version: None,
|
|
term: None,
|
|
multiplexer: None,
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn selects_osc9_method() {
|
|
assert!(matches!(
|
|
detect_backend(NotificationMethod::Osc9),
|
|
super::DesktopNotificationBackend::Osc9(_)
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn selects_bel_method() {
|
|
assert!(matches!(
|
|
detect_backend(NotificationMethod::Bel),
|
|
super::DesktopNotificationBackend::Bel(_)
|
|
));
|
|
}
|
|
|
|
#[test]
|
|
fn supports_osc9_for_supported_terminals() {
|
|
for name in [
|
|
TerminalName::Ghostty,
|
|
TerminalName::Iterm2,
|
|
TerminalName::Kitty,
|
|
TerminalName::WarpTerminal,
|
|
TerminalName::WezTerm,
|
|
] {
|
|
assert!(
|
|
supports_osc9(&test_terminal(name)),
|
|
"{name:?} should support OSC 9"
|
|
);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn supports_osc9_for_unsupported_terminals() {
|
|
for name in [
|
|
TerminalName::AppleTerminal,
|
|
TerminalName::Alacritty,
|
|
TerminalName::Dumb,
|
|
TerminalName::GnomeTerminal,
|
|
TerminalName::Konsole,
|
|
TerminalName::Unknown,
|
|
TerminalName::VsCode,
|
|
TerminalName::Vte,
|
|
TerminalName::WindowsTerminal,
|
|
] {
|
|
assert_eq!(
|
|
supports_osc9(&test_terminal(name)),
|
|
false,
|
|
"{name:?} should not support OSC 9"
|
|
);
|
|
}
|
|
}
|
|
}
|