ext/guardian/src/lib.rs
77 lines
use std::sync::Arc;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_protocol::ThreadId;/// 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>(registry: &mut ExtensionRegistryBuilder<Config>, agent_spawner: S)where S: Send + Sync + 'static,{ registry.thread_lifecycle_contributor(Arc::new(GuardianExtension::new(agent_spawner)));}