pub struct ChildSessionAdapter { /* private fields */ }Expand description
Server-side adapter that bridges domain ChildSessionPort to infrastructure.
Holds all shared state needed by SubAgentTool.
Implements the full ChildSessionPort trait with real methods (no stubs).
Implementations§
Source§impl ChildSessionAdapter
impl ChildSessionAdapter
Sourcepub fn new(
session_store: Arc<SessionStoreV2>,
storage: Arc<dyn Storage>,
persistence: Arc<LockedSessionStore>,
scheduler: Arc<SpawnScheduler>,
sessions_cache: SessionCache,
agent_runners: Arc<RwLock<HashMap<String, AgentRunner>>>,
session_event_senders: Arc<RwLock<HashMap<String, Sender<AgentEvent>>>>,
subagent_model_resolver: OptionalSubagentModelResolver,
config: Arc<RwLock<Config>>,
) -> Self
pub fn new( session_store: Arc<SessionStoreV2>, storage: Arc<dyn Storage>, persistence: Arc<LockedSessionStore>, scheduler: Arc<SpawnScheduler>, sessions_cache: SessionCache, agent_runners: Arc<RwLock<HashMap<String, AgentRunner>>>, session_event_senders: Arc<RwLock<HashMap<String, Sender<AgentEvent>>>>, subagent_model_resolver: OptionalSubagentModelResolver, config: Arc<RwLock<Config>>, ) -> Self
Construct an adapter. Public so a self-orchestrating WORKER (Phase 6:
direct nested execution) can build its OWN child-session machinery
against its own store/scheduler — the struct fields are pub(crate), so
out-of-crate callers (the worker binary) go through this constructor.
Sourcepub async fn resolve_subagent_model(
&self,
subagent_type: &str,
) -> Option<ProviderModelRef>
pub async fn resolve_subagent_model( &self, subagent_type: &str, ) -> Option<ProviderModelRef>
Resolve the provider+model ref for a given subagent_type using the configured resolver.
Sourcepub async fn resolve_runtime_metadata(
&self,
subagent_type: &str,
) -> HashMap<String, String>
pub async fn resolve_runtime_metadata( &self, subagent_type: &str, ) -> HashMap<String, String>
Resolve runtime metadata (e.g. external agent routing) for a subagent_type.
Sourcepub async fn register_parent_wait_for_child(
&self,
parent_session_id: &str,
child_session_id: &str,
tool_call_id: Option<&str>,
) -> Result<(), ChildSessionError>
pub async fn register_parent_wait_for_child( &self, parent_session_id: &str, child_session_id: &str, tool_call_id: Option<&str>, ) -> Result<(), ChildSessionError>
Register a durable parent wait for an enqueued child session.
This is intentionally idempotent: repeated registrations for the same child merge into the existing wait set. The child runner owns timeout and liveness; the parent wait timeout is a long lease for observability.
Registrations are coalesced per parent: when several children are
spawned in one round (the LLM issuing multiple SubAgent.create calls
that join_all runs concurrently), the first call to win the per-parent
barrier drains all currently-pending registrations and persists the parent
once, instead of each child triggering its own load+write. Callers whose
child was drained-and-persisted by that holder return without an extra
write — and only after the holder’s write committed, so durability holds.
Sourcepub async fn register_parent_wait_for_children(
&self,
parent_session_id: &str,
child_session_ids: &[String],
policy: ChildWaitPolicy,
) -> Result<usize, ChildSessionError>
pub async fn register_parent_wait_for_children( &self, parent_session_id: &str, child_session_ids: &[String], policy: ChildWaitPolicy, ) -> Result<usize, ChildSessionError>
Explicitly register a parent wait for an arbitrary set of children with a
chosen policy. Used by the SubAgent.wait action (wait on all active
children) and the end-of-turn safety net. A single parent write.
Returns the number of children the wait now covers (0 means there was nothing to wait on and no wait was registered).
Sourcepub async fn active_child_ids(&self, parent_session_id: &str) -> Vec<String>
pub async fn active_child_ids(&self, parent_session_id: &str) -> Vec<String>
The parent’s currently-active (non-terminal) children, derived from the session index (single source of truth).
Trait Implementations§
Source§impl ChildSessionPort for ChildSessionAdapter
impl ChildSessionPort for ChildSessionAdapter
fn load_root_session<'life0, 'life1, 'async_trait>(
&'life0 self,
root_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<Session, ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn load_child_for_parent<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
child_session_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<Session, ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn save_child_session<'life0, 'life1, 'async_trait>(
&'life0 self,
child: &'life1 mut Session,
) -> Pin<Box<dyn Future<Output = Result<(), ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn is_child_running<'life0, 'life1, 'async_trait>(
&'life0 self,
child_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = bool> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn list_children<'life0, 'life1, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Vec<ChildSessionEntry>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn find_resident_child<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
root_session_id: &'life1 str,
resident_name: &'life2 str,
) -> Pin<Box<dyn Future<Output = Option<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn find_resident_child<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
root_session_id: &'life1 str,
resident_name: &'life2 str,
) -> Pin<Box<dyn Future<Output = Option<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
resident_name, returning its child session id if one exists. Used to
reuse a resident agent for a new task instead of minting a new child.
Index-backed (matches root_session_id + metadata["resident_name"]).fn enqueue_child_run<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
parent: &'life1 Session,
child: &'life2 Session,
) -> Pin<Box<dyn Future<Output = Result<(), ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn cancel_child_run_and_wait<'life0, 'life1, 'async_trait>(
&'life0 self,
child_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Result<(), ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn delete_child_session<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
child_id: &'life2 str,
) -> Pin<Box<dyn Future<Output = Result<DeleteChildResult, ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Source§fn get_child_runner_info<'life0, 'life1, 'async_trait>(
&'life0 self,
child_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<ChildRunnerInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_child_runner_info<'life0, 'life1, 'async_trait>(
&'life0 self,
child_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<ChildRunnerInfo>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn register_parent_wait_for_child<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
child_session_id: &'life2 str,
tool_call_id: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = Result<(), ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
fn register_parent_wait_for_child<'life0, 'life1, 'life2, 'life3, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
child_session_id: &'life2 str,
tool_call_id: Option<&'life3 str>,
) -> Pin<Box<dyn Future<Output = Result<(), ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Source§fn register_parent_wait_for_children<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
child_session_ids: &'life2 [String],
policy: ChildWaitPolicy,
) -> Pin<Box<dyn Future<Output = Result<usize, ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn register_parent_wait_for_children<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
child_session_ids: &'life2 [String],
policy: ChildWaitPolicy,
) -> Pin<Box<dyn Future<Output = Result<usize, ChildSessionError>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
SubAgent.wait action). Returns the number of
children the wait now covers (0 = nothing to wait on).Source§fn active_child_ids<'life0, 'life1, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Vec<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn active_child_ids<'life0, 'life1, 'async_trait>(
&'life0 self,
parent_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = Vec<String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§fn ensure_child_indexed<'life0, 'life1, 'async_trait>(
&'life0 self,
child_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn ensure_child_indexed<'life0, 'life1, 'async_trait>(
&'life0 self,
child_session_id: &'life1 str,
) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Source§impl GuardianSpawner for ChildSessionAdapter
Lets a ChildSessionAdapter act as the engine’s guardian-review spawner.
impl GuardianSpawner for ChildSessionAdapter
Lets a ChildSessionAdapter act as the engine’s guardian-review spawner.
Arc<ChildSessionAdapter> therefore doubles as Arc<dyn GuardianSpawner>
(wired onto AppState), so the terminal gate spawns the read-only reviewer
through the same child-session machinery the SubAgent tool uses — no second
spawn path. The reviewer is a real sub-agent: it fetches the diff and runs
tests itself via its (read-only) toolset.
Source§fn spawn_guardian_review<'life0, 'life1, 'async_trait>(
&'life0 self,
parent_session: &'life1 Session,
review_prompt: String,
model: String,
disabled_tools: Option<BTreeSet<String>>,
) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn spawn_guardian_review<'life0, 'life1, 'async_trait>(
&'life0 self,
parent_session: &'life1 Session,
review_prompt: String,
model: String,
disabled_tools: Option<BTreeSet<String>>,
) -> Pin<Box<dyn Future<Output = Result<String, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
parent_session_id, seeded with
review_prompt, enqueue it to run, and return its session id so the
caller can register a wait on it.Source§impl SubagentResolutionPort for ChildSessionAdapter
impl SubagentResolutionPort for ChildSessionAdapter
Source§fn resolve_subagent_model<'life0, 'life1, 'async_trait>(
&'life0 self,
subagent_type: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<ProviderModelRef>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn resolve_subagent_model<'life0, 'life1, 'async_trait>(
&'life0 self,
subagent_type: &'life1 str,
) -> Pin<Box<dyn Future<Output = Option<ProviderModelRef>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
subagent_type, or None to use defaults.Source§fn resolve_runtime_metadata<'life0, 'life1, 'async_trait>(
&'life0 self,
subagent_type: &'life1 str,
) -> Pin<Box<dyn Future<Output = HashMap<String, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn resolve_runtime_metadata<'life0, 'life1, 'async_trait>(
&'life0 self,
subagent_type: &'life1 str,
) -> Pin<Box<dyn Future<Output = HashMap<String, String>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
subagent_type.