fix(codex): serve versioned dynamic model catalogs

This commit is contained in:
zhefox
2026-08-14 18:41:44 +08:00
parent a1d64e5239
commit 810c3dfe2b
39 changed files with 6147 additions and 362 deletions
+10
View File
@@ -480,6 +480,16 @@ impl AppState {
.map_err(|err| GatewayError::Internal(err.to_string()))
}
pub(crate) async fn list_provider_catalog_keys_by_ids_strong(
&self,
key_ids: &[String],
) -> Result<Vec<provider_catalog::StoredProviderCatalogKey>, GatewayError> {
self.data
.list_provider_catalog_keys_by_ids_strong(key_ids)
.await
.map_err(|err| GatewayError::Internal(err.to_string()))
}
pub(crate) async fn list_provider_catalog_key_page(
&self,
query: &provider_catalog::ProviderCatalogKeyListQuery,
+105 -2
View File
@@ -25,7 +25,7 @@ use tracing::{debug, warn};
use super::{AppState, GatewayError};
use crate::clock::current_unix_secs;
use crate::model_fetch::ModelFetchRuntimeState;
use crate::model_fetch::{CodexCatalogRuntime, ModelFetchRuntimeState};
use crate::provider_transport::{GatewayProviderTransportSnapshot, LocalResolvedOAuthRequestAuth};
use crate::request_candidate_runtime::{
RequestCandidateRuntimeCapabilityReader, RequestCandidateRuntimeReader,
@@ -34,6 +34,8 @@ use crate::request_candidate_runtime::{
use crate::scheduler::state::SchedulerRuntimeState;
use crate::{execution_runtime, provider_transport};
const MODEL_FETCH_RESPONSE_BODY_LIMIT_BYTES: usize = 8 * 1024 * 1024;
impl AppState {
pub(crate) async fn hydrate_antigravity_project_metadata_for_transport(
&self,
@@ -274,12 +276,90 @@ impl ModelFetchTransportRuntime for AppState {
&self,
plan: &ExecutionPlan,
) -> Result<ExecutionResult, String> {
execution_runtime::execute_execution_runtime_sync_plan(self, None, plan)
let bounded_plan = execution_runtime::transport::with_upstream_response_body_limit(
plan,
MODEL_FETCH_RESPONSE_BODY_LIMIT_BYTES,
);
execution_runtime::execute_execution_runtime_sync_plan(self, None, &bounded_plan)
.await
.map_err(GatewayError::into_message)
}
}
#[async_trait]
impl CodexCatalogRuntime for AppState {
fn codex_catalog_runtime_state(&self) -> &aether_runtime_state::RuntimeState {
self.runtime_state.as_ref()
}
async fn read_codex_catalog_transport_snapshot(
&self,
provider_id: &str,
endpoint_id: &str,
key_id: &str,
) -> Result<Option<GatewayProviderTransportSnapshot>, String> {
self.read_provider_transport_snapshot(provider_id, endpoint_id, key_id)
.await
.map_err(GatewayError::into_message)
}
async fn read_codex_catalog_credential_scope_strong(
&self,
provider_id: &str,
key_id: &str,
) -> Result<Option<String>, String> {
let Some(key) = self
.list_provider_catalog_keys_by_ids_strong(&[key_id.to_string()])
.await
.map_err(GatewayError::into_message)?
.into_iter()
.find(|key| key.id == key_id && key.provider_id == provider_id && key.is_active)
else {
return Ok(None);
};
if let Some(scope) =
crate::model_fetch::codex_catalog_credential_scope_from_stored_key(&key, None, None)
{
return Ok(Some(scope));
}
let decrypted_auth_config = match key.encrypted_auth_config.as_deref() {
Some(ciphertext) => Some(
crate::handlers::shared::decrypt_catalog_secret_with_fallbacks(
self.encryption_key(),
ciphertext,
)
.ok_or_else(|| {
"Codex catalog auth config could not be verified for credential fencing"
.to_string()
})?,
),
None => None,
};
let decrypted_api_key = match key.encrypted_api_key.as_deref() {
Some(ciphertext) => Some(
crate::handlers::shared::decrypt_catalog_secret_with_fallbacks(
self.encryption_key(),
ciphertext,
)
.ok_or_else(|| {
"Codex catalog API key could not be verified for credential fencing".to_string()
})?,
),
None => None,
};
Ok(
crate::model_fetch::codex_catalog_credential_scope_from_stored_key(
&key,
decrypted_auth_config.as_deref(),
decrypted_api_key.as_deref(),
),
)
}
}
#[async_trait]
impl ModelFetchRuntimeState for AppState {
fn has_provider_catalog_data_reader(&self) -> bool {
@@ -320,6 +400,29 @@ impl ModelFetchRuntimeState for AppState {
execution_runtime::execute_execution_runtime_sync_plan(self, None, plan).await
}
async fn read_recent_codex_catalog_client_version(
&self,
provider_id: &str,
key_id: &str,
) -> Option<String> {
let credential_scope =
<AppState as CodexCatalogRuntime>::read_codex_catalog_credential_scope_strong(
self,
provider_id,
key_id,
)
.await
.ok()
.flatten()?;
crate::model_fetch::read_recent_codex_catalog_client_version(
self.runtime_state.as_ref(),
provider_id,
key_id,
&credential_scope,
)
.await
}
async fn update_provider_catalog_key_model_fetch_state(
&self,
key_id: &str,