1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
use serde::{Deserialize, Serialize};
use serde_json::{Map, Value};
use crate::Cancellation;
pub type Error = crate::Error;
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct Definition {
pub name: String,
pub description: Option<String>,
#[serde(default)]
pub metadata: Map<String, Value>,
}
/// Instructions and resource information for an Agent, not an executable
/// function. Reading a Skill never grants access to tools or owns Runtime state.
pub trait Skill: Send + Sync {
fn definition(&self) -> &Definition;
fn read(
&self,
cancellation: &Cancellation,
) -> impl std::future::Future<Output = Result<String, Error>> + Send;
}
/// A Skill loader owned by a Workspace or another application backend. Local
/// loaders may discover directories; server loaders can implement the same
/// contract using database records. Names returned by `list` identify the
/// exact instructions and resources subsequently read during this Agent run.
pub trait Loader: Send + Sync {
/// Return a stable source version or fingerprint for the current Skill
/// catalog. Workspace-backed loaders use this value to reuse a parsed
/// snapshot across executions and refresh only after the source changes.
/// A default value derived from the definitions keeps existing loaders
/// source-compatible; database-backed loaders should override it with a
/// cheap revision or content fingerprint that also covers Skill bodies
/// and resources.
fn version(
&self,
cancellation: &Cancellation,
) -> impl std::future::Future<Output = Result<String, Error>> + Send {
async move {
let definitions = self.list(cancellation).await?;
serde_json::to_string(&definitions)
.map_err(|_| Error::new("INTERNAL", "Skill definitions cannot be serialized"))
}
}
fn list(
&self,
cancellation: &Cancellation,
) -> impl std::future::Future<Output = Result<Vec<Definition>, Error>> + Send;
fn read(
&self,
name: &str,
cancellation: &Cancellation,
) -> impl std::future::Future<Output = Result<String, Error>> + Send;
fn read_resource(
&self,
name: &str,
path: &str,
cancellation: &Cancellation,
) -> impl std::future::Future<Output = Result<Vec<u8>, Error>> + Send;
}