mirror of
https://github.com/openai/codex.git
synced 2026-11-09 08:40:33 +00:00
Show permissions and approval mode in the TUI status line (#21677)
Fixes #21665. ## Why The TUI status line is the right place for compact, glanceable session state. The original request was motivated by the need to see the active permission posture without opening `/permissions` or `/status`, especially when switching between safer and more permissive modes during a session. This PR intentionally separates `permissions` from `approval-mode` instead of combining them into one status-line item. They answer related but different questions: `permissions` describes the active sandbox/profile shape, while `approval-mode` describes how command approvals are handled. Keeping them separate makes each item independently configurable and avoids long combined labels in an already space-constrained status line. The tradeoff is that users who want the full permission posture in the status line need to opt into both items. In exchange, users can show only the sandbox/profile label, only the approval behavior, or both, and named user-defined profiles remain concise. Non-standard permission shapes are rendered as `Custom permissions` rather than trying to squeeze detailed profile contents into the status line; `/status` remains the fuller explanatory surface. ## What changed - Added a configurable `permissions` status-line item. - Added a separate `approval-mode` status-line item, with `approval` as an alias. - Render standard permission states compactly as `Read Only`, `Workspace`, or `Full Access`. - Preserve user-defined permission profile names directly in the status line. - Render unnamed non-standard permission shapes as `Custom permissions`. - Refresh status surfaces when `/permissions` updates the permission profile, approval policy, or approval reviewer. - Updated status-line preview snapshot coverage for the new items. ## Verification - `cargo test -p codex-tui status_permissions_non_default_workspace_write_uses_workspace_label` - `cargo test -p codex-tui permissions_selection_emits_history_cell_when_selection_changes` - `cargo insta pending-snapshots --manifest-path tui/Cargo.toml`
This commit is contained in:
1 parent
f86d95a242
commit
e6312d44f0
7 files changed
+77
-2
No files matched your search
+1
-1
@@ -2,5 +2,5 @@
|
||||
source: tui/src/chatwidget/tests/status_surface_previews.rs
|
||||
expression: snapshot
|
||||
---
|
||||
status line: my-project · feat/awesome-feature · thread title
|
||||
status line: my-project · feat/awesome-feature · thread title · Read Only · on-request
|
||||
terminal title: thread title | feat/awesome-feature | Tasks 0/0
|
||||
@@ -6,7 +6,12 @@
|
||||
use super::*;
|
||||
use crate::bottom_pane::status_line_from_segments;
|
||||
use crate::branch_summary;
|
||||
use crate::legacy_core::config::Config;
|
||||
use crate::status::format_tokens_compact;
|
||||
use codex_app_server_protocol::AskForApproval;
|
||||
use codex_protocol::config_types::ApprovalsReviewer;
|
||||
use codex_protocol::models::PermissionProfile;
|
||||
use codex_utils_sandbox_summary::summarize_permission_profile;
|
||||
|
||||
/// Items shown in the terminal title when the user has not configured a
|
||||
/// custom selection. Intentionally minimal: activity indicator + project name.
|
||||
@@ -590,6 +595,8 @@ impl ChatWidget {
|
||||
}
|
||||
}),
|
||||
StatusLineItem::Status => Some(self.run_state_status_text()),
|
||||
StatusLineItem::Permissions => Some(permissions_display(&self.config)),
|
||||
StatusLineItem::ApprovalMode => Some(approval_mode_display(&self.config)),
|
||||
StatusLineItem::UsedTokens => {
|
||||
let usage = self.status_line_total_usage();
|
||||
let total = usage.blended_total();
|
||||
@@ -678,6 +685,8 @@ impl ChatWidget {
|
||||
StatusSurfacePreviewItem::GitBranch => StatusLineItem::GitBranch,
|
||||
StatusSurfacePreviewItem::PullRequestNumber => StatusLineItem::PullRequestNumber,
|
||||
StatusSurfacePreviewItem::BranchChanges => StatusLineItem::BranchChanges,
|
||||
StatusSurfacePreviewItem::Permissions => StatusLineItem::Permissions,
|
||||
StatusSurfacePreviewItem::ApprovalMode => StatusLineItem::ApprovalMode,
|
||||
StatusSurfacePreviewItem::ContextRemaining => StatusLineItem::ContextRemaining,
|
||||
StatusSurfacePreviewItem::ContextUsed => StatusLineItem::ContextUsed,
|
||||
StatusSurfacePreviewItem::FiveHourLimit => StatusLineItem::FiveHourLimit,
|
||||
@@ -890,6 +899,44 @@ impl ChatWidget {
|
||||
}
|
||||
}
|
||||
|
||||
fn permissions_display(config: &Config) -> String {
|
||||
let active_permission_profile = config.permissions.active_permission_profile();
|
||||
if let Some(active_permission_profile) = active_permission_profile.as_ref()
|
||||
&& !active_permission_profile.id.starts_with(':')
|
||||
{
|
||||
return active_permission_profile.id.clone();
|
||||
}
|
||||
|
||||
let permission_profile = config.permissions.permission_profile();
|
||||
let summary = summarize_permission_profile(&permission_profile, config.cwd.as_path());
|
||||
if let Some(details) = summary.strip_prefix("read-only")
|
||||
&& !details.contains("(network access enabled)")
|
||||
{
|
||||
return "Read Only".to_string();
|
||||
}
|
||||
if let Some(details) = summary.strip_prefix("workspace-write")
|
||||
&& !details.contains("(network access enabled)")
|
||||
{
|
||||
return "Workspace".to_string();
|
||||
}
|
||||
if permission_profile == PermissionProfile::Disabled {
|
||||
return "Full Access".to_string();
|
||||
}
|
||||
|
||||
"Custom permissions".to_string()
|
||||
}
|
||||
|
||||
fn approval_mode_display(config: &Config) -> String {
|
||||
let approval_policy = AskForApproval::from(config.permissions.approval_policy.value());
|
||||
if approval_policy == AskForApproval::OnRequest
|
||||
&& config.approvals_reviewer == ApprovalsReviewer::AutoReview
|
||||
{
|
||||
"auto-review".to_string()
|
||||
} else {
|
||||
config.permissions.approval_policy.value().to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_items_with_invalids<T>(ids: impl IntoIterator<Item = String>) -> (Vec<T>, Vec<String>)
|
||||
where
|
||||
T: std::str::FromStr,
|
||||
|
||||
@@ -112,6 +112,8 @@ async fn status_surface_preview_lines_hardcoded_only_snapshot() {
|
||||
StatusLineItem::ProjectRoot,
|
||||
StatusLineItem::GitBranch,
|
||||
StatusLineItem::ThreadTitle,
|
||||
StatusLineItem::Permissions,
|
||||
StatusLineItem::ApprovalMode,
|
||||
],
|
||||
&[
|
||||
TerminalTitleItem::Thread,
|
||||
|
||||
Reference in new issue
Block a user