mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
[codex] Remove async_trait from first-party code (#27475)
## Why First-party async traits should expose their `Send` contracts explicitly without requiring `async_trait`. This completes the migration pattern established in #27303 and #27304. ## What changed - Replaced the remaining first-party `async_trait` traits with native return-position `impl Future + Send` where statically dispatched and explicit boxed `Send` futures where object safety is required. - Kept implementations behavior-preserving, outlining existing async bodies into inherent methods where that keeps the diff reviewable. - Removed all direct first-party `async-trait` dependencies and the workspace dependency declaration. - Added a cargo-deny policy that permits `async-trait` only through the remaining transitive wrapper crates. - Updated `rand` from 0.8.5 to 0.8.6 to resolve RUSTSEC-2026-0097 and keep the full cargo-deny check passing. ## Validation - `just test -p codex-exec-server`: 216 passed, 2 skipped. - `just test -p codex-model-provider`: 39 passed. - `just test -p codex-core` and `just test`: changed tests passed; remaining failures are environment-sensitive suites unrelated to this migration. - `cargo deny check` - `just fix` - `just fmt` - `cargo shear` - `just bazel-lock-check`
This commit is contained in:
@@ -34,6 +34,7 @@ pub use mitm_hook::MitmHookMatchConfig;
|
||||
pub use network_policy::NetworkDecision;
|
||||
pub use network_policy::NetworkDecisionSource;
|
||||
pub use network_policy::NetworkPolicyDecider;
|
||||
pub use network_policy::NetworkPolicyDeciderFuture;
|
||||
pub use network_policy::NetworkPolicyDecision;
|
||||
pub use network_policy::NetworkPolicyRequest;
|
||||
pub use network_policy::NetworkPolicyRequestArgs;
|
||||
@@ -59,7 +60,9 @@ pub use proxy::proxy_url_env_value;
|
||||
pub use runtime::BlockedRequest;
|
||||
pub use runtime::BlockedRequestArgs;
|
||||
pub use runtime::BlockedRequestObserver;
|
||||
pub use runtime::BlockedRequestObserverFuture;
|
||||
pub use runtime::ConfigReloader;
|
||||
pub use runtime::ConfigReloaderFuture;
|
||||
pub use runtime::ConfigState;
|
||||
pub use runtime::NetworkProxyState;
|
||||
pub use state::NetworkProxyAuditMetadata;
|
||||
|
||||
@@ -3,10 +3,10 @@ use crate::runtime::HostBlockDecision;
|
||||
use crate::runtime::HostBlockReason;
|
||||
use crate::state::NetworkProxyState;
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use chrono::SecondsFormat;
|
||||
use chrono::Utc;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
||||
const AUDIT_TARGET: &str = "codex_otel.network_proxy";
|
||||
@@ -263,26 +263,26 @@ fn audit_timestamp() -> String {
|
||||
/// If `command` or `exec_policy_hint` is provided, callers can map exec-policy
|
||||
/// approvals to network access (e.g., allow all requests for commands matching
|
||||
/// approved prefixes like `curl *`).
|
||||
#[async_trait]
|
||||
pub trait NetworkPolicyDecider: Send + Sync + 'static {
|
||||
async fn decide(&self, req: NetworkPolicyRequest) -> NetworkDecision;
|
||||
fn decide(&self, req: NetworkPolicyRequest) -> NetworkPolicyDeciderFuture<'_>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub type NetworkPolicyDeciderFuture<'a> =
|
||||
Pin<Box<dyn Future<Output = NetworkDecision> + Send + 'a>>;
|
||||
|
||||
impl<D: NetworkPolicyDecider + ?Sized> NetworkPolicyDecider for Arc<D> {
|
||||
async fn decide(&self, req: NetworkPolicyRequest) -> NetworkDecision {
|
||||
(**self).decide(req).await
|
||||
fn decide(&self, req: NetworkPolicyRequest) -> NetworkPolicyDeciderFuture<'_> {
|
||||
Box::pin(async move { (**self).decide(req).await })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<F, Fut> NetworkPolicyDecider for F
|
||||
where
|
||||
F: Fn(NetworkPolicyRequest) -> Fut + Send + Sync + 'static,
|
||||
Fut: Future<Output = NetworkDecision> + Send,
|
||||
Fut: Future<Output = NetworkDecision> + Send + 'static,
|
||||
{
|
||||
async fn decide(&self, req: NetworkPolicyRequest) -> NetworkDecision {
|
||||
(self)(req).await
|
||||
fn decide(&self, req: NetworkPolicyRequest) -> NetworkPolicyDeciderFuture<'_> {
|
||||
Box::pin((self)(req))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,6 +541,7 @@ mod tests {
|
||||
use crate::reasons::REASON_NOT_ALLOWED;
|
||||
use crate::reasons::REASON_NOT_ALLOWED_LOCAL;
|
||||
use crate::runtime::ConfigReloader;
|
||||
use crate::runtime::ConfigReloaderFuture;
|
||||
use crate::runtime::ConfigState;
|
||||
use crate::runtime::NetworkProxyAuditMetadata;
|
||||
use crate::state::NetworkProxyConstraints;
|
||||
@@ -560,14 +561,13 @@ mod tests {
|
||||
state: ConfigState,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ConfigReloader for StaticReloader {
|
||||
async fn maybe_reload(&self) -> anyhow::Result<Option<ConfigState>> {
|
||||
Ok(None)
|
||||
fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option<ConfigState>> {
|
||||
Box::pin(async { Ok(None) })
|
||||
}
|
||||
|
||||
async fn reload_now(&self) -> anyhow::Result<ConfigState> {
|
||||
Ok(self.state.clone())
|
||||
fn reload_now(&self) -> ConfigReloaderFuture<'_, ConfigState> {
|
||||
Box::pin(async { Ok(self.state.clone()) })
|
||||
}
|
||||
|
||||
fn source_label(&self) -> String {
|
||||
|
||||
@@ -20,7 +20,6 @@ use crate::state::build_config_state;
|
||||
use crate::state::validate_policy_against_constraints;
|
||||
use anyhow::Context;
|
||||
use anyhow::Result;
|
||||
use async_trait::async_trait;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use globset::GlobSet;
|
||||
use serde::Serialize;
|
||||
@@ -30,6 +29,7 @@ use std::future::Future;
|
||||
use std::net::IpAddr;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use time::OffsetDateTime;
|
||||
@@ -168,38 +168,38 @@ pub struct ConfigState {
|
||||
pub blocked_total: u64,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait ConfigReloader: Send + Sync {
|
||||
/// Human-readable description of where config is loaded from, for logs.
|
||||
fn source_label(&self) -> String;
|
||||
|
||||
/// Return a freshly loaded state if a reload is needed; otherwise, return `None`.
|
||||
async fn maybe_reload(&self) -> Result<Option<ConfigState>>;
|
||||
fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option<ConfigState>>;
|
||||
|
||||
/// Force a reload, regardless of whether a change was detected.
|
||||
async fn reload_now(&self) -> Result<ConfigState>;
|
||||
fn reload_now(&self) -> ConfigReloaderFuture<'_, ConfigState>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub type ConfigReloaderFuture<'a, T> = Pin<Box<dyn Future<Output = Result<T>> + Send + 'a>>;
|
||||
|
||||
pub trait BlockedRequestObserver: Send + Sync + 'static {
|
||||
async fn on_blocked_request(&self, request: BlockedRequest);
|
||||
fn on_blocked_request(&self, request: BlockedRequest) -> BlockedRequestObserverFuture<'_>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub type BlockedRequestObserverFuture<'a> = Pin<Box<dyn Future<Output = ()> + Send + 'a>>;
|
||||
|
||||
impl<O: BlockedRequestObserver + ?Sized> BlockedRequestObserver for Arc<O> {
|
||||
async fn on_blocked_request(&self, request: BlockedRequest) {
|
||||
(**self).on_blocked_request(request).await
|
||||
fn on_blocked_request(&self, request: BlockedRequest) -> BlockedRequestObserverFuture<'_> {
|
||||
Box::pin(async move { (**self).on_blocked_request(request).await })
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<F, Fut> BlockedRequestObserver for F
|
||||
where
|
||||
F: Fn(BlockedRequest) -> Fut + Send + Sync + 'static,
|
||||
Fut: Future<Output = ()> + Send,
|
||||
Fut: Future<Output = ()> + Send + 'static,
|
||||
{
|
||||
async fn on_blocked_request(&self, request: BlockedRequest) {
|
||||
(self)(request).await
|
||||
fn on_blocked_request(&self, request: BlockedRequest) -> BlockedRequestObserverFuture<'_> {
|
||||
Box::pin((self)(request))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -891,18 +891,17 @@ pub(crate) fn network_proxy_state_for_policy(
|
||||
struct NoopReloader;
|
||||
|
||||
#[cfg(test)]
|
||||
#[async_trait]
|
||||
impl ConfigReloader for NoopReloader {
|
||||
fn source_label(&self) -> String {
|
||||
"test config state".to_string()
|
||||
}
|
||||
|
||||
async fn maybe_reload(&self) -> Result<Option<ConfigState>> {
|
||||
Ok(None)
|
||||
fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option<ConfigState>> {
|
||||
Box::pin(async { Ok(None) })
|
||||
}
|
||||
|
||||
async fn reload_now(&self) -> Result<ConfigState> {
|
||||
Err(anyhow::anyhow!("force reload is not supported in tests"))
|
||||
fn reload_now(&self) -> ConfigReloaderFuture<'_, ConfigState> {
|
||||
Box::pin(async { Err(anyhow::anyhow!("force reload is not supported in tests")) })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -714,10 +714,10 @@ mod tests {
|
||||
use crate::network_policy::test_support::capture_events;
|
||||
use crate::network_policy::test_support::find_event_by_name;
|
||||
use crate::runtime::ConfigReloader;
|
||||
use crate::runtime::ConfigReloaderFuture;
|
||||
use crate::runtime::ConfigState;
|
||||
use crate::state::NetworkProxyConstraints;
|
||||
use crate::state::build_config_state;
|
||||
use async_trait::async_trait;
|
||||
use pretty_assertions::assert_eq;
|
||||
use rama_core::extensions::Extensions;
|
||||
use rama_core::extensions::ExtensionsMut;
|
||||
@@ -738,14 +738,13 @@ mod tests {
|
||||
state: ConfigState,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl ConfigReloader for StaticReloader {
|
||||
async fn maybe_reload(&self) -> anyhow::Result<Option<ConfigState>> {
|
||||
Ok(None)
|
||||
fn maybe_reload(&self) -> ConfigReloaderFuture<'_, Option<ConfigState>> {
|
||||
Box::pin(async { Ok(None) })
|
||||
}
|
||||
|
||||
async fn reload_now(&self) -> anyhow::Result<ConfigState> {
|
||||
Ok(self.state.clone())
|
||||
fn reload_now(&self) -> ConfigReloaderFuture<'_, ConfigState> {
|
||||
Box::pin(async { Ok(self.state.clone()) })
|
||||
}
|
||||
|
||||
fn source_label(&self) -> String {
|
||||
|
||||
Reference in New Issue
Block a user