Make goals feature on by default and no longer experimental (#23732)

## Why

The `goals` feature is ready to be available without requiring users to
opt into experimental features. Keeping it behind the beta flag leaves
persisted thread goals and automatic goal continuation disabled by
default.

This PR also marks the goal-related app server APIs and events as no
longer experimental.

## What changed

- Mark `goals` as `Stage::Stable`.
- Enable `goals` by default in `codex-rs/features/src/lib.rs`.
This commit is contained in:
Eric Traut
2026-05-20 15:07:35 -07:00
committed by GitHub
parent 3075061bdd
commit 0e9d222178
21 changed files with 782 additions and 38 deletions
+9 -19
View File
@@ -2,9 +2,8 @@ use super::*;
use codex_app_server_protocol::ConfigWarningNotification;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::ServerNotification;
use codex_app_server_protocol::ThreadGoal;
use codex_app_server_protocol::ThreadGoalStatus;
use codex_app_server_protocol::ThreadGoalUpdatedNotification;
use codex_app_server_protocol::ThreadRealtimeStartedNotification;
use codex_protocol::protocol::RealtimeConversationVersion;
use codex_utils_absolute_path::AbsolutePathBuf;
use pretty_assertions::assert_eq;
use serde_json::json;
@@ -15,20 +14,11 @@ fn absolute_path(path: &str) -> AbsolutePathBuf {
AbsolutePathBuf::from_absolute_path(path).expect("absolute path")
}
fn thread_goal_updated_notification() -> ServerNotification {
ServerNotification::ThreadGoalUpdated(ThreadGoalUpdatedNotification {
fn thread_realtime_started_notification() -> ServerNotification {
ServerNotification::ThreadRealtimeStarted(ThreadRealtimeStartedNotification {
thread_id: "thread-1".to_string(),
turn_id: None,
goal: ThreadGoal {
thread_id: "thread-1".to_string(),
objective: "ship goal mode".to_string(),
status: ThreadGoalStatus::Active,
token_budget: None,
tokens_used: 0,
time_used_seconds: 0,
created_at: 1,
updated_at: 1,
},
realtime_session_id: None,
version: RealtimeConversationVersion::V1,
})
}
@@ -182,7 +172,7 @@ async fn experimental_notifications_are_dropped_without_capability() {
&mut connections,
OutgoingEnvelope::ToConnection {
connection_id,
message: OutgoingMessage::AppServerNotification(thread_goal_updated_notification()),
message: OutgoingMessage::AppServerNotification(thread_realtime_started_notification()),
write_complete_tx: None,
},
)
@@ -215,7 +205,7 @@ async fn experimental_notifications_are_preserved_with_capability() {
&mut connections,
OutgoingEnvelope::ToConnection {
connection_id,
message: OutgoingMessage::AppServerNotification(thread_goal_updated_notification()),
message: OutgoingMessage::AppServerNotification(thread_realtime_started_notification()),
write_complete_tx: None,
},
)
@@ -227,7 +217,7 @@ async fn experimental_notifications_are_preserved_with_capability() {
.expect("experimental notification should reach opted-in client");
assert!(matches!(
message.message,
OutgoingMessage::AppServerNotification(ServerNotification::ThreadGoalUpdated(_))
OutgoingMessage::AppServerNotification(ServerNotification::ThreadRealtimeStarted(_))
));
}