mirror of
https://github.com/openai/codex.git
synced 2026-08-23 13:09:46 +00:00
[codex] allow CCA image generation and web search extensions (#29909)
## Summary - allow the standalone image-generation and web-search extensions for the actor-authorized provider shape used by CCA - preserve builtin `image_generation` and `web_search` for older models and existing flows - keep ordinary non-OpenAI providers excluded from both extensions - remove only the image extension local managed-AuthManager requirement that CCA cannot satisfy - share actor-authorization detection through `ModelProviderInfo` - keep Core tests focused on routing behavior and cover header-shape edge cases in `model-provider-info` - add a Responses Lite regression that verifies both `image_gen.imagegen` and `web.run` ## Why CCA uses a provider named `local` with `requires_openai_auth: false` and a non-empty `x-openai-actor-authorization` header. Core accepts that provider shape, but both extension provider-name gates rejected it; image generation additionally required a Codex-managed login. The standalone paths must coexist with existing builtin tools. New Responses Lite models can receive `image_gen.imagegen` and `web.run`, while older models continue using builtin tools. ## Impact This enables both standalone extensions for CCA once installed downstream, without removing or changing builtin-tool compatibility for older models. ## Validation - `just test -p codex-core responses_lite_exposes_standalone_tools_for_actor_authorized_provider` - `just test -p codex-core responses_lite_uses_standalone_web_search_and_image_generation` - `just test -p codex-core hosted_tools_follow_provider_auth_model_and_config_gates` - `just test -p codex-image-generation-extension` - `just test -p codex-web-search-extension` - `just test -p codex-model-provider-info` - `just fmt` - `git diff --check`
This commit is contained in:
@@ -33,6 +33,7 @@ const MAX_STREAM_MAX_RETRIES: u64 = 100;
|
||||
const MAX_REQUEST_MAX_RETRIES: u64 = 100;
|
||||
|
||||
const OPENAI_PROVIDER_NAME: &str = "OpenAI";
|
||||
const OPENAI_ACTOR_AUTHORIZATION_HEADER: &str = "x-openai-actor-authorization";
|
||||
pub const OPENAI_PROVIDER_ID: &str = "openai";
|
||||
pub const CHATGPT_CODEX_BASE_URL: &str = "https://chatgpt.com/backend-api/codex";
|
||||
const AMAZON_BEDROCK_PROVIDER_NAME: &str = "Amazon Bedrock";
|
||||
@@ -392,6 +393,16 @@ impl ModelProviderInfo {
|
||||
self.name == OPENAI_PROVIDER_NAME
|
||||
}
|
||||
|
||||
pub fn uses_openai_actor_authorization(&self) -> bool {
|
||||
!self.requires_openai_auth
|
||||
&& self.http_headers.as_ref().is_some_and(|headers| {
|
||||
headers.iter().any(|(name, value)| {
|
||||
name.eq_ignore_ascii_case(OPENAI_ACTOR_AUTHORIZATION_HEADER)
|
||||
&& !value.trim().is_empty()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_amazon_bedrock(&self) -> bool {
|
||||
self.name == AMAZON_BEDROCK_PROVIDER_NAME
|
||||
}
|
||||
|
||||
@@ -198,6 +198,31 @@ fn test_supports_remote_compaction_for_non_openai_non_azure_provider() {
|
||||
assert!(!provider.supports_remote_compaction());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_uses_openai_actor_authorization() {
|
||||
let mut provider = ModelProviderInfo {
|
||||
http_headers: Some(maplit::hashmap! {
|
||||
"X-OpenAI-Actor-Authorization".to_string() => "actor-token".to_string(),
|
||||
}),
|
||||
..ModelProviderInfo::default()
|
||||
};
|
||||
assert!(provider.uses_openai_actor_authorization());
|
||||
|
||||
provider.http_headers = None;
|
||||
assert!(!provider.uses_openai_actor_authorization());
|
||||
|
||||
provider.http_headers = Some(maplit::hashmap! {
|
||||
OPENAI_ACTOR_AUTHORIZATION_HEADER.to_string() => " ".to_string(),
|
||||
});
|
||||
assert!(!provider.uses_openai_actor_authorization());
|
||||
|
||||
provider.http_headers = Some(maplit::hashmap! {
|
||||
OPENAI_ACTOR_AUTHORIZATION_HEADER.to_string() => "actor-token".to_string(),
|
||||
});
|
||||
provider.requires_openai_auth = true;
|
||||
assert!(!provider.uses_openai_actor_authorization());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deserialize_provider_auth_config_defaults() {
|
||||
let base_dir = tempdir().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user