Remove Guardian subagent-spawner plumbing (#45491)

## What changed

- Remove `AgentSpawner` and `AgentSpawnFuture` from the extension API, along with the Guardian wrapper, thread lifecycle context, and app-server injection plumbing.
- Define `InternalSessionSpawnFuture` directly as a boxed future instead of aliasing `AgentSpawnFuture`.
- Raise the workspace `rustls` minimum version to `0.23.45`.

GitOrigin-RevId: b7319dee41bfb869479afeb7555a6f050c4d00a5
This commit is contained in:
felixxia-oai
2026-09-14 18:56:43 +00:00
committed by copyberry
parent e5a2094817
commit f2d9bccbde
10 changed files with 39 additions and 218 deletions
@@ -1,38 +0,0 @@
use std::future::Future;
use std::pin::Pin;
use codex_protocol::ThreadId;
/// Future returned by one injected subagent-spawn helper.
pub type AgentSpawnFuture<'a, T, E> = Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>>;
/// Constructor-injected host helper for extensions that need to spawn subagents.
///
/// The extension owns the request shape and resulting handle types. The host
/// provides the implementation when it constructs the extension.
pub trait AgentSpawner<R>: Send + Sync {
type Spawned;
type Error;
fn spawn_subagent<'a>(
&'a self,
forked_from_thread_id: ThreadId,
request: R,
) -> AgentSpawnFuture<'a, Self::Spawned, Self::Error>;
}
impl<R, S, E, F> AgentSpawner<R> for F
where
F: Fn(ThreadId, R) -> AgentSpawnFuture<'static, S, E> + Send + Sync,
{
type Spawned = S;
type Error = E;
fn spawn_subagent<'a>(
&'a self,
forked_from_thread_id: ThreadId,
request: R,
) -> AgentSpawnFuture<'a, Self::Spawned, Self::Error> {
self(forked_from_thread_id, request)
}
}
@@ -1,9 +1,11 @@
use std::future::Future;
use std::pin::Pin;
use codex_protocol::ThreadId;
use super::agent::AgentSpawnFuture;
/// Future returned by one host-owned internal-session spawning request.
pub type InternalSessionSpawnFuture<'a, T, E> = AgentSpawnFuture<'a, T, E>;
pub type InternalSessionSpawnFuture<'a, T, E> =
Pin<Box<dyn Future<Output = Result<T, E>> + Send + 'a>>;
/// Constructor-injected host helper for extensions that need private internal sessions.
///
@@ -1,12 +1,9 @@
mod agent;
mod conversation_history;
mod events;
mod internal_session;
mod metrics;
mod response_items;
pub use agent::AgentSpawnFuture;
pub use agent::AgentSpawner;
pub use conversation_history::ConversationHistorySnapshot;
pub use events::ExtensionEventSink;
pub use events::ExtensionWarning;
-2
View File
@@ -8,8 +8,6 @@ mod user_instructions;
pub use session_isolation::SessionIsolation;
pub use capabilities::AgentSpawnFuture;
pub use capabilities::AgentSpawner;
pub use capabilities::ConversationHistorySnapshot;
pub use capabilities::ExtensionEventSink;
pub use capabilities::ExtensionMetrics;
@@ -1,8 +1,6 @@
use std::sync::Arc;
use std::sync::Mutex;
use codex_extension_api::AgentSpawnFuture;
use codex_extension_api::AgentSpawner;
use codex_extension_api::InternalSessionSpawnFuture;
use codex_extension_api::InternalSessionSpawner;
use codex_extension_api::NoopResponseItemInjector;
@@ -30,33 +28,6 @@ async fn noop_response_item_injector_returns_original_items() {
assert_eq!(returned_items, items);
}
#[tokio::test]
async fn closure_agent_spawner_forwards_arguments_and_result() {
let calls = Arc::new(Mutex::new(Vec::new()));
let recorded_calls = Arc::clone(&calls);
let spawner = move |thread_id: ThreadId,
request: String|
-> AgentSpawnFuture<'static, usize, &'static str> {
recorded_calls
.lock()
.expect("agent spawn calls lock")
.push((thread_id, request.clone()));
Box::pin(async move { Ok(request.len()) })
};
let thread_id =
ThreadId::from_string("11111111-1111-4111-8111-111111111111").expect("valid thread id");
let spawned = spawner
.spawn_subagent(thread_id, "delegate this".to_string())
.await;
assert_eq!(spawned, Ok(13));
assert_eq!(
calls.lock().expect("agent spawn calls lock").as_slice(),
[(thread_id, "delegate this".to_string())]
);
}
#[tokio::test]
async fn closure_internal_session_spawner_forwards_arguments_and_result() {
let calls = Arc::new(Mutex::new(Vec::new()));
+2 -71
View File
@@ -3,89 +3,20 @@ use std::sync::Weak;
use codex_core::ThreadManager;
use codex_core::config::Config;
use codex_extension_api::AgentSpawnFuture;
use codex_extension_api::AgentSpawner;
use codex_extension_api::ExtensionFuture;
use codex_extension_api::ExtensionRegistryBuilder;
use codex_extension_api::ThreadLifecycleContributor;
use codex_extension_api::ThreadStartInput;
use codex_login::AuthManager;
use codex_protocol::ThreadId;
mod async_scorer;
mod sync_reviewer;
pub use sync_reviewer::GuardianExtension as GuardianReviewerExtension;
/// Guardian extension dependencies supplied by the host at construction time.
#[derive(Clone, Debug)]
pub struct GuardianExtension<S> {
agent_spawner: S,
}
impl<S> GuardianExtension<S> {
/// Creates a guardian extension with its host-provided agent spawn helper.
pub fn new(agent_spawner: S) -> Self {
Self { agent_spawner }
}
/// Delegates one guardian-owned subagent spawn request to the host helper.
pub fn spawn_subagent<'a, R>(
&'a self,
forked_from_thread_id: ThreadId,
request: R,
) -> AgentSpawnFuture<'a, <S as AgentSpawner<R>>::Spawned, <S as AgentSpawner<R>>::Error>
where
S: AgentSpawner<R>,
{
self.agent_spawner
.spawn_subagent(forked_from_thread_id, request)
}
}
/// Thread-local guardian state captured when the host starts a thread.
#[derive(Clone, Copy, Debug)]
pub struct GuardianThreadContext {
forked_from_thread_id: ThreadId,
}
impl GuardianThreadContext {
/// Returns the thread that future guardian subagents should fork from by default.
pub fn forked_from_thread_id(&self) -> ThreadId {
self.forked_from_thread_id
}
}
impl<S> ThreadLifecycleContributor<Config> for GuardianExtension<S>
where
S: Send + Sync,
{
fn on_thread_start<'a>(
&'a self,
input: ThreadStartInput<'a, Config>,
) -> ExtensionFuture<'a, ()> {
Box::pin(async move {
let Ok(forked_from_thread_id) = ThreadId::from_string(input.thread_store.level_id())
else {
return;
};
input.thread_store.insert(GuardianThreadContext {
forked_from_thread_id,
});
})
}
}
/// Installs the guardian contributors into the extension registry.
pub fn install<S>(
pub fn install(
registry: &mut ExtensionRegistryBuilder<Config>,
agent_spawner: S,
auth_manager: Arc<AuthManager>,
thread_manager: Weak<ThreadManager>,
) where
S: Send + Sync + 'static,
{
registry.thread_lifecycle_contributor(Arc::new(GuardianExtension::new(agent_spawner)));
) {
async_scorer::install(registry, auth_manager, thread_manager.clone());
sync_reviewer::install(registry, thread_manager);
}