pub struct ScopedToolRegistry { /* private fields */ }Expand description
LIFO scoped tool registry with shadow-stack semantics.
Wraps a base ToolRegistry with a stack of scopes. Tools in
higher scopes shadow identically-named tools in lower scopes.
Popping a scope removes all its tools and restores shadows.
The scope stack is protected by a Mutex for interior mutability,
enabling push/pop through &self. The base registry is lock-free.
Implementations§
Source§impl ScopedToolRegistry
impl ScopedToolRegistry
Sourcepub fn new(base: ToolRegistry) -> Self
pub fn new(base: ToolRegistry) -> Self
Creates a new scoped registry with the given base.
The base registry provides tools at the lowest resolution level.
Sourcepub fn push_scope(&self) -> ScopeId
pub fn push_scope(&self) -> ScopeId
Pushes a new empty scope onto the stack and returns its ScopeId.
Sourcepub fn pop_scope(&self, id: ScopeId) -> bool
pub fn pop_scope(&self, id: ScopeId) -> bool
Pops the given scope from the stack.
Returns true if the scope was found and removed, false if it
was not the top scope or does not exist. Only the topmost scope
can be popped — attempting to pop a non-top scope is a no-op.
Sourcepub fn register_in_scope<T: Tool + 'static>(
&self,
scope: ScopeId,
tool: T,
) -> Result<Option<Arc<dyn Tool>>, T>
pub fn register_in_scope<T: Tool + 'static>( &self, scope: ScopeId, tool: T, ) -> Result<Option<Arc<dyn Tool>>, T>
Registers a tool in the specified scope.
If a tool with the same name already exists in that scope, it is replaced and the old tool is returned. Tools in other scopes or the base registry are not affected — they are simply shadowed.
§Errors
Returns the tool back if the scope does not exist.
Sourcepub fn register_arc_in_scope(
&self,
scope: ScopeId,
name: String,
tool: Arc<dyn Tool>,
) -> Result<Option<Arc<dyn Tool>>, (String, Arc<dyn Tool>)>
pub fn register_arc_in_scope( &self, scope: ScopeId, name: String, tool: Arc<dyn Tool>, ) -> Result<Option<Arc<dyn Tool>>, (String, Arc<dyn Tool>)>
Registers an already-Arc’d tool in the specified scope.
Returns Ok(old) if the scope exists, or Err((name, tool)) if not.
§Errors
Returns Err((name, tool)) when the requested scope does not exist
in the layer stack. The returned tuple lets the caller recover the
name and Arc’d tool without an extra allocation.
Sourcepub fn get(&self, name: &str) -> Option<Arc<dyn Tool>>
pub fn get(&self, name: &str) -> Option<Arc<dyn Tool>>
Returns a tool by searching from top scope to base.
Sourcepub fn specs(&self) -> Vec<ToolSpec>
pub fn specs(&self) -> Vec<ToolSpec>
Generates merged ToolSpecs from all scopes and base,
sorted alphabetically by tool name.
Tools in higher scopes shadow those with the same name in lower scopes or the base. The returned list contains one entry per unique tool name.
The sorted output ensures deterministic prompt caching across turns and provider calls.
Sourcepub fn scope_depth(&self) -> usize
pub fn scope_depth(&self) -> usize
Returns the number of active scopes.
Sourcepub fn base(&self) -> &ToolRegistry
pub fn base(&self) -> &ToolRegistry
Returns a reference to the base registry.
Sourcepub fn base_mut(&mut self) -> &mut ToolRegistry
pub fn base_mut(&mut self) -> &mut ToolRegistry
Returns a mutable reference to the base registry.
Sourcepub fn unregister_from_base(&self, name: &str) -> Option<Arc<dyn Tool>>
pub fn unregister_from_base(&self, name: &str) -> Option<Arc<dyn Tool>>
Removes a tool from the base registry by name.
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the total number of unique tools visible (base + all scopes).
Sourcepub async fn execute(&self, call: &ToolCall) -> ToolResult<ToolOutput>
pub async fn execute(&self, call: &ToolCall) -> ToolResult<ToolOutput>
Executes a tool call using the merged tool view.
This delegates to the first matching tool from top scope to base.
§Errors
Returns ToolError::NotFound
when the tool is not in any scope or the base.
Sourcepub fn push_scope_guarded(self: &Arc<Self>) -> ScopeGuard
pub fn push_scope_guarded(self: &Arc<Self>) -> ScopeGuard
Pushes a new scope and returns a RAII guard that pops it on drop.
This is the preferred way to manage scope lifetimes. The returned
ScopeGuard automatically calls pop_scope
when dropped, ensuring cleanup even in the presence of early
returns or panics.