Enable TUI voice conversations by default (#44921)

## What changed

Promote `realtime_conversation` to stable and enable it by default, removing its experimental announcement. Update popup and tooltip tests to use explicit experimental voice fixtures now that the feature is stable.

GitOrigin-RevId: 4e947189f41de465d1f343e95100b26d6200db24
This commit is contained in:
Benjamin Carlsson
2026-09-11 21:59:01 +00:00
committed by copyberry
parent 3052bbcf8c
commit 3f59eb965a
3 changed files with 25 additions and 15 deletions
+3 -7
View File
@@ -348,7 +348,7 @@ pub enum Feature {
FastMode,
/// Enable explicitly requested model changes for later step captures.
StepModelSwitching,
/// Removed compatibility flag. Realtime sessions no longer require a per-thread opt-in.
/// Enable voice conversations in the TUI.
RealtimeConversation,
/// Prevent idle system sleep while a turn is actively running.
PreventIdleSleep,
@@ -1692,12 +1692,8 @@ pub const FEATURES: &[FeatureSpec] = &[
FeatureSpec {
id: Feature::RealtimeConversation,
key: "realtime_conversation",
stage: Stage::Experimental {
name: "Voice conversations",
menu_description: "Talk with Codex using /voice.",
announcement: "NEW: Voice conversations can now be enabled from /experimental. Restart Codex after enabling, then use /voice.",
},
default_enabled: false,
stage: Stage::Stable,
default_enabled: true,
},
FeatureSpec {
id: Feature::RemoteControl,
@@ -3038,7 +3038,6 @@ async fn apps_popup_for_not_installed_app_uses_install_only_selected_description
async fn experimental_features_popup_snapshot() {
let (mut chat, _rx, _op_rx) = make_chatwidget_manual(/*model_override*/ None).await;
let voice = Feature::RealtimeConversation.stage();
let features = vec![
ExperimentalFeatureItem {
key: Feature::JsRepl.key().to_string(),
@@ -3057,8 +3056,8 @@ async fn experimental_features_popup_snapshot() {
ExperimentalFeatureItem {
key: Feature::RealtimeConversation.key().to_string(),
writable: true,
name: voice.experimental_menu_name().unwrap().to_string(),
description: voice.experimental_menu_description().unwrap().to_string(),
name: "Voice conversations".to_string(),
description: "Talk with Codex using /voice.".to_string(),
enabled: false,
},
];
+20 -5
View File
@@ -1,5 +1,6 @@
use codex_features::FEATURES;
use codex_features::Feature;
use codex_features::FeatureSpec;
use codex_protocol::account::PlanType;
use lazy_static::lazy_static;
use rand::Rng;
@@ -38,14 +39,18 @@ lazy_static! {
let mut tips = Vec::new();
tips.extend(TOOLTIPS.iter().copied());
tips.extend(experimental_tooltips(
FEATURES,
codex_realtime_webrtc::RealtimeWebrtcSession::is_supported,
));
tips
};
}
fn experimental_tooltips(voice_supported: impl Fn() -> bool) -> Vec<&'static str> {
FEATURES
fn experimental_tooltips(
features: &[FeatureSpec],
voice_supported: impl Fn() -> bool,
) -> Vec<&'static str> {
features
.iter()
.filter(|spec| spec.id != Feature::RealtimeConversation || voice_supported())
.filter_map(|spec| spec.stage.experimental_announcement())
@@ -364,9 +369,19 @@ mod tests {
#[test]
fn experimental_voice_tooltip_requires_runtime_support() {
let unavailable = experimental_tooltips(|| false);
let available = experimental_tooltips(|| true);
let voice_tip = FEATURES
let mut features = FEATURES.to_vec();
features
.iter_mut()
.find(|spec| spec.id == Feature::RealtimeConversation)
.unwrap()
.stage = codex_features::Stage::Experimental {
name: "Voice conversations",
menu_description: "Talk with Codex using /voice.",
announcement: "NEW: Voice conversations can now be enabled from /experimental. Restart Codex after enabling, then use /voice.",
};
let unavailable = experimental_tooltips(&features, || false);
let available = experimental_tooltips(&features, || true);
let voice_tip = features
.iter()
.find(|spec| spec.id == Feature::RealtimeConversation)
.and_then(|spec| spec.stage.experimental_announcement())