vtcode_core/skills/
instructions.rs1use std::path::PathBuf;
2
3pub const SKILL_INSTRUCTIONS_PREFIX: &str = "<skill>";
5
6#[derive(Debug, Clone)]
7pub struct SkillInstructions {
8 pub name: String,
9 pub path: PathBuf,
10 pub contents: String,
11}
12
13impl SkillInstructions {
14 pub fn is_skill_instructions(text: &str) -> bool {
16 text.starts_with(SKILL_INSTRUCTIONS_PREFIX)
17 }
18
19 pub fn to_xml_message(&self) -> String {
21 let path_str = self.path.to_string_lossy().replace('\\', "/");
22 format!(
23 "<skill>\n<name>{}</name>\n<path>{}</path>\n{}\n</skill>",
24 self.name, path_str, self.contents
25 )
26 }
27}
28
29#[cfg(test)]
30mod tests {
31 use super::*;
32
33 #[test]
34 fn test_skill_instructions_prefix_detection() {
35 let msg = "<skill>\n<name>test</name>\n<path>/path</path>\ncontents\n</skill>";
36 assert!(SkillInstructions::is_skill_instructions(msg));
37
38 let non_skill = "Regular message without skill";
39 assert!(!SkillInstructions::is_skill_instructions(non_skill));
40 }
41
42 #[test]
43 fn test_skill_instructions_xml_format() {
44 let skill = SkillInstructions {
45 name: "test-skill".to_string(),
46 path: PathBuf::from("/path/to/skill/SKILL.md"),
47 contents: "# Test Skill\n\nInstructions here.".to_string(),
48 };
49
50 let xml = skill.to_xml_message();
51 assert!(xml.starts_with("<skill>"));
52 assert!(xml.contains("<name>test-skill</name>"));
53 assert!(xml.contains("<path>/path/to/skill/SKILL.md</path>"));
54 assert!(xml.contains("# Test Skill"));
55 assert!(xml.ends_with("</skill>"));
56 }
57}