feat(tui): Add confirmation prompt for enabling full access approvals (#4980)

## Summary
Adds a confirmation screen when a user attempts to select Full Access
via the `/approvals` flow in the TUI.

If the user selects the remember option, the preference is persisted to
config.toml as `full_access_warning_acknowledged`, so they will not be
prompted again.


## Testing
- [x] Adds snapshot test coverage for the approvals flow and the
confirmation flow
<img width="865" height="187" alt="Screenshot 2025-10-08 at 6 04 59 PM"
src="https://github.com/user-attachments/assets/fd1dac62-28b0-4835-ba91-5da6dc5ec4c4"
/>



------
https://chatgpt.com/codex/tasks/task_i_68e6c5c458088322a28efa3207058180

---------

Co-authored-by: Fouad Matin <169186268+fouad-openai@users.noreply.github.com>
Co-authored-by: Fouad Matin <fouad@openai.com>
This commit is contained in:
Dylan
2025-10-16 17:31:46 -07:00
committed by GitHub
parent fc1723f131
commit 78f2785595
8 changed files with 276 additions and 14 deletions

View File

@@ -7,6 +7,7 @@ use crate::config_types::DEFAULT_OTEL_ENVIRONMENT;
use crate::config_types::History;
use crate::config_types::McpServerConfig;
use crate::config_types::McpServerTransportConfig;
use crate::config_types::Notice;
use crate::config_types::Notifications;
use crate::config_types::OtelConfig;
use crate::config_types::OtelConfigToml;
@@ -242,6 +243,9 @@ pub struct Config {
/// Tracks whether the Windows onboarding screen has been acknowledged.
pub windows_wsl_setup_acknowledged: bool,
/// Collection of various notices we show the user
pub notices: Notice,
/// When true, disables burst-paste detection for typed input entirely.
/// All characters are inserted as they are received, and no buffering
/// or placeholder replacement will occur for fast keypress bursts.
@@ -557,6 +561,54 @@ pub fn set_windows_wsl_setup_acknowledged(
Ok(())
}
/// Persist the acknowledgement flag for the full access warning prompt.
pub fn set_hide_full_access_warning(codex_home: &Path, acknowledged: bool) -> anyhow::Result<()> {
let config_path = codex_home.join(CONFIG_TOML_FILE);
let mut doc = match std::fs::read_to_string(config_path.clone()) {
Ok(s) => s.parse::<DocumentMut>()?,
Err(e) if e.kind() == std::io::ErrorKind::NotFound => DocumentMut::new(),
Err(e) => return Err(e.into()),
};
let notices_table = load_or_create_top_level_table(&mut doc, Notice::TABLE_KEY)?;
notices_table["hide_full_access_warning"] = toml_edit::value(acknowledged);
std::fs::create_dir_all(codex_home)?;
let tmp_file = NamedTempFile::new_in(codex_home)?;
std::fs::write(tmp_file.path(), doc.to_string())?;
tmp_file.persist(config_path)?;
Ok(())
}
fn load_or_create_top_level_table<'a>(
doc: &'a mut DocumentMut,
key: &str,
) -> anyhow::Result<&'a mut toml_edit::Table> {
let mut created_table = false;
let root = doc.as_table_mut();
let needs_table =
!root.contains_key(key) || root.get(key).and_then(|item| item.as_table()).is_none();
if needs_table {
root.insert(key, toml_edit::table());
created_table = true;
}
let Some(table) = doc[key].as_table_mut() else {
return Err(anyhow::anyhow!(format!(
"table [{key}] missing after initialization"
)));
};
if created_table {
table.set_implicit(true);
}
Ok(table)
}
fn ensure_profile_table<'a>(
doc: &'a mut DocumentMut,
profile_name: &str,
@@ -832,6 +884,10 @@ pub struct ConfigToml {
/// Tracks whether the Windows onboarding screen has been acknowledged.
pub windows_wsl_setup_acknowledged: Option<bool>,
/// Collection of in-product notices (different from notifications)
/// See [`crate::config_types::Notices`] for more details
pub notice: Option<Notice>,
/// Legacy, now use features
pub experimental_instructions_file: Option<PathBuf>,
pub experimental_use_exec_command_tool: Option<bool>,
@@ -1247,6 +1303,7 @@ impl Config {
active_profile: active_profile_name,
active_project,
windows_wsl_setup_acknowledged: cfg.windows_wsl_setup_acknowledged.unwrap_or(false),
notices: cfg.notice.unwrap_or_default(),
disable_paste_burst: cfg.disable_paste_burst.unwrap_or(false),
tui_notifications: cfg
.tui
@@ -2330,6 +2387,7 @@ model_verbosity = "high"
active_profile: Some("o3".to_string()),
active_project: ProjectConfig { trust_level: None },
windows_wsl_setup_acknowledged: false,
notices: Default::default(),
disable_paste_burst: false,
tui_notifications: Default::default(),
otel: OtelConfig::default(),
@@ -2396,6 +2454,7 @@ model_verbosity = "high"
active_profile: Some("gpt3".to_string()),
active_project: ProjectConfig { trust_level: None },
windows_wsl_setup_acknowledged: false,
notices: Default::default(),
disable_paste_burst: false,
tui_notifications: Default::default(),
otel: OtelConfig::default(),
@@ -2477,6 +2536,7 @@ model_verbosity = "high"
active_profile: Some("zdr".to_string()),
active_project: ProjectConfig { trust_level: None },
windows_wsl_setup_acknowledged: false,
notices: Default::default(),
disable_paste_burst: false,
tui_notifications: Default::default(),
otel: OtelConfig::default(),
@@ -2544,6 +2604,7 @@ model_verbosity = "high"
active_profile: Some("gpt5".to_string()),
active_project: ProjectConfig { trust_level: None },
windows_wsl_setup_acknowledged: false,
notices: Default::default(),
disable_paste_burst: false,
tui_notifications: Default::default(),
otel: OtelConfig::default(),

View File

@@ -322,6 +322,20 @@ pub struct Tui {
pub notifications: Notifications,
}
/// Settings for notices we display to users via the tui and app-server clients
/// (primarily the Codex IDE extension). NOTE: these are different from
/// notifications - notices are warnings, NUX screens, acknowledgements, etc.
#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
pub struct Notice {
/// Tracks whether the user has acknowledged the full access warning prompt.
pub hide_full_access_warning: Option<bool>,
}
impl Notice {
/// used by set_hide_full_access_warning until we refactor config updates
pub(crate) const TABLE_KEY: &'static str = "notice";
}
#[derive(Deserialize, Debug, Clone, PartialEq, Default)]
pub struct SandboxWorkspaceWrite {
#[serde(default)]