mirror of
https://github.com/openai/codex.git
synced 2026-05-01 09:56:37 +00:00
feat: experimental menu (#8071)
This will automatically render any `Stage::Beta` features. The change only gets applied to the *next session*. This started as a bug but actually this is a good thing to prevent out of distribution push <img width="986" height="288" alt="Screenshot 2025-12-15 at 15 38 35" src="https://github.com/user-attachments/assets/78b7a71d-0e43-4828-a118-91c5237909c7" /> <img width="509" height="109" alt="Screenshot 2025-12-15 at 17 35 44" src="https://github.com/user-attachments/assets/6933de52-9b66-4abf-b58b-a5f26d5747e2" />
This commit is contained in:
@@ -9,6 +9,8 @@ use codex_app_server_protocol::AuthMode;
|
||||
use codex_backend_client::Client as BackendClient;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::types::Notifications;
|
||||
use codex_core::features::FEATURES;
|
||||
use codex_core::features::Feature;
|
||||
use codex_core::git_info::current_branch_name;
|
||||
use codex_core::git_info::local_git_branches;
|
||||
use codex_core::openai_models::model_family::ModelFamily;
|
||||
@@ -85,9 +87,11 @@ use tracing::debug;
|
||||
use crate::app_event::AppEvent;
|
||||
use crate::app_event_sender::AppEventSender;
|
||||
use crate::bottom_pane::ApprovalRequest;
|
||||
use crate::bottom_pane::BetaFeatureItem;
|
||||
use crate::bottom_pane::BottomPane;
|
||||
use crate::bottom_pane::BottomPaneParams;
|
||||
use crate::bottom_pane::CancellationEvent;
|
||||
use crate::bottom_pane::ExperimentalFeaturesView;
|
||||
use crate::bottom_pane::InputResult;
|
||||
use crate::bottom_pane::SelectionAction;
|
||||
use crate::bottom_pane::SelectionItem;
|
||||
@@ -1571,6 +1575,9 @@ impl ChatWidget {
|
||||
SlashCommand::Approvals => {
|
||||
self.open_approvals_popup();
|
||||
}
|
||||
SlashCommand::Experimental => {
|
||||
self.open_experimental_popup();
|
||||
}
|
||||
SlashCommand::Quit | SlashCommand::Exit => {
|
||||
self.request_exit();
|
||||
}
|
||||
@@ -2635,6 +2642,24 @@ impl ChatWidget {
|
||||
});
|
||||
}
|
||||
|
||||
pub(crate) fn open_experimental_popup(&mut self) {
|
||||
let features: Vec<BetaFeatureItem> = FEATURES
|
||||
.iter()
|
||||
.filter_map(|spec| {
|
||||
let description = spec.stage.beta_menu_description()?;
|
||||
Some(BetaFeatureItem {
|
||||
feature: spec.id,
|
||||
name: feature_label_from_key(spec.key),
|
||||
description: description.to_string(),
|
||||
enabled: self.config.features.enabled(spec.id),
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let view = ExperimentalFeaturesView::new(features, self.app_event_tx.clone());
|
||||
self.bottom_pane.show_view(Box::new(view));
|
||||
}
|
||||
|
||||
fn approval_preset_actions(
|
||||
approval: AskForApproval,
|
||||
sandbox: SandboxPolicy,
|
||||
@@ -2977,6 +3002,14 @@ impl ChatWidget {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_feature_enabled(&mut self, feature: Feature, enabled: bool) {
|
||||
if enabled {
|
||||
self.config.features.enable(feature);
|
||||
} else {
|
||||
self.config.features.disable(feature);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_full_access_warning_acknowledged(&mut self, acknowledged: bool) {
|
||||
self.config.notices.hide_full_access_warning = Some(acknowledged);
|
||||
}
|
||||
@@ -3310,6 +3343,23 @@ impl ChatWidget {
|
||||
}
|
||||
}
|
||||
|
||||
fn feature_label_from_key(key: &str) -> String {
|
||||
let mut out = String::with_capacity(key.len());
|
||||
let mut capitalize = true;
|
||||
for ch in key.chars() {
|
||||
if ch == '_' || ch == '-' {
|
||||
out.push(' ');
|
||||
capitalize = true;
|
||||
} else if capitalize {
|
||||
out.push(ch.to_ascii_uppercase());
|
||||
capitalize = false;
|
||||
} else {
|
||||
out.push(ch);
|
||||
}
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
impl Drop for ChatWidget {
|
||||
fn drop(&mut self) {
|
||||
self.stop_rate_limit_poller();
|
||||
|
||||
Reference in New Issue
Block a user