1use async_trait::async_trait;
4use std::time::Instant;
5
6use crate::error::Result;
7use crate::mode::Mode;
8use crate::models::{
9 Capability, ModeAction, ModeConfig, ModeConstraints, ModeContext, ModeResponse, Operation,
10};
11
12#[derive(Debug, Clone)]
20pub struct VibeMode {
21 config: ModeConfig,
22}
23
24impl VibeMode {
25 pub fn new() -> Self {
27 Self {
28 config: ModeConfig {
29 temperature: 0.9,
30 max_tokens: 4096,
31 system_prompt: "You are a creative coding partner. Help explore ideas, \
32 prototype quickly, and iterate on concepts. Bypass formal specifications \
33 and focus on rapid development."
34 .to_string(),
35 capabilities: vec![
36 Capability::CodeGeneration,
37 Capability::CodeModification,
38 Capability::FileOperations,
39 Capability::FreeformChat,
40 Capability::QuestionAnswering,
41 Capability::SpecConversion,
42 ],
43 constraints: ModeConstraints {
44 allow_file_operations: true,
45 allow_command_execution: false,
46 allow_code_generation: true,
47 require_specs: false,
48 auto_think_more_threshold: None,
49 },
50 },
51 }
52 }
53
54 pub fn with_config(config: ModeConfig) -> Self {
56 Self { config }
57 }
58
59 pub fn generate_code_from_description(&self, description: &str) -> Result<String> {
64 if !self.config.constraints.allow_code_generation {
66 return Err(crate::error::ModeError::OperationNotAllowed {
67 mode: self.id().to_string(),
68 operation: Operation::GenerateCode.to_string(),
69 });
70 }
71
72 Ok(format!(
75 "// Generated from description:\n// {}\n\n// TODO: Implement based on description",
76 description
77 ))
78 }
79
80 pub fn iterate_rapidly(&self, iteration_input: &str) -> Result<String> {
85 if !self.config.constraints.allow_code_generation {
87 return Err(crate::error::ModeError::OperationNotAllowed {
88 mode: self.id().to_string(),
89 operation: Operation::GenerateCode.to_string(),
90 });
91 }
92
93 Ok(format!(
94 "// Rapid iteration:\n// {}\n\n// Generated code for quick prototyping",
95 iteration_input
96 ))
97 }
98
99 pub fn generate_with_iterations(&self, description: &str, iterations: usize) -> Result<String> {
104 if !self.config.constraints.allow_code_generation {
106 return Err(crate::error::ModeError::OperationNotAllowed {
107 mode: self.id().to_string(),
108 operation: Operation::GenerateCode.to_string(),
109 });
110 }
111
112 let mut code = format!(
113 "// Generated from description:\n// {}\n\n// Iteration 1:\n// TODO: Implement",
114 description
115 );
116
117 for i in 2..=iterations {
118 code.push_str(&format!("\n\n// Iteration {}:\n// TODO: Refine", i));
119 }
120
121 Ok(code)
122 }
123
124 pub fn accept_natural_language(&self, input: &str) -> Result<String> {
129 if !self.config.constraints.allow_code_generation {
131 return Err(crate::error::ModeError::OperationNotAllowed {
132 mode: self.id().to_string(),
133 operation: Operation::GenerateCode.to_string(),
134 });
135 }
136
137 if self.config.constraints.require_specs {
139 return Err(crate::error::ModeError::ProcessingFailed(
140 "Specs are required in this mode".to_string(),
141 ));
142 }
143
144 Ok(format!(
145 "// Natural language input:\n// {}\n\n// Generated code without formal specs",
146 input
147 ))
148 }
149
150 pub fn convert_to_specs(&self, project_code: &str) -> Result<String> {
155 let spec_template = format!(
156 "# Generated Specification\n\n\
157 ## Overview\n\
158 This specification was auto-generated from Vibe Mode code.\n\n\
159 ## Code\n\
160 ```\n\
161 {}\n\
162 ```\n\n\
163 ## Next Steps\n\
164 1. Review and refine the specification\n\
165 2. Add acceptance criteria\n\
166 3. Define design decisions\n\
167 4. Create implementation tasks",
168 project_code
169 );
170 Ok(spec_template)
171 }
172
173 pub fn preserve_code_and_context(&self, code: &str, context: &ModeContext) -> Result<String> {
178 let mut preserved = String::new();
179 preserved.push_str("# Preserved Context\n\n");
180 preserved.push_str(&format!("Session ID: {}\n", context.session_id));
181
182 if let Some(path) = &context.project_path {
183 preserved.push_str(&format!("Project Path: {}\n", path.display()));
184 }
185
186 preserved.push_str(&format!(
187 "Conversation History: {} messages\n",
188 context.conversation_history.len()
189 ));
190
191 preserved.push_str("\n# Preserved Code\n\n");
192 preserved.push_str("```\n");
193 preserved.push_str(code);
194 preserved.push_str("\n```\n");
195
196 Ok(preserved)
197 }
198
199 pub fn generate_specs_from_code(&self, code: &str) -> Result<String> {
204 let mut spec = String::new();
205 spec.push_str("# Auto-Generated Specification from Code\n\n");
206
207 if code.contains("fn ") {
209 spec.push_str("## Functions\n");
210 spec.push_str("The following functions were detected in the code:\n\n");
211 for line in code.lines() {
213 if line.contains("fn ") {
214 spec.push_str(&format!("- {}\n", line.trim()));
215 }
216 }
217 spec.push('\n');
218 }
219
220 if code.contains("struct ") {
222 spec.push_str("## Data Structures\n");
223 spec.push_str("The following structures were detected in the code:\n\n");
224 for line in code.lines() {
225 if line.contains("struct ") {
226 spec.push_str(&format!("- {}\n", line.trim()));
227 }
228 }
229 spec.push('\n');
230 }
231
232 spec.push_str("## Requirements\n");
233 spec.push_str("Based on the code analysis, the following requirements are inferred:\n\n");
234 spec.push_str("1. The system should implement the detected functions\n");
235 spec.push_str("2. The system should use the detected data structures\n");
236 spec.push_str("3. The system should follow the patterns in the code\n\n");
237
238 spec.push_str("## Next Steps\n");
239 spec.push_str("1. Review the inferred requirements\n");
240 spec.push_str("2. Add acceptance criteria for each requirement\n");
241 spec.push_str("3. Define design decisions\n");
242 spec.push_str("4. Create implementation tasks\n");
243
244 Ok(spec)
245 }
246
247 pub fn convert_project_to_specs(&self, code: &str, context: &ModeContext) -> Result<String> {
252 let mut conversion = String::new();
253 conversion.push_str("# Vibe Mode to Spec-Driven Conversion\n\n");
254
255 conversion.push_str("## Preserved Context\n");
257 let preserved = self.preserve_code_and_context(code, context)?;
258 conversion.push_str(&preserved);
259 conversion.push_str("\n\n");
260
261 conversion.push_str("## Generated Specification\n");
263 let specs = self.generate_specs_from_code(code)?;
264 conversion.push_str(&specs);
265
266 Ok(conversion)
267 }
268
269 pub fn generate_warnings(&self) -> Vec<String> {
274 vec![
275 "⚠️ Vibe Mode bypasses formal specifications. \
276 Consider converting to spec-driven development for production code."
277 .to_string(),
278 "⚠️ Code generated in Vibe Mode may lack comprehensive testing. \
279 Add tests before deploying to production."
280 .to_string(),
281 "⚠️ Vibe Mode does not enforce code quality standards. \
282 Review code quality manually or switch to Code Mode."
283 .to_string(),
284 "⚠️ Rapid iteration may lead to technical debt. \
285 Plan for refactoring and cleanup."
286 .to_string(),
287 "💡 Best Practice: Use Vibe Mode for exploration and prototyping, \
288 then convert to spec-driven development for production."
289 .to_string(),
290 ]
291 }
292
293 pub fn generate_specific_warnings(&self, context: &str) -> Vec<String> {
298 let mut warnings = self.generate_warnings();
299
300 if context.contains("production") {
301 warnings.push(
302 "⚠️ WARNING: Vibe Mode is not recommended for production code. \
303 Use Code Mode with formal specifications instead."
304 .to_string(),
305 );
306 }
307
308 if context.contains("test") {
309 warnings.push(
310 "⚠️ Code generated in Vibe Mode requires comprehensive testing. \
311 Add unit tests, integration tests, and property-based tests."
312 .to_string(),
313 );
314 }
315
316 if context.contains("quality") {
317 warnings.push(
318 "⚠️ Code quality validation is not performed in Vibe Mode. \
319 Switch to Code Mode for quality validation."
320 .to_string(),
321 );
322 }
323
324 warnings
325 }
326
327 pub fn format_warnings(&self, warnings: &[String]) -> String {
331 let mut formatted = String::new();
332 formatted.push_str("=== Vibe Mode Warnings ===\n\n");
333
334 for warning in warnings {
335 formatted.push_str(&format!("{}\n", warning));
336 }
337
338 formatted.push_str("\n=== End Warnings ===\n");
339 formatted
340 }
341
342 pub fn add_warnings_to_response(&self, response: &mut ModeResponse) {
347 let warnings = self.generate_warnings();
348 for warning in warnings {
349 response.add_suggestion(warning);
350 }
351 }
352
353 pub fn add_specific_warnings_to_response(&self, response: &mut ModeResponse, context: &str) {
357 let warnings = self.generate_specific_warnings(context);
358 for warning in warnings {
359 response.add_suggestion(warning);
360 }
361 }
362
363 pub fn validate_operation(&self, operation: &Operation) -> Result<()> {
367 match operation {
368 Operation::GenerateCode | Operation::ModifyFile | Operation::AnswerQuestion => Ok(()),
369 Operation::ExecuteCommand => Err(crate::error::ModeError::OperationNotAllowed {
370 mode: self.id().to_string(),
371 operation: operation.to_string(),
372 }),
373 Operation::RunTests => Err(crate::error::ModeError::OperationNotAllowed {
374 mode: self.id().to_string(),
375 operation: operation.to_string(),
376 }),
377 Operation::ValidateQuality => Err(crate::error::ModeError::OperationNotAllowed {
378 mode: self.id().to_string(),
379 operation: operation.to_string(),
380 }),
381 }
382 }
383
384 pub fn provide_best_practices(&self) -> Vec<String> {
388 vec![
389 "Start with Vibe Mode for rapid prototyping and exploration".to_string(),
390 "Use natural language descriptions to generate code quickly".to_string(),
391 "Iterate rapidly without formal review cycles".to_string(),
392 "Convert to spec-driven development when ready for production".to_string(),
393 "Add comprehensive tests before deploying code".to_string(),
394 "Review code quality and refactor as needed".to_string(),
395 ]
396 }
397}
398
399impl Default for VibeMode {
400 fn default() -> Self {
401 Self::new()
402 }
403}
404
405#[async_trait]
406impl Mode for VibeMode {
407 fn id(&self) -> &str {
408 "vibe"
409 }
410
411 fn name(&self) -> &str {
412 "Vibe Mode"
413 }
414
415 fn description(&self) -> &str {
416 "Free-form exploration and rapid prototyping without formal specifications"
417 }
418
419 fn system_prompt(&self) -> &str {
420 &self.config.system_prompt
421 }
422
423 async fn process(&self, input: &str, context: &ModeContext) -> Result<ModeResponse> {
424 let start = Instant::now();
425
426 let mut response = ModeResponse::new(input.to_string(), self.id().to_string());
428
429 if input.contains("generate") || input.contains("create") || input.contains("build") {
431 response.add_action(ModeAction::GenerateCode {
432 spec: input.to_string(),
433 });
434 }
435
436 if input.contains("file") || input.contains("modify") {
438 response.add_action(ModeAction::ModifyFile {
439 path: std::path::PathBuf::from("generated.rs"),
440 diff: "// Generated code".to_string(),
441 });
442 }
443
444 if input.contains("spec") || input.contains("formal") {
446 response.add_action(ModeAction::SuggestMode {
447 mode: "code".to_string(),
448 reason: "Consider Code Mode for spec-driven development".to_string(),
449 });
450 }
451
452 self.add_warnings_to_response(&mut response);
454
455 response.metadata.duration = start.elapsed();
457 response.metadata.think_more_used = context.think_more_enabled;
458
459 Ok(response)
460 }
461
462 fn capabilities(&self) -> Vec<Capability> {
463 self.config.capabilities.clone()
464 }
465
466 fn config(&self) -> &ModeConfig {
467 &self.config
468 }
469
470 fn can_execute(&self, operation: &Operation) -> bool {
471 matches!(
472 operation,
473 Operation::GenerateCode | Operation::ModifyFile | Operation::AnswerQuestion
474 )
475 }
476
477 fn constraints(&self) -> ModeConstraints {
478 self.config.constraints.clone()
479 }
480}
481
482#[cfg(test)]
483mod tests {
484 use super::*;
485
486 #[test]
487 fn test_vibe_mode_creation() {
488 let mode = VibeMode::new();
489 assert_eq!(mode.id(), "vibe");
490 assert_eq!(mode.name(), "Vibe Mode");
491 }
492
493 #[test]
494 fn test_vibe_mode_capabilities() {
495 let mode = VibeMode::new();
496 let capabilities = mode.capabilities();
497 assert!(capabilities.contains(&Capability::CodeGeneration));
498 assert!(capabilities.contains(&Capability::CodeModification));
499 assert!(capabilities.contains(&Capability::FileOperations));
500 assert!(capabilities.contains(&Capability::FreeformChat));
501 assert!(capabilities.contains(&Capability::QuestionAnswering));
502 assert!(capabilities.contains(&Capability::SpecConversion));
503 }
504
505 #[test]
506 fn test_vibe_mode_can_execute() {
507 let mode = VibeMode::new();
508 assert!(mode.can_execute(&Operation::GenerateCode));
509 assert!(mode.can_execute(&Operation::ModifyFile));
510 assert!(mode.can_execute(&Operation::AnswerQuestion));
511 assert!(!mode.can_execute(&Operation::ExecuteCommand));
512 assert!(!mode.can_execute(&Operation::RunTests));
513 assert!(!mode.can_execute(&Operation::ValidateQuality));
514 }
515
516 #[test]
517 fn test_vibe_mode_constraints() {
518 let mode = VibeMode::new();
519 let constraints = mode.constraints();
520 assert!(constraints.allow_file_operations);
521 assert!(!constraints.allow_command_execution);
522 assert!(constraints.allow_code_generation);
523 assert!(!constraints.require_specs);
524 assert_eq!(constraints.auto_think_more_threshold, None);
525 }
526
527 #[test]
528 fn test_vibe_mode_system_prompt() {
529 let mode = VibeMode::new();
530 let prompt = mode.system_prompt();
531 assert!(prompt.contains("creative coding partner"));
532 assert!(prompt.contains("rapid"));
533 assert!(prompt.contains("Bypass formal specifications"));
534 }
535
536 #[tokio::test]
537 async fn test_vibe_mode_process() {
538 let mode = VibeMode::new();
539 let context = ModeContext::new("test-session".to_string());
540 let response = mode.process("create a function", &context).await.unwrap();
541 assert_eq!(response.content, "create a function");
542 assert_eq!(response.metadata.mode, "vibe");
543 assert!(!response.metadata.think_more_used);
544 assert!(!response.actions.is_empty());
545 }
546
547 #[tokio::test]
548 async fn test_vibe_mode_process_with_think_more() {
549 let mode = VibeMode::new();
550 let mut context = ModeContext::new("test-session".to_string());
551 context.think_more_enabled = true;
552 let response = mode.process("create a function", &context).await.unwrap();
553 assert!(response.metadata.think_more_used);
554 }
555
556 #[tokio::test]
557 async fn test_vibe_mode_process_includes_warnings() {
558 let mode = VibeMode::new();
559 let context = ModeContext::new("test-session".to_string());
560 let response = mode.process("test input", &context).await.unwrap();
561 assert!(!response.suggestions.is_empty());
562 assert!(response
564 .suggestions
565 .iter()
566 .any(|s| s.contains("⚠️") || s.contains("💡")));
567 }
568
569 #[test]
570 fn test_vibe_mode_default() {
571 let mode = VibeMode::default();
572 assert_eq!(mode.id(), "vibe");
573 }
574
575 #[test]
576 fn test_vibe_mode_with_custom_config() {
577 let custom_config = ModeConfig {
578 temperature: 0.8,
579 max_tokens: 2048,
580 system_prompt: "Custom prompt".to_string(),
581 capabilities: vec![Capability::CodeGeneration],
582 constraints: ModeConstraints {
583 allow_file_operations: true,
584 allow_command_execution: false,
585 allow_code_generation: true,
586 require_specs: false,
587 auto_think_more_threshold: None,
588 },
589 };
590 let mode = VibeMode::with_config(custom_config);
591 assert_eq!(mode.config().temperature, 0.8);
592 assert_eq!(mode.config().max_tokens, 2048);
593 }
594
595 #[test]
596 fn test_generate_code_from_description() {
597 let mode = VibeMode::new();
598 let description = "Create a function that adds two numbers";
599 let result = mode.generate_code_from_description(description);
600 assert!(result.is_ok());
601 let code = result.unwrap();
602 assert!(code.contains("Generated from description"));
603 assert!(code.contains(description));
604 }
605
606 #[test]
607 fn test_iterate_rapidly() {
608 let mode = VibeMode::new();
609 let iteration = "Add error handling";
610 let result = mode.iterate_rapidly(iteration);
611 assert!(result.is_ok());
612 let code = result.unwrap();
613 assert!(code.contains("Rapid iteration"));
614 assert!(code.contains(iteration));
615 }
616
617 #[test]
618 fn test_convert_to_specs() {
619 let mode = VibeMode::new();
620 let code = "fn main() { println!(\"Hello\"); }";
621 let result = mode.convert_to_specs(code);
622 assert!(result.is_ok());
623 let spec = result.unwrap();
624 assert!(spec.contains("Generated Specification"));
625 assert!(spec.contains("auto-generated from Vibe Mode"));
626 assert!(spec.contains(code));
627 }
628
629 #[test]
630 fn test_generate_warnings() {
631 let mode = VibeMode::new();
632 let warnings = mode.generate_warnings();
633 assert!(!warnings.is_empty());
634 assert!(warnings.iter().any(|w| w.contains("⚠️")));
635 assert!(warnings.iter().any(|w| w.contains("specification")));
636 assert!(warnings.iter().any(|w| w.contains("testing")));
637 }
638
639 #[tokio::test]
640 async fn test_add_warnings_to_response() {
641 let mode = VibeMode::new();
642 let mut response = ModeResponse::new("test".to_string(), "vibe".to_string());
643 let initial_suggestions = response.suggestions.len();
644 mode.add_warnings_to_response(&mut response);
645 assert!(response.suggestions.len() > initial_suggestions);
646 }
647
648 #[test]
649 fn test_validate_operation_allowed() {
650 let mode = VibeMode::new();
651 assert!(mode.validate_operation(&Operation::GenerateCode).is_ok());
652 assert!(mode.validate_operation(&Operation::ModifyFile).is_ok());
653 assert!(mode.validate_operation(&Operation::AnswerQuestion).is_ok());
654 }
655
656 #[test]
657 fn test_validate_operation_blocked_execute_command() {
658 let mode = VibeMode::new();
659 let result = mode.validate_operation(&Operation::ExecuteCommand);
660 assert!(result.is_err());
661 }
662
663 #[test]
664 fn test_validate_operation_blocked_run_tests() {
665 let mode = VibeMode::new();
666 let result = mode.validate_operation(&Operation::RunTests);
667 assert!(result.is_err());
668 }
669
670 #[test]
671 fn test_validate_operation_blocked_validate_quality() {
672 let mode = VibeMode::new();
673 let result = mode.validate_operation(&Operation::ValidateQuality);
674 assert!(result.is_err());
675 }
676
677 #[test]
678 fn test_provide_best_practices() {
679 let mode = VibeMode::new();
680 let practices = mode.provide_best_practices();
681 assert!(!practices.is_empty());
682 assert!(practices.iter().any(|p| p.contains("prototyping")));
683 assert!(practices.iter().any(|p| p.contains("spec-driven")));
684 assert!(practices.iter().any(|p| p.contains("tests")));
685 }
686
687 #[tokio::test]
688 async fn test_process_with_generate_keyword() {
689 let mode = VibeMode::new();
690 let context = ModeContext::new("test-session".to_string());
691 let response = mode.process("generate a function", &context).await.unwrap();
692 assert!(!response.actions.is_empty());
693 }
694
695 #[tokio::test]
696 async fn test_process_with_file_keyword() {
697 let mode = VibeMode::new();
698 let context = ModeContext::new("test-session".to_string());
699 let response = mode.process("modify file", &context).await.unwrap();
700 assert!(!response.actions.is_empty());
701 }
702
703 #[tokio::test]
704 async fn test_process_with_spec_keyword() {
705 let mode = VibeMode::new();
706 let context = ModeContext::new("test-session".to_string());
707 let response = mode.process("convert to spec", &context).await.unwrap();
708 assert!(!response.actions.is_empty());
709 }
710
711 #[test]
712 fn test_generate_with_iterations() {
713 let mode = VibeMode::new();
714 let description = "Create a function";
715 let result = mode.generate_with_iterations(description, 3);
716 assert!(result.is_ok());
717 let code = result.unwrap();
718 assert!(code.contains("Iteration 1"));
719 assert!(code.contains("Iteration 2"));
720 assert!(code.contains("Iteration 3"));
721 }
722
723 #[test]
724 fn test_accept_natural_language() {
725 let mode = VibeMode::new();
726 let input = "Create a function that adds two numbers";
727 let result = mode.accept_natural_language(input);
728 assert!(result.is_ok());
729 let code = result.unwrap();
730 assert!(code.contains("Natural language input"));
731 assert!(code.contains("without formal specs"));
732 assert!(code.contains(input));
733 }
734
735 #[test]
736 fn test_accept_natural_language_blocked_when_specs_required() {
737 let custom_config = ModeConfig {
738 temperature: 0.9,
739 max_tokens: 4096,
740 system_prompt: "Test".to_string(),
741 capabilities: vec![Capability::CodeGeneration],
742 constraints: ModeConstraints {
743 allow_file_operations: true,
744 allow_command_execution: false,
745 allow_code_generation: true,
746 require_specs: true,
747 auto_think_more_threshold: None,
748 },
749 };
750 let mode = VibeMode::with_config(custom_config);
751 let result = mode.accept_natural_language("test input");
752 assert!(result.is_err());
753 }
754
755 #[test]
756 fn test_generate_code_from_description_blocked_when_disabled() {
757 let custom_config = ModeConfig {
758 temperature: 0.9,
759 max_tokens: 4096,
760 system_prompt: "Test".to_string(),
761 capabilities: vec![],
762 constraints: ModeConstraints {
763 allow_file_operations: true,
764 allow_command_execution: false,
765 allow_code_generation: false,
766 require_specs: false,
767 auto_think_more_threshold: None,
768 },
769 };
770 let mode = VibeMode::with_config(custom_config);
771 let result = mode.generate_code_from_description("test");
772 assert!(result.is_err());
773 }
774
775 #[test]
776 fn test_iterate_rapidly_blocked_when_disabled() {
777 let custom_config = ModeConfig {
778 temperature: 0.9,
779 max_tokens: 4096,
780 system_prompt: "Test".to_string(),
781 capabilities: vec![],
782 constraints: ModeConstraints {
783 allow_file_operations: true,
784 allow_command_execution: false,
785 allow_code_generation: false,
786 require_specs: false,
787 auto_think_more_threshold: None,
788 },
789 };
790 let mode = VibeMode::with_config(custom_config);
791 let result = mode.iterate_rapidly("test");
792 assert!(result.is_err());
793 }
794
795 #[test]
796 fn test_generate_with_iterations_blocked_when_disabled() {
797 let custom_config = ModeConfig {
798 temperature: 0.9,
799 max_tokens: 4096,
800 system_prompt: "Test".to_string(),
801 capabilities: vec![],
802 constraints: ModeConstraints {
803 allow_file_operations: true,
804 allow_command_execution: false,
805 allow_code_generation: false,
806 require_specs: false,
807 auto_think_more_threshold: None,
808 },
809 };
810 let mode = VibeMode::with_config(custom_config);
811 let result = mode.generate_with_iterations("test", 3);
812 assert!(result.is_err());
813 }
814
815 #[test]
816 fn test_preserve_code_and_context() {
817 let mode = VibeMode::new();
818 let code = "fn main() {}";
819 let context = ModeContext::new("test-session".to_string());
820 let result = mode.preserve_code_and_context(code, &context);
821 assert!(result.is_ok());
822 let preserved = result.unwrap();
823 assert!(preserved.contains("Preserved Context"));
824 assert!(preserved.contains("test-session"));
825 assert!(preserved.contains("Preserved Code"));
826 assert!(preserved.contains(code));
827 }
828
829 #[test]
830 fn test_preserve_code_and_context_with_project_path() {
831 let mode = VibeMode::new();
832 let code = "fn main() {}";
833 let mut context = ModeContext::new("test-session".to_string());
834 context.project_path = Some(std::path::PathBuf::from("/path/to/project"));
835 let result = mode.preserve_code_and_context(code, &context);
836 assert!(result.is_ok());
837 let preserved = result.unwrap();
838 assert!(preserved.contains("/path/to/project"));
839 }
840
841 #[test]
842 fn test_generate_specs_from_code() {
843 let mode = VibeMode::new();
844 let code = "fn add(a: i32, b: i32) -> i32 { a + b }\nstruct Point { x: i32, y: i32 }";
845 let result = mode.generate_specs_from_code(code);
846 assert!(result.is_ok());
847 let spec = result.unwrap();
848 assert!(spec.contains("Auto-Generated Specification"));
849 assert!(spec.contains("Functions"));
850 assert!(spec.contains("Data Structures"));
851 assert!(spec.contains("Requirements"));
852 }
853
854 #[test]
855 fn test_generate_specs_from_code_with_functions() {
856 let mode = VibeMode::new();
857 let code = "fn add(a: i32, b: i32) -> i32 { a + b }";
858 let result = mode.generate_specs_from_code(code);
859 assert!(result.is_ok());
860 let spec = result.unwrap();
861 assert!(spec.contains("Functions"));
862 assert!(spec.contains("fn add"));
863 }
864
865 #[test]
866 fn test_generate_specs_from_code_with_structs() {
867 let mode = VibeMode::new();
868 let code = "struct Point { x: i32, y: i32 }";
869 let result = mode.generate_specs_from_code(code);
870 assert!(result.is_ok());
871 let spec = result.unwrap();
872 assert!(spec.contains("Data Structures"));
873 assert!(spec.contains("struct Point"));
874 }
875
876 #[test]
877 fn test_convert_project_to_specs() {
878 let mode = VibeMode::new();
879 let code = "fn main() {}";
880 let context = ModeContext::new("test-session".to_string());
881 let result = mode.convert_project_to_specs(code, &context);
882 assert!(result.is_ok());
883 let conversion = result.unwrap();
884 assert!(conversion.contains("Vibe Mode to Spec-Driven Conversion"));
885 assert!(conversion.contains("Preserved Context"));
886 assert!(conversion.contains("Generated Specification"));
887 }
888
889 #[test]
890 fn test_convert_project_to_specs_preserves_all_data() {
891 let mode = VibeMode::new();
892 let code = "fn add(a: i32, b: i32) -> i32 { a + b }";
893 let mut context = ModeContext::new("test-session".to_string());
894 context.project_path = Some(std::path::PathBuf::from("/project"));
895 let result = mode.convert_project_to_specs(code, &context);
896 assert!(result.is_ok());
897 let conversion = result.unwrap();
898 assert!(conversion.contains("test-session"));
899 assert!(conversion.contains("/project"));
900 assert!(conversion.contains(code));
901 }
902
903 #[test]
904 fn test_generate_specific_warnings_production() {
905 let mode = VibeMode::new();
906 let warnings = mode.generate_specific_warnings("production");
907 assert!(!warnings.is_empty());
908 assert!(warnings.iter().any(|w| w.contains("production")));
909 }
910
911 #[test]
912 fn test_generate_specific_warnings_test() {
913 let mode = VibeMode::new();
914 let warnings = mode.generate_specific_warnings("test");
915 assert!(!warnings.is_empty());
916 assert!(warnings.iter().any(|w| w.contains("testing")));
917 }
918
919 #[test]
920 fn test_generate_specific_warnings_quality() {
921 let mode = VibeMode::new();
922 let warnings = mode.generate_specific_warnings("quality");
923 assert!(!warnings.is_empty());
924 assert!(warnings.iter().any(|w| w.contains("quality")));
925 }
926
927 #[test]
928 fn test_format_warnings() {
929 let mode = VibeMode::new();
930 let warnings = vec!["Warning 1".to_string(), "Warning 2".to_string()];
931 let formatted = mode.format_warnings(&warnings);
932 assert!(formatted.contains("Vibe Mode Warnings"));
933 assert!(formatted.contains("Warning 1"));
934 assert!(formatted.contains("Warning 2"));
935 }
936
937 #[tokio::test]
938 async fn test_add_specific_warnings_to_response() {
939 let mode = VibeMode::new();
940 let mut response = ModeResponse::new("test".to_string(), "vibe".to_string());
941 let initial_suggestions = response.suggestions.len();
942 mode.add_specific_warnings_to_response(&mut response, "production");
943 assert!(response.suggestions.len() > initial_suggestions);
944 assert!(response
945 .suggestions
946 .iter()
947 .any(|s| s.contains("production")));
948 }
949
950 #[test]
951 fn test_warnings_include_best_practices() {
952 let mode = VibeMode::new();
953 let warnings = mode.generate_warnings();
954 assert!(warnings.iter().any(|w| w.contains("💡")));
955 assert!(warnings.iter().any(|w| w.contains("Best Practice")));
956 }
957
958 #[test]
959 fn test_warnings_include_limitations() {
960 let mode = VibeMode::new();
961 let warnings = mode.generate_warnings();
962 assert!(warnings.iter().any(|w| w.contains("⚠️")));
963 assert!(warnings.iter().any(|w| w.contains("specifications")));
964 assert!(warnings.iter().any(|w| w.contains("testing")));
965 }
966}