mirror of
https://github.com/openai/codex.git
synced 2026-11-01 19:33:35 +00:00
## What changed - Default `features.api_key_cyber_access_programs` to `true` and allow `codex exec` to select Daybreak with an OpenAI API key. Select the advertised standard program when `daybreak=false`, while respecting explicit feature opt-outs. - Resolve API-key eligibility for TUI background turns from the target thread's feature settings, including project opt-outs. Omit access-program overrides when the server cannot report those settings. - Preserve automatic server treatment for unlisted models and missing or empty Cyber program metadata in exec and TUI. Continue rejecting Daybreak when a nonempty program list does not offer it. ## Testing Update regression coverage for API-key Daybreak selection, the off override, explicit opt-outs, resumed sessions, target-thread settings, and missing model metadata. GitOrigin-RevId: f3cf7bd95a2754d4b4281bc70b18c7da4b177552
109 lines
3.2 KiB
Rust
109 lines
3.2 KiB
Rust
//! Account-scoped Daybreak eligibility and per-turn program selection.
|
|
//! Pending or failed discovery never implies access.
|
|
|
|
use codex_protocol::openai_models::ModelAccessPrograms;
|
|
use codex_protocol::openai_models::ModelPreset;
|
|
use codex_protocol::turn_input::CyberAccessProgram;
|
|
|
|
pub(crate) fn program_for_turn(
|
|
models: &[ModelPreset],
|
|
model: &str,
|
|
eligible_account: bool,
|
|
enabled: bool,
|
|
) -> Result<Option<CyberAccessProgram>, String> {
|
|
if !eligible_account {
|
|
return if enabled {
|
|
Err("Daybreak requires the OpenAI provider with either ChatGPT sign-in or an API key with Daybreak support enabled. Turn it off to continue.".into())
|
|
} else {
|
|
Ok(None)
|
|
};
|
|
}
|
|
let programs = models
|
|
.iter()
|
|
.find(|entry| entry.model == model)
|
|
.and_then(|entry| entry.available_access_programs.as_ref())
|
|
.filter(|programs| !programs.cyber.is_empty());
|
|
let Some(programs) = programs else {
|
|
// Missing discovery metadata preserves the server's automatic treatment.
|
|
return Ok(None);
|
|
};
|
|
if enabled {
|
|
programs
|
|
.daybreak()
|
|
.map(Some)
|
|
.ok_or_else(|| format!("Daybreak support for model {model} could not be confirmed by the connected server. Use /daybreak to turn it off, or choose a compatible model and server."))
|
|
} else {
|
|
Ok(programs.standard())
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
pub(crate) enum Notice {
|
|
Apply,
|
|
Astra,
|
|
Disabled,
|
|
Enabled,
|
|
}
|
|
|
|
pub(crate) fn notice_for_setting(
|
|
models: &[ModelPreset],
|
|
model: &str,
|
|
enabled: bool,
|
|
can_enable_daybreak: bool,
|
|
) -> Notice {
|
|
if enabled {
|
|
return Notice::Enabled;
|
|
}
|
|
if can_enable_daybreak {
|
|
let programs = models
|
|
.iter()
|
|
.find(|entry| entry.model == model)
|
|
.and_then(|entry| entry.available_access_programs.as_ref());
|
|
if matches!(model, "gpt-6-astra" | "gpt-6-astra-wm")
|
|
&& programs.is_some_and(|programs| {
|
|
programs.cyber.contains(&CyberAccessProgram::Standard)
|
|
&& programs.daybreak().is_none()
|
|
})
|
|
{
|
|
return Notice::Astra;
|
|
}
|
|
if programs.and_then(ModelAccessPrograms::daybreak).is_some() {
|
|
return Notice::Disabled;
|
|
}
|
|
}
|
|
Notice::Apply
|
|
}
|
|
|
|
pub(crate) fn available(models: &[ModelPreset]) -> bool {
|
|
models.iter().any(|model| {
|
|
model
|
|
.available_access_programs
|
|
.as_ref()
|
|
.and_then(codex_protocol::openai_models::ModelAccessPrograms::daybreak)
|
|
.is_some()
|
|
})
|
|
}
|
|
|
|
/// Missing or empty program lists do not establish that the account lacks access.
|
|
pub(crate) fn availability(models: &[ModelPreset]) -> Option<bool> {
|
|
if available(models) {
|
|
return Some(true);
|
|
}
|
|
if models.is_empty() {
|
|
return None;
|
|
}
|
|
models
|
|
.iter()
|
|
.all(|model| {
|
|
model
|
|
.available_access_programs
|
|
.as_ref()
|
|
.is_some_and(|programs| !programs.cyber.is_empty())
|
|
})
|
|
.then_some(false)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
#[path = "daybreak_tests.rs"]
|
|
mod tests;
|