cascade_agent/skills/
skill_tool.rs1use async_trait::async_trait;
4
5use crate::tools::{Tool, ToolResult};
6
7use super::executor::{SkillExecutor, DEFAULT_TIMEOUT};
8use super::types::Skill;
9
10pub struct SkillTool {
16 skill: Skill,
17}
18
19impl SkillTool {
20 pub fn new(skill: Skill) -> Self {
21 Self { skill }
22 }
23
24 fn build_description(&self) -> String {
27 let meta_desc = self.skill.metadata.description.clone();
28 let instructions = self.skill.instructions.trim();
29 if instructions.is_empty() {
30 return meta_desc;
31 }
32 const MAX_INSTRUCTIONS_LEN: usize = 2_000;
34 let truncated = if instructions.len() > MAX_INSTRUCTIONS_LEN {
35 format!(
36 "{}\n\n[... instructions truncated at {} chars ...]",
37 &instructions[..MAX_INSTRUCTIONS_LEN],
38 MAX_INSTRUCTIONS_LEN
39 )
40 } else {
41 instructions.to_string()
42 };
43 format!("{}\n\nInstructions:\n{}", meta_desc, truncated)
44 }
45
46 fn build_parameters_schema(&self) -> serde_json::Value {
48 if let Some(ref input_format) = self.skill.metadata.input_format {
49 input_format.schema.clone()
51 } else if self.skill.executable_path.is_some() {
52 serde_json::json!({
54 "type": "object",
55 "properties": {
56 "input": {
57 "type": "string",
58 "description": "Input to pass to the skill executable"
59 }
60 }
61 })
62 } else {
63 serde_json::json!({
65 "type": "object",
66 "properties": {}
67 })
68 }
69 }
70}
71
72#[async_trait]
73impl Tool for SkillTool {
74 fn name(&self) -> &str {
75 &self.skill.metadata.name
76 }
77
78 fn description(&self) -> &str {
79 &self.skill.metadata.description
85 }
86
87 fn parameters_schema(&self) -> serde_json::Value {
88 self.build_parameters_schema()
89 }
90
91 async fn execute(&self, args: serde_json::Value) -> ToolResult {
92 if let Some(ref exe_path) = self.skill.executable_path {
93 SkillExecutor::execute(exe_path, args, &self.skill.directory, DEFAULT_TIMEOUT).await
94 } else {
95 ToolResult::ok(serde_json::json!({
97 "instructions": self.skill.instructions.trim()
98 }))
99 }
100 }
101
102 fn to_definition(&self) -> llm_cascade::ToolDefinition {
103 llm_cascade::ToolDefinition {
104 name: self.name().to_owned(),
105 description: self.build_description(),
106 parameters: self.parameters_schema(),
107 }
108 }
109}