Skip to main content

agentkit_capabilities/
lib.rs

1use std::fmt;
2use std::sync::Arc;
3
4use agentkit_core::{DataRef, Item, MetadataMap, SessionId, TurnId};
5use async_trait::async_trait;
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8use thiserror::Error;
9
10macro_rules! capability_id {
11    ($name:ident) => {
12        #[derive(
13            Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
14        )]
15        pub struct $name(pub String);
16
17        impl $name {
18            pub fn new(value: impl Into<String>) -> Self {
19                Self(value.into())
20            }
21        }
22
23        impl fmt::Display for $name {
24            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25                self.0.fmt(f)
26            }
27        }
28    };
29}
30
31capability_id!(CapabilityName);
32capability_id!(ResourceId);
33capability_id!(PromptId);
34
35#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
36pub struct InvocableSpec {
37    pub name: CapabilityName,
38    pub description: String,
39    pub input_schema: Value,
40    pub metadata: MetadataMap,
41}
42
43#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
44pub struct InvocableRequest {
45    pub input: Value,
46    pub session_id: Option<SessionId>,
47    pub turn_id: Option<TurnId>,
48    pub metadata: MetadataMap,
49}
50
51#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
52pub struct InvocableResult {
53    pub output: InvocableOutput,
54    pub metadata: MetadataMap,
55}
56
57#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
58pub enum InvocableOutput {
59    Text(String),
60    Structured(Value),
61    Items(Vec<Item>),
62    Data(DataRef),
63}
64
65#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
66pub struct ResourceDescriptor {
67    pub id: ResourceId,
68    pub name: String,
69    pub description: Option<String>,
70    pub mime_type: Option<String>,
71    pub metadata: MetadataMap,
72}
73
74#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
75pub struct ResourceContents {
76    pub data: DataRef,
77    pub metadata: MetadataMap,
78}
79
80#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
81pub struct PromptDescriptor {
82    pub id: PromptId,
83    pub name: String,
84    pub description: Option<String>,
85    pub input_schema: Value,
86    pub metadata: MetadataMap,
87}
88
89#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
90pub struct PromptContents {
91    pub items: Vec<Item>,
92    pub metadata: MetadataMap,
93}
94
95#[derive(Clone, Debug, PartialEq, Eq)]
96pub struct CapabilityContext<'a> {
97    pub session_id: Option<&'a SessionId>,
98    pub turn_id: Option<&'a TurnId>,
99    pub metadata: &'a MetadataMap,
100}
101
102#[async_trait]
103pub trait Invocable: Send + Sync {
104    fn spec(&self) -> &InvocableSpec;
105
106    async fn invoke(
107        &self,
108        request: InvocableRequest,
109        ctx: &mut CapabilityContext<'_>,
110    ) -> Result<InvocableResult, CapabilityError>;
111}
112
113#[async_trait]
114pub trait ResourceProvider: Send + Sync {
115    async fn list_resources(&self) -> Result<Vec<ResourceDescriptor>, CapabilityError>;
116
117    async fn read_resource(
118        &self,
119        id: &ResourceId,
120        ctx: &mut CapabilityContext<'_>,
121    ) -> Result<ResourceContents, CapabilityError>;
122}
123
124#[async_trait]
125pub trait PromptProvider: Send + Sync {
126    async fn list_prompts(&self) -> Result<Vec<PromptDescriptor>, CapabilityError>;
127
128    async fn get_prompt(
129        &self,
130        id: &PromptId,
131        args: Value,
132        ctx: &mut CapabilityContext<'_>,
133    ) -> Result<PromptContents, CapabilityError>;
134}
135
136pub trait CapabilityProvider: Send + Sync {
137    fn invocables(&self) -> Vec<Arc<dyn Invocable>>;
138    fn resources(&self) -> Vec<Arc<dyn ResourceProvider>>;
139    fn prompts(&self) -> Vec<Arc<dyn PromptProvider>>;
140}
141
142#[derive(Debug, Error)]
143pub enum CapabilityError {
144    #[error("capability unavailable: {0}")]
145    Unavailable(String),
146    #[error("invalid capability input: {0}")]
147    InvalidInput(String),
148    #[error("capability execution failed: {0}")]
149    ExecutionFailed(String),
150}