pub struct CompositeExecutor<A: ToolExecutor, B: ToolExecutor> { /* private fields */ }Expand description
Chains two ToolExecutor implementations with first-match-wins dispatch.
For each method, first is tried first. If it returns Ok(None) (i.e. it does not
handle the input), second is tried. If first returns an Err, the error propagates
immediately without consulting second.
Use this to compose a chain of specialized executors at startup instead of a dynamic
Vec<Box<dyn ...>>. Nest multiple CompositeExecutors to handle more than two backends.
Tool definitions from both executors are merged, with first taking precedence when
both define a tool with the same ID.
§Example
use zeph_tools::{
CompositeExecutor, ShellExecutor, WebScrapeExecutor, ShellConfig, ScrapeConfig,
};
let shell = ShellExecutor::new(&ShellConfig::default());
let scrape = WebScrapeExecutor::new(&ScrapeConfig::default());
let executor = CompositeExecutor::new(shell, scrape);
// executor handles both bash blocks and scrape/fetch tool calls.Implementations§
Source§impl<A: ToolExecutor, B: ToolExecutor> CompositeExecutor<A, B>
impl<A: ToolExecutor, B: ToolExecutor> CompositeExecutor<A, B>
Trait Implementations§
Source§impl<A: Debug + ToolExecutor, B: Debug + ToolExecutor> Debug for CompositeExecutor<A, B>
impl<A: Debug + ToolExecutor, B: Debug + ToolExecutor> Debug for CompositeExecutor<A, B>
Source§impl<A: ToolExecutor, B: ToolExecutor> ToolExecutor for CompositeExecutor<A, B>
impl<A: ToolExecutor, B: ToolExecutor> ToolExecutor for CompositeExecutor<A, B>
Source§fn set_skill_env(&self, env: Option<HashMap<String, String>>)
fn set_skill_env(&self, env: Option<HashMap<String, String>>)
Forward the active skill’s env injection to BOTH inner executors.
The base ToolExecutor::set_skill_env is a no-op, so without this override the
composition tree built in agent_setup silently swallows env injection — the
underlying ShellExecutor never sees GITHUB_TOKEN etc. Each layer ignores the call
if it does not own a skill_env slot; layers that do (e.g. ShellExecutor) update
their state. See #3869.
Source§fn set_effective_trust(&self, level: SkillTrustLevel)
fn set_effective_trust(&self, level: SkillTrustLevel)
Forward the active skill’s trust level to BOTH inner executors.
Mirrors Self::set_skill_env: without this override, TrustGateExecutor never
observes a non-Trusted level when composed under CompositeExecutor, leaving
quarantine enforcement effectively bypassed. See #3869.
Source§async fn execute(&self, response: &str) -> Result<Option<ToolOutput>, ToolError>
async fn execute(&self, response: &str) -> Result<Option<ToolOutput>, ToolError>
response for fenced tool blocks and execute them. Read moreSource§async fn execute_confirmed(
&self,
response: &str,
) -> Result<Option<ToolOutput>, ToolError>
async fn execute_confirmed( &self, response: &str, ) -> Result<Option<ToolOutput>, ToolError>
Source§fn tool_definitions(&self) -> Vec<ToolDef>
fn tool_definitions(&self) -> Vec<ToolDef>
Source§async fn execute_tool_call(
&self,
call: &ToolCall,
) -> Result<Option<ToolOutput>, ToolError>
async fn execute_tool_call( &self, call: &ToolCall, ) -> Result<Option<ToolOutput>, ToolError>
Source§fn is_tool_retryable(&self, tool_id: &str) -> bool
fn is_tool_retryable(&self, tool_id: &str) -> bool
Source§fn is_tool_speculatable(&self, tool_id: &str) -> bool
fn is_tool_speculatable(&self, tool_id: &str) -> bool
Auto Trait Implementations§
impl<A, B> Freeze for CompositeExecutor<A, B>
impl<A, B> RefUnwindSafe for CompositeExecutor<A, B>where
A: RefUnwindSafe,
B: RefUnwindSafe,
impl<A, B> Send for CompositeExecutor<A, B>
impl<A, B> Sync for CompositeExecutor<A, B>
impl<A, B> Unpin for CompositeExecutor<A, B>
impl<A, B> UnsafeUnpin for CompositeExecutor<A, B>where
A: UnsafeUnpin,
B: UnsafeUnpin,
impl<A, B> UnwindSafe for CompositeExecutor<A, B>where
A: UnwindSafe,
B: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> ErasedToolExecutor for Twhere
T: ToolExecutor,
impl<T> ErasedToolExecutor for Twhere
T: ToolExecutor,
fn execute_erased<'a>( &'a self, response: &'a str, ) -> Pin<Box<dyn Future<Output = Result<Option<ToolOutput>, ToolError>> + Send + 'a>>
fn execute_confirmed_erased<'a>( &'a self, response: &'a str, ) -> Pin<Box<dyn Future<Output = Result<Option<ToolOutput>, ToolError>> + Send + 'a>>
fn tool_definitions_erased(&self) -> Vec<ToolDef>
fn execute_tool_call_erased<'a>( &'a self, call: &'a ToolCall, ) -> Pin<Box<dyn Future<Output = Result<Option<ToolOutput>, ToolError>> + Send + 'a>>
fn execute_tool_call_confirmed_erased<'a>( &'a self, call: &'a ToolCall, ) -> Pin<Box<dyn Future<Output = Result<Option<ToolOutput>, ToolError>> + Send + 'a>>
Source§fn set_skill_env(&self, env: Option<HashMap<String, String>>)
fn set_skill_env(&self, env: Option<HashMap<String, String>>)
Source§fn set_effective_trust(&self, level: SkillTrustLevel)
fn set_effective_trust(&self, level: SkillTrustLevel)
Source§fn is_tool_retryable_erased(&self, tool_id: &str) -> bool
fn is_tool_retryable_erased(&self, tool_id: &str) -> bool
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request