Add per-turn Cyber access program selection to exec and the SDK (#49939)

## Why

`codex exec` and the TypeScript SDK need a way to request a Cyber access program for an individual turn. Resuming with an API key can also leave compaction using a saved program that the current credentials cannot access.

## What changed

- Add `--cyber-access-program` with `standard`, `daybreak_blue`, and `daybreak_red`, and expose the equivalent `cyberAccessProgram` turn option and `CyberAccessProgram` type in the TypeScript SDK.
- Apply explicit selections to new, resumed, and prompted fork turns. Override automatic Daybreak selection for that turn without changing the saved choice. Reject the flag for review and forks without a prompt.
- Filter Cyber programs by the built-in OpenAI provider when starting turns and restoring previous-turn settings for compaction.
- Allow previous-model compaction fallback with API-key authentication, comparing both model and program so a program change can trigger a retry with the current pair even when the model is unchanged.

## Testing

Add CLI help, argument parsing, exec, and SDK coverage for per-turn selection and unsupported commands. Extend core tests for API-key compaction retries, denied explicit selections, custom-provider filtering, remote compaction, and WebSocket response reuse.

GitOrigin-RevId: 586f25b621924f3bc509c9a39b39fe2020ff9cd2
This commit is contained in:
mldangelo-oai
2026-10-01 08:57:53 +00:00
committed by copyberry
parent 444da310e1
commit 6b4daafdb4
19 changed files with 548 additions and 40 deletions
+23
View File
@@ -28,6 +28,11 @@ pub struct Cli {
#[arg(long = "thread-source", value_name = "SOURCE", global = true)]
pub thread_source: Option<ThreadSource>,
/// Request an experimental Cyber access program for this turn (OpenAI provider only).
/// Omit to use server defaults. Not supported with review; fork requires a prompt.
#[arg(long, value_enum, value_name = "PROGRAM", global = true)]
pub cyber_access_program: Option<CyberAccessProgramCliArg>,
/// Allow running Codex outside a Git repository.
#[arg(long = "skip-git-repo-check", global = true, default_value_t = false)]
pub skip_git_repo_check: bool,
@@ -80,6 +85,24 @@ pub struct Cli {
pub prompt: Option<String>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
#[value(rename_all = "snake_case")]
pub enum CyberAccessProgramCliArg {
Standard,
DaybreakBlue,
DaybreakRed,
}
impl From<CyberAccessProgramCliArg> for codex_app_server_protocol::CyberAccessProgram {
fn from(value: CyberAccessProgramCliArg) -> Self {
match value {
CyberAccessProgramCliArg::Standard => Self::Standard,
CyberAccessProgramCliArg::DaybreakBlue => Self::DaybreakBlue,
CyberAccessProgramCliArg::DaybreakRed => Self::DaybreakRed,
}
}
}
impl std::ops::Deref for Cli {
type Target = SharedCliOptions;