rig_core/tool/managed.rs
1//! Registry contracts for refreshable external tool sources.
2//! Generation tokens protect newer registrations from stale refreshes, while
3//! [`DynamicTool::is_live`] reports disconnection without tool execution.
4//!
5//! ```
6//! use rig_core::tool::ManagedToolToken;
7//!
8//! let token = ManagedToolToken::new();
9//! assert_eq!(token, token.clone());
10//! assert_ne!(token, ManagedToolToken::new());
11//! ```
12
13use std::collections::HashMap;
14use std::sync::Arc;
15
16use super::DynamicTool;
17
18/// Opaque identity for one managed registry generation.
19///
20/// Minted by a [`ManagedToolSink`] when it installs a tool; two tokens are
21/// equal only if they are the same generation.
22#[derive(Clone, Debug)]
23pub struct ManagedToolToken(Arc<()>);
24
25impl ManagedToolToken {
26 /// Mint a fresh generation. Only sinks should call this.
27 pub fn new() -> Self {
28 Self(Arc::new(()))
29 }
30}
31
32impl Default for ManagedToolToken {
33 fn default() -> Self {
34 Self::new()
35 }
36}
37
38impl PartialEq for ManagedToolToken {
39 fn eq(&self, other: &Self) -> bool {
40 Arc::ptr_eq(&self.0, &other.0)
41 }
42}
43
44impl Eq for ManagedToolToken {}
45
46/// A tool registry that accepts tools from an external, refreshable source.
47pub trait ManagedToolSink {
48 /// Atomically install the initial tools owned by one source.
49 /// Last-registration-wins: an existing name is replaced. Tools that
50 /// report `!is_live()` are skipped. Returns one generation token per
51 /// installed name, to hand back to [`Self::reconcile_managed_tools`].
52 fn add_managed_tools(&self, tools: Vec<DynamicTool>) -> HashMap<String, ManagedToolToken>;
53
54 /// Atomically reconcile one source's registrations with a refreshed tool
55 /// list. Existing names change only while their `expected` generation is
56 /// still current (newer local or peer-source registrations win); names
57 /// missing from `tools` and still owned by this source are removed.
58 /// Returns the new generation tokens.
59 fn reconcile_managed_tools(
60 &self,
61 expected: HashMap<String, ManagedToolToken>,
62 tools: Vec<DynamicTool>,
63 ) -> HashMap<String, ManagedToolToken>;
64}