Skip to main content

agent_sdk_toolkit/packs/
bundle.rs

1//! Toolkit pack assembly helpers. Use these modules to turn toolkit operations into
2//! core package capabilities, sidecars, and routes. Pack assembly is data-only and
3//! does not execute tools or mutate a runtime package until explicitly installed.
4//! This file contains the bundle portion of that contract.
5//!
6use agent_sdk_core::{
7    AgentError, DestinationKind, DestinationRef, PackageSidecarSnapshot, RetentionClass,
8    RuntimePackageBuilder, ToolPackSnapshot, ToolRoute,
9};
10
11#[derive(Clone, Debug)]
12/// Toolkit pack toolkit pack bundle value.
13/// Use it to assemble exported tool-pack configuration; installation or activation effects are documented by the bundle executor.
14pub struct ToolkitPackBundle {
15    /// Snapshot used by this record or request.
16    pub snapshot: ToolPackSnapshot,
17    /// Sidecar used by this record or request.
18    pub sidecar: PackageSidecarSnapshot,
19    /// Capabilities frozen into the package or returned by an adapter health
20    /// check.
21    pub capabilities: Vec<agent_sdk_core::CapabilitySpec>,
22    /// Collection of routes values.
23    /// Ordering and membership should be treated as part of the serialized contract when
24    /// relevant.
25    pub routes: Vec<ToolRoute>,
26}
27
28impl ToolkitPackBundle {
29    /// Constructs this value from snapshot. Use it when adapting
30    /// canonical SDK records without introducing a second behavior
31    /// path.
32    pub fn from_snapshot(snapshot: ToolPackSnapshot) -> Result<Self, AgentError> {
33        let sidecar_ref = snapshot.sidecar_ref()?;
34        let sidecar = snapshot.package_sidecar_snapshot()?;
35        let capabilities = snapshot.capability_specs()?;
36        let routes = snapshot
37            .tools
38            .iter()
39            .map(|tool| ToolRoute {
40                capability_id: tool.capability_id.clone(),
41                canonical_tool_name: tool.canonical_tool_name.clone(),
42                namespace: tool.namespace.clone(),
43                source: snapshot.source.clone(),
44                destination: DestinationRef::with_kind(
45                    DestinationKind::Tool,
46                    format!("destination.{}", tool.canonical_tool_name.as_str()),
47                ),
48                executor_ref: Some(tool.executor_ref.clone()),
49                policy_refs: tool.policy_refs.clone(),
50                sidecar_refs: vec![sidecar_ref.clone()],
51                effect_class: tool.effect_class.clone(),
52                risk_class: tool.risk_class.clone(),
53                privacy: tool.privacy,
54                retention: RetentionClass::RunScoped,
55            })
56            .collect();
57        Ok(Self {
58            snapshot,
59            sidecar,
60            capabilities,
61            routes,
62        })
63    }
64
65    /// Install into.
66    /// This updates the provided RuntimePackageBuilder with bundle routes and sidecars; it does
67    /// not activate tools by itself.
68    pub fn install_into(&self, mut builder: RuntimePackageBuilder) -> RuntimePackageBuilder {
69        builder = builder.sidecar(self.sidecar.clone());
70        for capability in &self.capabilities {
71            builder = builder.capability(capability.clone());
72        }
73        builder
74    }
75}