Add per-turn cyber access program selection (#40687)

## What changed

- Add the experimental `turn/start.cyberAccessProgram` option with `standard`,
  `daybreakBlue`, and `daybreakRed` values.
- Forward the selection as `access_programs.cyber` on Responses, WebSocket,
  and remote-compaction requests made with ChatGPT authentication, while
  omitting it for API-key and custom-provider requests.
- Preserve the per-turn selection across recovery, compaction, and child-agent
  turns without making it a persistent thread setting.

## Testing

- Cover app-server forwarding, authentication boundaries, WebSocket reuse,
  turn recovery, compaction, and child-agent inheritance.

GitOrigin-RevId: d2eb468f365b2214c5099bc21741cf30f8bd2eb5
This commit is contained in:
faizan-oai authored and copyberry committed 2026-08-25 19:54:52 +00:00
1 parent a6e63f9f32
commit 94967e03e5
72 files changed
+1323 -273

No files matched your search

+28 -22
View File
@@ -82,16 +82,11 @@ pub async fn inter_agent_communication(
sess: &Arc<Session>,
sub_id: String,
communication: InterAgentCommunication,
parent_turn_id: Option<String>,
root_turn_id: Option<String>,
start_options: codex_protocol::turn_input::TurnStartOptions,
) {
let trigger_turn = communication.trigger_turn;
sess.input_queue
.enqueue_mailbox_communication(
communication,
parent_turn_id.filter(|_| trigger_turn),
root_turn_id.filter(|_| trigger_turn),
)
.enqueue_mailbox_communication(communication, start_options)
.await;
crate::agent_communication::emit_agent_communication_receive(&sub_id);
if trigger_turn || sess.has_outstanding_durable_sleep() {
@@ -118,7 +113,9 @@ pub async fn run_user_shell_command(sess: &Arc<Session>, sub_id: String, command
return;
}
let turn_context = sess.new_default_turn_with_sub_id(sub_id).await;
let turn_context = sess
.new_turn_with_default_settings(sub_id, Default::default())
.await;
sess.spawn_task(turn_context, Vec::new(), UserShellCommandTask::new(command))
.await;
}
@@ -237,7 +234,9 @@ pub async fn reload_user_config(sess: &Arc<Session>) {
}
pub async fn compact(sess: &Arc<Session>, sub_id: String) {
let turn_context = sess.new_default_turn_with_sub_id(sub_id).await;
let turn_context = sess
.new_turn_with_default_settings(sub_id, Default::default())
.await;
sess.spawn_task(turn_context, Vec::new(), CompactTask).await;
}
@@ -268,7 +267,9 @@ pub async fn thread_rollback(sess: &Arc<Session>, sub_id: String, num_turns: u32
return;
}
let turn_context = sess.new_default_turn_with_sub_id(sub_id).await;
let turn_context = sess
.new_turn_with_default_settings(sub_id, Default::default())
.await;
let live_thread = match sess.live_thread_for_persistence("rollback thread") {
Ok(live_thread) => live_thread,
Err(_) => {
@@ -478,7 +479,9 @@ pub async fn review(
sub_id: String,
review_request: ReviewRequest,
) {
let turn_context = sess.new_default_turn_with_sub_id(sub_id.clone()).await;
let turn_context = sess
.new_turn_with_default_settings(sub_id.clone(), Default::default())
.await;
sess.maybe_emit_model_warnings_for_turn(turn_context.as_ref())
.await;
#[allow(deprecated)]
@@ -572,10 +575,16 @@ pub(super) async fn submission_loop(
}
Op::RecoverTurn {
thread_settings,
start_options,
reply,
} => {
let result =
turn_input::handle_recovery(&sess, thread_settings, sub.id.clone()).await;
let result = turn_input::handle_recovery(
&sess,
thread_settings,
start_options,
sub.id.clone(),
)
.await;
let _ = reply.send(result);
false
}
@@ -605,15 +614,12 @@ pub(super) async fn submission_loop(
let _ = reply.send(outcome);
false
}
Op::InterAgentCommunication { communication } => {
inter_agent_communication(
&sess,
sub.id.clone(),
communication,
sub.parent_turn_id,
sub.root_turn_id,
)
.await;
Op::InterAgentCommunication {
communication,
start_options,
} => {
inter_agent_communication(&sess, sub.id.clone(), communication, start_options)
.await;
false
}
Op::ExecApproval {