Enable remote compaction for Amazon Bedrock (#36981)

## What changed

- Add provider-owned remote compaction capabilities for unsupported, v1, and v2 protocols.
- Mark Amazon Bedrock as v1-only so manual and automatic compaction use `/v1/responses/compact`, even when the v2 feature is enabled.
- Preserve v2 support for OpenAI and Azure Responses providers and local compaction for unsupported providers.

## Testing

- Cover Amazon Bedrock manual and automatic remote compaction, including endpoint selection, authentication headers, model selection, and reuse of the compacted summary.

GitOrigin-RevId: d58093178605d1f8155b93d9a161408177f6ac72
This commit is contained in:
rka-oai authored and copyberry committed 2026-08-04 22:07:56 +00:00
1 parent e1f39b5f5b
commit b9ba969f39
10 files changed
+277 -156

No files matched your search

+64
View File
@@ -7,6 +7,7 @@ use std::sync::Arc;
use codex_api::ApiError;
use codex_api::Provider;
use codex_api::SharedAuthProvider;
use codex_api::is_azure_responses_provider;
use codex_login::AuthManager;
use codex_login::CodexAuth;
use codex_model_provider_info::ModelProviderInfo;
@@ -25,6 +26,17 @@ use crate::auth::resolve_provider_auth;
use crate::auth::resolve_provider_auth_for_scope;
use crate::models_endpoint::OpenAiModelsEndpoint;
/// Remote context-compaction protocols supported by a model provider.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RemoteCompactionSupport {
/// The provider does not support remote compaction.
Unsupported,
/// The provider supports only the dedicated `/v1/responses/compact` endpoint.
V1,
/// The provider supports both the dedicated endpoint and `compaction_trigger` items.
V2,
}
/// Optional provider-backed features that Codex may expose at runtime.
///
/// These capabilities are a provider-owned upper bound. Callers can disable
@@ -36,6 +48,7 @@ pub struct ProviderCapabilities {
pub image_generation: bool,
pub web_search: bool,
pub external_web_access: bool,
pub remote_compaction: RemoteCompactionSupport,
}
impl Default for ProviderCapabilities {
@@ -45,6 +58,7 @@ impl Default for ProviderCapabilities {
image_generation: true,
web_search: true,
external_web_access: true,
remote_compaction: RemoteCompactionSupport::V2,
}
}
}
@@ -264,6 +278,21 @@ impl ModelProvider for ConfiguredModelProvider {
&self.info
}
fn capabilities(&self) -> ProviderCapabilities {
let remote_compaction = if self.info.is_openai()
|| is_azure_responses_provider(&self.info.name, self.info.base_url.as_deref())
{
RemoteCompactionSupport::V2
} else {
RemoteCompactionSupport::Unsupported
};
ProviderCapabilities {
remote_compaction,
..ProviderCapabilities::default()
}
}
fn auth_manager(&self) -> Option<Arc<AuthManager>> {
self.auth_manager.clone()
}
@@ -508,6 +537,41 @@ mod tests {
assert_eq!(provider.capabilities(), ProviderCapabilities::default());
}
#[test]
fn configured_provider_remote_compaction_matches_provider_support() {
let cases = [
(
ModelProviderInfo::create_openai_provider(/*base_url*/ None),
RemoteCompactionSupport::V2,
),
(
ModelProviderInfo {
name: "Azure".to_string(),
base_url: Some("https://example.com/openai".to_string()),
..ModelProviderInfo::default()
},
RemoteCompactionSupport::V2,
),
(
ModelProviderInfo {
name: "Custom".to_string(),
base_url: Some("https://example.openai.azure.com/openai/v1".to_string()),
..ModelProviderInfo::default()
},
RemoteCompactionSupport::V2,
),
(
provider_for("https://example.test/v1".to_string()),
RemoteCompactionSupport::Unsupported,
),
];
for (provider_info, expected) in cases {
let provider = create_model_provider(provider_info, /*auth_manager*/ None);
assert_eq!(provider.capabilities().remote_compaction, expected);
}
}
#[test]
fn configured_provider_uses_default_approval_review_preferred_model() {
let provider = create_model_provider(