mirror of
https://github.com/openai/codex.git
synced 2026-10-20 17:38:45 +00:00
Enable Cyber access programs for API-key sessions by default (#53717)
## 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
This commit is contained in:
@@ -9,9 +9,12 @@ use codex_app_server_protocol::GetAccountParams;
|
||||
use codex_app_server_protocol::GetAccountResponse;
|
||||
use codex_app_server_protocol::ModelListParams;
|
||||
use codex_app_server_protocol::ModelListResponse;
|
||||
use codex_features::Feature;
|
||||
use codex_features::Features;
|
||||
use codex_protocol::openai_models::ModelAccessPrograms;
|
||||
|
||||
pub(crate) async fn program_for_turn(
|
||||
features: &Features,
|
||||
client: &InProcessAppServerClient,
|
||||
request_ids: &mut RequestIdSequencer,
|
||||
model: &str,
|
||||
@@ -25,8 +28,11 @@ pub(crate) async fn program_for_turn(
|
||||
|
||||
if enabled {
|
||||
anyhow::ensure!(
|
||||
has_chatgpt_account(client, request_ids).await?,
|
||||
"Daybreak requires a signed-in ChatGPT account"
|
||||
matches!(
|
||||
read_account(client, request_ids).await?,
|
||||
Some(Account::Chatgpt { .. } | Account::ApiKey { .. })
|
||||
),
|
||||
"Daybreak requires a signed-in ChatGPT account or an OpenAI API key"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,44 +49,48 @@ pub(crate) async fn program_for_turn(
|
||||
})
|
||||
.await;
|
||||
let Ok(result) = result else {
|
||||
anyhow::ensure!(!enabled, "Daybreak availability could not be determined");
|
||||
return Ok(None);
|
||||
};
|
||||
if let Some(selected) = result.data.into_iter().find(|entry| entry.model == model) {
|
||||
let programs = selected
|
||||
.available_access_programs
|
||||
.map(ModelAccessPrograms::from);
|
||||
.map(ModelAccessPrograms::from)
|
||||
.filter(|programs| !programs.cyber.is_empty());
|
||||
let Some(programs) = programs else {
|
||||
return Ok(None);
|
||||
};
|
||||
if enabled {
|
||||
return programs
|
||||
.and_then(|programs| programs.daybreak())
|
||||
.daybreak()
|
||||
.map(|program| Some(program.into()))
|
||||
.ok_or_else(|| anyhow::anyhow!("Daybreak is unavailable for model {model}; turn it off or choose a compatible model"));
|
||||
}
|
||||
let Some(standard) = programs.and_then(|programs| programs.standard()) else {
|
||||
let Some(standard) = programs.standard() else {
|
||||
return Ok(None);
|
||||
};
|
||||
return Ok(has_chatgpt_account(client, request_ids)
|
||||
.await
|
||||
.unwrap_or(false)
|
||||
.then_some(standard.into()));
|
||||
let eligible = match read_account(client, request_ids).await.unwrap_or(None) {
|
||||
Some(Account::Chatgpt { .. }) => true,
|
||||
Some(Account::ApiKey { .. }) => {
|
||||
features.enabled(Feature::ApiKeyCyberAccessPrograms)
|
||||
}
|
||||
Some(Account::AmazonBedrock { .. }) | None => false,
|
||||
};
|
||||
return Ok(eligible.then_some(standard.into()));
|
||||
}
|
||||
match result.next_cursor {
|
||||
Some(next) => cursor = Some(next),
|
||||
None => {
|
||||
anyhow::ensure!(
|
||||
!enabled,
|
||||
"Daybreak availability could not be determined for model {model}"
|
||||
);
|
||||
// Preserve automatic treatment for explicit model IDs absent from the catalog.
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn has_chatgpt_account(
|
||||
async fn read_account(
|
||||
client: &InProcessAppServerClient,
|
||||
request_ids: &mut RequestIdSequencer,
|
||||
) -> anyhow::Result<bool> {
|
||||
) -> anyhow::Result<Option<Account>> {
|
||||
let account = client
|
||||
.request_typed::<GetAccountResponse>(ClientRequest::GetAccount {
|
||||
request_id: request_ids.next(),
|
||||
@@ -92,5 +102,5 @@ async fn has_chatgpt_account(
|
||||
.map_err(|error| {
|
||||
anyhow::anyhow!("Daybreak account availability could not be determined: {error}")
|
||||
})?;
|
||||
Ok(matches!(account.account, Some(Account::Chatgpt { .. })))
|
||||
Ok(account.account)
|
||||
}
|
||||
|
||||
@@ -1215,6 +1215,7 @@ async fn run_exec_session(args: ExecRunArgs) -> anyhow::Result<()> {
|
||||
Some(program) => Some(program),
|
||||
None if config.features.enabled(Feature::CliDaybreak) => {
|
||||
daybreak::program_for_turn(
|
||||
&config.features,
|
||||
&client,
|
||||
&mut request_ids,
|
||||
&session_configured.model,
|
||||
|
||||
Reference in New Issue
Block a user