mirror of
https://github.com/openai/codex.git
synced 2026-11-05 16:29:31 +00:00
Add TUI notification condition config (#17175)
Problem: TUI desktop notifications are hard-gated on terminal focus, so terminal/IDE hosts that want in-focus notifications cannot opt in. Solution: Add a flat `[tui] notification_condition` setting (`unfocused` by default, `always` opt-in), carry grouped TUI notification settings through runtime config, apply method + condition together in the TUI, and regenerate the config schema.
This commit is contained in:
1 parent
2f9090be62
commit
6dc5391c7c
8 files changed
+191
-48
No files matched your search
@@ -34,12 +34,14 @@ use codex_config::types::McpServerTransportConfig;
|
||||
use codex_config::types::MemoriesConfig;
|
||||
use codex_config::types::MemoriesToml;
|
||||
use codex_config::types::ModelAvailabilityNuxConfig;
|
||||
use codex_config::types::NotificationCondition;
|
||||
use codex_config::types::NotificationMethod;
|
||||
use codex_config::types::Notifications;
|
||||
use codex_config::types::SandboxWorkspaceWrite;
|
||||
use codex_config::types::SkillsConfig;
|
||||
use codex_config::types::ToolSuggestDiscoverableType;
|
||||
use codex_config::types::Tui;
|
||||
use codex_config::types::TuiNotificationSettings;
|
||||
use codex_features::Feature;
|
||||
use codex_features::FeaturesToml;
|
||||
use codex_model_provider_info::LMSTUDIO_OSS_PROVIDER_ID;
|
||||
@@ -355,8 +357,7 @@ fn config_toml_deserializes_model_availability_nux() {
|
||||
assert_eq!(
|
||||
cfg.tui.expect("tui config should deserialize"),
|
||||
Tui {
|
||||
notifications: Notifications::default(),
|
||||
notification_method: NotificationMethod::default(),
|
||||
notification_settings: TuiNotificationSettings::default(),
|
||||
animations: true,
|
||||
show_tooltips: true,
|
||||
alternate_screen: AltScreenMode::default(),
|
||||
@@ -1052,8 +1053,7 @@ fn tui_config_missing_notifications_field_defaults_to_enabled() {
|
||||
assert_eq!(
|
||||
tui,
|
||||
Tui {
|
||||
notifications: Notifications::Enabled(true),
|
||||
notification_method: NotificationMethod::Auto,
|
||||
notification_settings: TuiNotificationSettings::default(),
|
||||
animations: true,
|
||||
show_tooltips: true,
|
||||
alternate_screen: AltScreenMode::Auto,
|
||||
@@ -4583,7 +4583,6 @@ fn test_precedence_fixture_with_o3_profile() -> std::io::Result<()> {
|
||||
check_for_update_on_startup: true,
|
||||
disable_paste_burst: false,
|
||||
tui_notifications: Default::default(),
|
||||
tui_notification_method: Default::default(),
|
||||
animations: true,
|
||||
show_tooltips: true,
|
||||
model_availability_nux: ModelAvailabilityNuxConfig::default(),
|
||||
@@ -4730,7 +4729,6 @@ fn test_precedence_fixture_with_gpt3_profile() -> std::io::Result<()> {
|
||||
check_for_update_on_startup: true,
|
||||
disable_paste_burst: false,
|
||||
tui_notifications: Default::default(),
|
||||
tui_notification_method: Default::default(),
|
||||
animations: true,
|
||||
show_tooltips: true,
|
||||
model_availability_nux: ModelAvailabilityNuxConfig::default(),
|
||||
@@ -4875,7 +4873,6 @@ fn test_precedence_fixture_with_zdr_profile() -> std::io::Result<()> {
|
||||
check_for_update_on_startup: true,
|
||||
disable_paste_burst: false,
|
||||
tui_notifications: Default::default(),
|
||||
tui_notification_method: Default::default(),
|
||||
animations: true,
|
||||
show_tooltips: true,
|
||||
model_availability_nux: ModelAvailabilityNuxConfig::default(),
|
||||
@@ -5006,7 +5003,6 @@ fn test_precedence_fixture_with_gpt5_profile() -> std::io::Result<()> {
|
||||
check_for_update_on_startup: true,
|
||||
disable_paste_burst: false,
|
||||
tui_notifications: Default::default(),
|
||||
tui_notification_method: Default::default(),
|
||||
animations: true,
|
||||
show_tooltips: true,
|
||||
model_availability_nux: ModelAvailabilityNuxConfig::default(),
|
||||
@@ -6559,10 +6555,8 @@ speaker = "Desk Speakers"
|
||||
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
struct TuiTomlTest {
|
||||
#[serde(default)]
|
||||
notifications: Notifications,
|
||||
#[serde(default)]
|
||||
notification_method: NotificationMethod,
|
||||
#[serde(default, flatten)]
|
||||
notifications: TuiNotificationSettings,
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Debug, PartialEq)]
|
||||
@@ -6577,7 +6571,10 @@ fn test_tui_notifications_true() {
|
||||
notifications = true
|
||||
"#;
|
||||
let parsed: RootTomlTest = toml::from_str(toml).expect("deserialize notifications=true");
|
||||
assert_matches!(parsed.tui.notifications, Notifications::Enabled(true));
|
||||
assert_matches!(
|
||||
parsed.tui.notifications.notifications,
|
||||
Notifications::Enabled(true)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -6588,7 +6585,7 @@ fn test_tui_notifications_custom_array() {
|
||||
"#;
|
||||
let parsed: RootTomlTest = toml::from_str(toml).expect("deserialize notifications=[\"foo\"]");
|
||||
assert_matches!(
|
||||
parsed.tui.notifications,
|
||||
parsed.tui.notifications.notifications,
|
||||
Notifications::Custom(ref v) if v == &vec!["foo".to_string()]
|
||||
);
|
||||
}
|
||||
@@ -6601,5 +6598,48 @@ fn test_tui_notification_method() {
|
||||
"#;
|
||||
let parsed: RootTomlTest =
|
||||
toml::from_str(toml).expect("deserialize notification_method=\"bel\"");
|
||||
assert_eq!(parsed.tui.notification_method, NotificationMethod::Bel);
|
||||
assert_eq!(parsed.tui.notifications.method, NotificationMethod::Bel);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tui_notification_condition_defaults_to_unfocused() {
|
||||
let toml = r#"
|
||||
[tui]
|
||||
"#;
|
||||
let parsed: RootTomlTest =
|
||||
toml::from_str(toml).expect("deserialize default notification condition");
|
||||
assert_eq!(
|
||||
parsed.tui.notifications.condition,
|
||||
NotificationCondition::Unfocused
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tui_notification_condition_always() {
|
||||
let toml = r#"
|
||||
[tui]
|
||||
notification_condition = "always"
|
||||
"#;
|
||||
let parsed: RootTomlTest =
|
||||
toml::from_str(toml).expect("deserialize notification_condition=\"always\"");
|
||||
assert_eq!(
|
||||
parsed.tui.notifications.condition,
|
||||
NotificationCondition::Always
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tui_notification_condition_rejects_unknown_value() {
|
||||
let toml = r#"
|
||||
[tui]
|
||||
notification_condition = "background"
|
||||
"#;
|
||||
let err = toml::from_str::<RootTomlTest>(toml).expect_err("reject unknown condition");
|
||||
let err = err.to_string();
|
||||
assert!(
|
||||
err.contains("unknown variant `background`")
|
||||
&& err.contains("unfocused")
|
||||
&& err.contains("always"),
|
||||
"unexpected error: {err}"
|
||||
);
|
||||
}
|
||||
@@ -38,8 +38,6 @@ use codex_config::types::McpServerTransportConfig;
|
||||
use codex_config::types::MemoriesConfig;
|
||||
use codex_config::types::ModelAvailabilityNuxConfig;
|
||||
use codex_config::types::Notice;
|
||||
use codex_config::types::NotificationMethod;
|
||||
use codex_config::types::Notifications;
|
||||
use codex_config::types::OAuthCredentialsStoreMode;
|
||||
use codex_config::types::OtelConfig;
|
||||
use codex_config::types::OtelConfigToml;
|
||||
@@ -47,6 +45,7 @@ use codex_config::types::OtelExporterKind;
|
||||
use codex_config::types::ShellEnvironmentPolicy;
|
||||
use codex_config::types::ToolSuggestConfig;
|
||||
use codex_config::types::ToolSuggestDiscoverable;
|
||||
use codex_config::types::TuiNotificationSettings;
|
||||
use codex_config::types::UriBasedFileOpener;
|
||||
use codex_config::types::WindowsSandboxModeToml;
|
||||
use codex_features::Feature;
|
||||
@@ -301,12 +300,8 @@ pub struct Config {
|
||||
/// If unset the feature is disabled.
|
||||
pub notify: Option<Vec<String>>,
|
||||
|
||||
/// TUI notifications preference. When set, the TUI will send terminal notifications on
|
||||
/// approvals and turn completions when not focused.
|
||||
pub tui_notifications: Notifications,
|
||||
|
||||
/// Notification method for terminal notifications (osc9 or bel).
|
||||
pub tui_notification_method: NotificationMethod,
|
||||
/// TUI notification settings, including enabled events, delivery method, and focus condition.
|
||||
pub tui_notifications: TuiNotificationSettings,
|
||||
|
||||
/// Enable ASCII animations and shimmer effects in the TUI.
|
||||
pub animations: bool,
|
||||
@@ -2136,12 +2131,7 @@ impl Config {
|
||||
tui_notifications: cfg
|
||||
.tui
|
||||
.as_ref()
|
||||
.map(|t| t.notifications.clone())
|
||||
.unwrap_or_default(),
|
||||
tui_notification_method: cfg
|
||||
.tui
|
||||
.as_ref()
|
||||
.map(|t| t.notification_method)
|
||||
.map(|t| t.notification_settings.clone())
|
||||
.unwrap_or_default(),
|
||||
animations: cfg.tui.as_ref().map(|t| t.animations).unwrap_or(true),
|
||||
show_tooltips: cfg.tui.as_ref().map(|t| t.show_tooltips).unwrap_or(true),
|
||||
|
||||
Reference in new issue
Block a user