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