miyabi_modes/
lib.rs

1//! Adaptive mode system for Miyabi - inspired by Roo-Code
2//!
3//! This crate provides a flexible mode system that allows users to define
4//! custom AI agent behaviors through YAML configuration files, similar to
5//! Roo-Code's `.roomodes` system.
6//!
7//! # Architecture
8//!
9//! - **MiyabiMode**: Core mode definition with role, tools, and instructions
10//! - **ModeLoader**: Loads modes from `.miyabi/modes/` directory
11//! - **ModeRegistry**: Thread-safe registry for managing modes
12//! - **ModeValidator**: Validates mode definitions
13//!
14//! # Example Usage
15//!
16//! ```no_run
17//! use miyabi_modes::{ModeLoader, ModeRegistry};
18//! use std::path::Path;
19//!
20//! # fn example() -> Result<(), Box<dyn std::error::Error>> {
21//! let loader = ModeLoader::new(Path::new("."));
22//! let registry = ModeRegistry::new();
23//!
24//! // Load all modes
25//! let modes = loader.load_all()?;
26//! registry.register_all(modes)?;
27//!
28//! // Get a specific mode
29//! if let Some(mode) = registry.get("codegen") {
30//!     println!("Found mode: {} ({})", mode.name, mode.character);
31//! }
32//! # Ok(())
33//! # }
34//! ```
35
36pub mod error;
37pub mod loader;
38pub mod mode;
39pub mod registry;
40pub mod template;
41pub mod tool_config;
42pub mod validator;
43
44// Re-exports for convenience
45pub use error::{ModeError, ModeResult};
46pub use loader::ModeLoader;
47pub use mode::{MiyabiMode, ToolGroup};
48pub use registry::ModeRegistry;
49pub use template::TemplateRenderer;
50pub use tool_config::{ToolConfig, ToolConfigSet};
51pub use validator::ModeValidator;
52
53#[cfg(test)]
54mod integration_tests {
55    use super::*;
56    use std::fs;
57    use tempfile::TempDir;
58
59    #[test]
60    fn test_full_workflow() {
61        // Setup test directory structure
62        let temp_dir = TempDir::new().unwrap();
63        let modes_dir = temp_dir.path().join(".miyabi/modes/system");
64        fs::create_dir_all(&modes_dir).unwrap();
65
66        // Create a test mode YAML
67        let yaml = r#"
68slug: test-mode
69name: "🧪 Test Mode"
70character: "てすとん"
71roleDefinition: "You are a test mode for validation and integration testing."
72whenToUse: "Use this mode for testing the mode system."
73groups:
74  - read
75  - edit
76  - command
77customInstructions: |-
78  Always write comprehensive tests.
79  Follow Rust best practices.
80source: "miyabi-core"
81fileRegex: ".*\\.rs$"
82"#;
83        fs::write(modes_dir.join("test-mode.yaml"), yaml).unwrap();
84
85        // Load modes
86        let loader = ModeLoader::new(temp_dir.path());
87        let modes = loader.load_all().unwrap();
88        assert_eq!(modes.len(), 1);
89
90        // Register modes
91        let registry = ModeRegistry::new();
92        registry.register_all(modes).unwrap();
93
94        // Verify registration
95        assert_eq!(registry.count(), 1);
96        assert!(registry.contains("test-mode"));
97
98        // Get mode
99        let mode = registry.get("test-mode").unwrap();
100        assert_eq!(mode.slug, "test-mode");
101        assert_eq!(mode.character, "てすとん");
102        assert!(mode.is_system_mode());
103
104        // Validate mode
105        assert!(ModeValidator::validate(&mode).is_ok());
106
107        // Test file matching
108        assert!(mode.matches_file("main.rs").unwrap());
109        assert!(!mode.matches_file("README.md").unwrap());
110
111        // Test tool group checking
112        assert!(mode.allows_tool(&ToolGroup::Read));
113        assert!(mode.allows_tool(&ToolGroup::Edit));
114        assert!(!mode.allows_tool(&ToolGroup::Browser));
115    }
116}