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                description: tool.description.clone(),
44                source: snapshot.source.clone(),
45                destination: DestinationRef::with_kind(
46                    DestinationKind::Tool,
47                    format!("destination.{}", tool.canonical_tool_name.as_str()),
48                ),
49                executor_ref: Some(tool.executor_ref.clone()),
50                policy_refs: tool.policy_refs.clone(),
51                requires_approval: tool.requires_approval,
52                sidecar_refs: vec![sidecar_ref.clone()],
53                effect_class: tool.effect_class.clone(),
54                risk_class: tool.risk_class.clone(),
55                privacy: tool.privacy,
56                retention: RetentionClass::RunScoped,
57            })
58            .collect();
59        Ok(Self {
60            snapshot,
61            sidecar,
62            capabilities,
63            routes,
64        })
65    }
66
67    /// Install into.
68    /// This updates the provided RuntimePackageBuilder with bundle routes and sidecars; it does
69    /// not activate tools by itself.
70    pub fn install_into(&self, mut builder: RuntimePackageBuilder) -> RuntimePackageBuilder {
71        builder = builder.sidecar(self.sidecar.clone());
72        for capability in &self.capabilities {
73            builder = builder.capability(capability.clone());
74        }
75        builder
76    }
77}