vtcode_core/skills/
enhanced_harness.rs1use crate::tools::generation_helpers::GenerationHelper;
7use anyhow::Result;
8use serde_json::Value;
9use std::path::PathBuf;
10
11pub struct EnhancedSkillResult {
13 pub message: String,
14 pub generated_files: Vec<String>,
15 pub metadata: Value,
16}
17
18pub struct EnhancedSkillHarness {
20 workspace_root: PathBuf,
21 helper: GenerationHelper,
22}
23
24impl EnhancedSkillHarness {
25 pub fn new(workspace_root: PathBuf) -> Self {
26 Self {
27 workspace_root: workspace_root.clone(),
28 helper: GenerationHelper::new(workspace_root),
29 }
30 }
31
32 pub async fn execute_skill_with_verification(
34 &self,
35 skill_name: &str,
36 output_filename: Option<&str>,
37 skill_logic: impl FnOnce() -> Result<()>,
38 ) -> Result<EnhancedSkillResult> {
39 skill_logic()?;
41
42 let mut verification_messages = Vec::new();
44 let mut generated_files = Vec::new();
45
46 if let Some(filename) = output_filename {
47 let verification = self.helper.verify_and_report(filename).await?;
48 verification_messages.push(verification.clone());
49 generated_files.push(filename.to_string());
50 }
51
52 let message = if verification_messages.is_empty() {
54 format!("✓ Skill '{skill_name}' executed successfully")
55 } else {
56 format!("✓ Skill '{}' executed successfully\n\n{}", skill_name, verification_messages.join("\n"))
57 };
58
59 Ok(EnhancedSkillResult {
60 message,
61 generated_files,
62 metadata: serde_json::json!({
63 "skill_name": skill_name,
64 "workspace_root": self.workspace_root.display().to_string(),
65 }),
66 })
67 }
68
69 pub async fn create_file_generation_response(
71 &self,
72 file_type: &str,
73 filename: &str,
74 generation_details: Option<&str>,
75 ) -> Result<String> {
76 let verification = self.helper.verify_and_report(filename).await?;
77
78 let details_section = if let Some(details) = generation_details {
79 format!("\n\n{details}")
80 } else {
81 String::new()
82 };
83
84 Ok(format!("✓ Generated {file_type}: {filename}\n\n{verification}{details_section}"))
85 }
86
87 pub async fn create_sample_response(
89 &self,
90 file_type: &str,
91 generator_code: impl FnOnce(&PathBuf) -> Result<()>,
92 ) -> Result<String> {
93 let timestamp = chrono::Local::now().format("%Y%m%d_%H%M%S");
95 let filename = format!("sample_{}_{}", file_type.to_lowercase(), timestamp);
96 let filepath = self.workspace_root.join(&filename);
97
98 generator_code(&filepath)?;
100
101 self.create_file_generation_response(
103 file_type,
104 &filename,
105 Some("This is a sample file. You can modify the content as needed."),
106 )
107 .await
108 }
109}
110
111pub async fn execute_file_generation_skill(
113 workspace_root: PathBuf,
114 skill_name: &str,
115 filename: &str,
116 success_message: Option<&str>,
117) -> Result<String> {
118 let harness = EnhancedSkillHarness::new(workspace_root);
119
120 let verification = harness.helper.verify_and_report(filename).await?;
121
122 let message = if let Some(custom_msg) = success_message {
123 format!("{custom_msg}\n\n{verification}")
124 } else {
125 format!("✓ Skill '{skill_name}' completed.\n\n{verification}")
126 };
127
128 Ok(message)
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134 use tempfile::TempDir;
135
136 #[tokio::test]
137 async fn test_enhanced_harness_creation() {
138 let temp_dir = TempDir::new().unwrap();
139 let harness = EnhancedSkillHarness::new(temp_dir.path().to_path_buf());
140
141 assert_eq!(harness.workspace_root, temp_dir.path().to_path_buf());
143 }
144
145 #[tokio::test]
146 async fn test_execute_skill_with_verification() {
147 let temp_dir = TempDir::new().unwrap();
148 let harness = EnhancedSkillHarness::new(temp_dir.path().to_path_buf());
149
150 let result = harness
152 .execute_skill_with_verification("test-skill", None, || Ok(()))
153 .await
154 .unwrap();
155
156 assert!(result.message.contains("test-skill"));
157 assert!(result.message.contains("executed successfully"));
158 assert!(result.generated_files.is_empty());
159 }
160
161 #[tokio::test]
162 async fn test_create_file_generation_response() {
163 let temp_dir = TempDir::new().unwrap();
164 let harness = EnhancedSkillHarness::new(temp_dir.path().to_path_buf());
165
166 let response = harness
167 .create_file_generation_response("PDF", "nonexistent.pdf", None)
168 .await
169 .unwrap();
170
171 assert!(response.contains("Generated PDF"));
172 assert!(response.contains("nonexistent.pdf"));
173 }
174
175 #[tokio::test]
176 async fn test_quick_execution_helper() {
177 let temp_dir = TempDir::new().unwrap();
178 let result = execute_file_generation_skill(
179 temp_dir.path().to_path_buf(),
180 "test-skill",
181 "test.pdf",
182 Some("Custom success message"),
183 )
184 .await
185 .unwrap();
186
187 assert!(result.contains("Custom success message"));
188 }
189}