Skip to main content

openhelm_sdk/
lib.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use serde_json::Value;
4
5pub use anyhow;
6pub use serde_json;
7pub use toml;
8
9/// The result of executing a tool.
10pub struct ToolOutput {
11    pub success: bool,
12    pub output: String,
13}
14
15/// An OpenAI-compatible tool/function definition.
16#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
17pub struct ToolDefinition {
18    #[serde(rename = "type")]
19    pub kind: String,
20    pub function: FunctionDefinition,
21}
22
23#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
24pub struct FunctionDefinition {
25    pub name: String,
26    pub description: String,
27    pub parameters: Value,
28}
29
30impl ToolDefinition {
31    /// Convenience constructor for function-type tools.
32    pub fn function(
33        name: impl Into<String>,
34        description: impl Into<String>,
35        parameters: Value,
36    ) -> Self {
37        Self {
38            kind: "function".to_string(),
39            function: FunctionDefinition {
40                name: name.into(),
41                description: description.into(),
42                parameters,
43            },
44        }
45    }
46}
47
48/// A tool that can be invoked by the AI.
49/// Skill tools bake all required config in at construction time (via
50/// [`Skill::build_tools`]) so they need no runtime context.
51#[async_trait]
52pub trait Tool: Send + Sync {
53    fn name(&self) -> &'static str;
54    fn definition(&self) -> ToolDefinition;
55    async fn execute(&self, args: &Value) -> Result<ToolOutput>;
56}
57
58/// A skill bundles a set of related tools and knows how to configure them.
59#[async_trait]
60pub trait Skill: Send + Sync {
61    /// Unique lowercase identifier, e.g. `"github"`.
62    fn name(&self) -> &'static str;
63
64    /// Build pre-configured tool instances from the raw per-profile config
65    /// table (`[profiles.<name>.skills.<skill>]`), or `None` if the table is
66    /// absent.  Returns an error if required config (e.g. a token) is missing.
67    async fn build_tools(&self, config: Option<&toml::Value>) -> Result<Vec<Box<dyn Tool>>>;
68}