Skip to main content

composio_sdk/wizard/
mod.rs

1//! Wizard instruction generation module
2//!
3//! This module provides utilities for extracting Composio Skills content
4//! and generating wizard instructions for AI agents. It integrates with the
5//! official Composio Skills repository to provide production-ready guidance
6//! based on best practices and anti-patterns.
7//!
8//! # Overview
9//!
10//! The wizard module consists of three main components:
11//!
12//! - **[`SkillsExtractor`]**: Extracts rules and best practices from the Composio Skills repository
13//! - **[`WizardInstructionGenerator`]**: Generates formatted wizard instructions for AI agents
14//! - **[`InstructionValidator`]**: Validates generated instructions against official patterns
15//!
16//! # Architecture
17//!
18//! ```text
19//! ┌─────────────────────────────────────────────────────────────┐
20//! │              Composio Skills Repository                      │
21//! │  (https://github.com/ComposioHQ/skills)                     │
22//! │  - AGENTS.md (consolidated reference)                        │
23//! │  - rules/tr-*.md (Tool Router rules)                        │
24//! │  - rules/triggers-*.md (Trigger rules)                      │
25//! └───────────────────────┬─────────────────────────────────────┘
26//!                         │
27//!                         │ extracts
28//!                         ▼
29//!                 ┌───────────────┐
30//!                 │ SkillsExtractor│
31//!                 └───────┬───────┘
32//!                         │
33//!          ┌──────────────┼──────────────┐
34//!          │              │              │
35//!          ▼              ▼              ▼
36//!   ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
37//!   │  Generator  │ │  Validator  │ │   Rules     │
38//!   └─────────────┘ └─────────────┘ └─────────────┘
39//! ```
40//!
41//! # Usage Examples
42//!
43//! ## Basic Usage: Generate Wizard Instructions
44//!
45//! ```rust,no_run
46//! use composio_sdk::wizard::{SkillsExtractor, WizardInstructionGenerator};
47//!
48//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
49//! // Skills are now bundled within the SDK
50//! // No need to specify external path - use the bundled skills
51//! let skills_path = concat!(env!("CARGO_MANIFEST_DIR"), "/skills");
52//! let skills = SkillsExtractor::new(skills_path);
53//!
54//! // Verify the Skills repository is accessible
55//! skills.verify_path()?;
56//!
57//! // Create the instruction generator
58//! let generator = WizardInstructionGenerator::new(skills);
59//!
60//! // Generate generic Composio instructions
61//! let instructions = generator.generate_composio_instructions(None)?;
62//! println!("{}", instructions);
63//!
64//! // Generate toolkit-specific instructions (e.g., for GitHub)
65//! let github_instructions = generator.generate_composio_instructions(Some("github"))?;
66//! println!("{}", github_instructions);
67//! # Ok(())
68//! # }
69//! ```
70//!
71//! ## Advanced Usage: Extract and Filter Rules
72//!
73//! ```rust,no_run
74//! use composio_sdk::wizard::{SkillsExtractor, Impact};
75//!
76//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
77//! // Skills are bundled within the SDK
78//! let skills_path = concat!(env!("CARGO_MANIFEST_DIR"), "/skills");
79//! let skills = SkillsExtractor::new(skills_path);
80//!
81//! // Get all Tool Router rules
82//! let tool_router_rules = skills.get_tool_router_rules()?;
83//! println!("Found {} Tool Router rules", tool_router_rules.len());
84//!
85//! // Get all Trigger rules
86//! let trigger_rules = skills.get_trigger_rules()?;
87//! println!("Found {} Trigger rules", trigger_rules.len());
88//!
89//! // Filter rules by tag
90//! let session_rules = skills.get_rules_by_tag("session")?;
91//! println!("Found {} session-related rules", session_rules.len());
92//!
93//! // Get consolidated content from AGENTS.md
94//! let consolidated = skills.get_consolidated_content()?;
95//! println!("Consolidated content: {} bytes", consolidated.len());
96//!
97//! // Inspect individual rules
98//! for rule in tool_router_rules.iter().take(5) {
99//!     println!("Rule: {}", rule.title);
100//!     println!("Impact: {:?}", rule.impact);
101//!     println!("Tags: {:?}", rule.tags);
102//!     println!("Correct examples: {}", rule.correct_examples.len());
103//!     println!("Incorrect examples: {}", rule.incorrect_examples.len());
104//!     println!("---");
105//! }
106//! # Ok(())
107//! # }
108//! ```
109//!
110//! ## Validation: Check Instructions Against Official Patterns
111//!
112//! ```rust,no_run
113//! use composio_sdk::wizard::{SkillsExtractor, InstructionValidator};
114//!
115//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
116//! // Skills are bundled within the SDK
117//! let skills_path = concat!(env!("CARGO_MANIFEST_DIR"), "/skills");
118//! let skills = SkillsExtractor::new(skills_path);
119//! let validator = InstructionValidator::new(skills);
120//!
121//! // Validate some instructions
122//! let instructions = r#"
123//! # Composio Integration Guide
124//!
125//! Always use composio.create(user_id) to create a session.
126//! Use session.tools() for native tool integration.
127//! "#;
128//!
129//! let result = validator.validate(instructions)?;
130//!
131//! if result.is_valid() {
132//!     println!("✓ Instructions are valid!");
133//! } else {
134//!     println!("✗ Validation failed:");
135//!     println!("{}", result.format());
136//! }
137//!
138//! if result.has_warnings() {
139//!     println!("⚠ Warnings found:");
140//!     println!("{}", result.format());
141//! }
142//!
143//! println!("Total issues: {}", result.total_issues());
144//! # Ok(())
145//! # }
146//! ```
147//!
148//! ## Working with Rules
149//!
150//! ```rust,no_run
151//! use composio_sdk::wizard::{Rule, Impact};
152//! use std::path::Path;
153//!
154//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
155//! // Load a rule from the bundled skills
156//! let skills_path = concat!(env!("CARGO_MANIFEST_DIR"), "/skills");
157//! let rule_path = format!("{}/rules/tr-001.md", skills_path);
158//! let rule = Rule::from_file(Path::new(&rule_path))?;
159//!
160//! println!("Title: {}", rule.title);
161//! println!("Impact: {:?}", rule.impact);
162//! println!("Description: {}", rule.description);
163//! println!("Tags: {:?}", rule.tags);
164//!
165//! // Access examples
166//! for (i, example) in rule.correct_examples.iter().enumerate() {
167//!     println!("✅ Correct example {}: {}", i + 1, example);
168//! }
169//!
170//! for (i, example) in rule.incorrect_examples.iter().enumerate() {
171//!     println!("❌ Incorrect example {}: {}", i + 1, example);
172//! }
173//! # Ok(())
174//! # }
175//! ```
176//!
177//! # Integration with Build Process
178//!
179//! The Skills content is now **bundled directly within the SDK** at `composio-sdk/skills/`.
180//! This means:
181//!
182//! 1. No external dependencies on vendor/skills repository
183//! 2. Skills content is always available at compile time
184//! 3. No need to clone or download Skills repository separately
185//! 4. SDK is fully self-contained
186//!
187//! The bundled Skills include:
188//! - `AGENTS.md` - Consolidated reference (150+ KB)
189//! - `SKILL.md` - Metadata
190//! - `rules/*.md` - 30+ rule files with best practices
191//!
192//! # Skills Repository Structure
193//!
194//! ```text
195//! composio-sdk/skills/
196//! ├── AGENTS.md              # Consolidated reference (150+ KB)
197//! ├── SKILL.md               # Metadata
198//! └── rules/
199//!     ├── tr-*.md            # Tool Router rules
200//!     ├── triggers-*.md      # Trigger rules
201//!     └── app-*.md           # Application rules
202//! ```
203//!
204//! # Rule Format
205//!
206//! Rules are markdown files with YAML frontmatter:
207//!
208//! ```markdown
209//! ---
210//! title: Always use composio.create(user_id)
211//! impact: critical
212//! tags: [session, user-scoping]
213//! ---
214//!
215//! # Description
216//! Always create sessions with user_id for proper isolation.
217//!
218//! ## Correct ✅
219//! ```python
220//! session = composio.create(user_id="user_123")
221//! ```
222//!
223//! ## Incorrect ❌
224//! ```python
225//! session = composio.create()  # Missing user_id
226//! ```
227//!
228//! # Impact Levels
229//!
230//! Rules are categorized by impact:
231//!
232//! - **Critical**: Must be followed, causes failures if violated
233//! - **High**: Should be followed, causes issues if violated
234//! - **Medium**: Recommended, improves quality
235//! - **Low**: Optional, nice to have
236//!
237//! # Error Handling
238//!
239//! All operations return `Result<T, SkillsError>` for proper error handling:
240//!
241//! ```rust,no_run
242//! use composio_sdk::wizard::{SkillsExtractor, SkillsError};
243//!
244//! # fn main() {
245//! // Skills are bundled within the SDK
246//! let skills_path = concat!(env!("CARGO_MANIFEST_DIR"), "/skills");
247//! let skills = SkillsExtractor::new(skills_path);
248//!
249//! match skills.verify_path() {
250//!     Ok(_) => println!("Skills repository found"),
251//!     Err(SkillsError::PathNotFound(path)) => {
252//!         eprintln!("Skills repository not found at: {}", path.display());
253//!     }
254//!     Err(e) => eprintln!("Error: {}", e),
255//! }
256//! # }
257//! ```
258
259mod generator;
260mod skills;
261mod validator;
262
263pub use generator::WizardInstructionGenerator;
264pub use skills::{Impact, Rule, SkillsExtractor, SkillsError};
265pub use validator::{InstructionValidator, ValidationResult};
266
267/// Generate wizard instructions for Composio integration
268///
269/// This is a convenience function that creates a SkillsExtractor and
270/// WizardInstructionGenerator, then generates comprehensive wizard instructions
271/// for AI agents using Composio Skills content.
272///
273/// # Arguments
274///
275/// * `toolkit` - Optional toolkit name for context-aware instructions (e.g., "github", "gmail", "slack")
276///
277/// # Returns
278///
279/// A formatted markdown string with wizard instructions, or an error if the Skills
280/// repository is not accessible or parsing fails.
281///
282/// # Examples
283///
284/// ## Generate Generic Instructions
285///
286/// ```no_run
287/// use composio_sdk::wizard::generate_wizard_instructions;
288///
289/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
290/// // Generate generic Composio instructions
291/// let instructions = generate_wizard_instructions(None)?;
292/// println!("{}", instructions);
293/// # Ok(())
294/// # }
295/// ```
296///
297/// ## Generate Toolkit-Specific Instructions
298///
299/// ```no_run
300/// use composio_sdk::wizard::generate_wizard_instructions;
301///
302/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
303/// // Generate GitHub-specific instructions
304/// let github_instructions = generate_wizard_instructions(Some("github"))?;
305/// println!("{}", github_instructions);
306///
307/// // Generate Gmail-specific instructions
308/// let gmail_instructions = generate_wizard_instructions(Some("gmail"))?;
309/// println!("{}", gmail_instructions);
310///
311/// // Generate Slack-specific instructions
312/// let slack_instructions = generate_wizard_instructions(Some("slack"))?;
313/// println!("{}", slack_instructions);
314/// # Ok(())
315/// # }
316/// ```
317///
318/// # Skills Repository
319///
320/// This function uses the Skills content bundled within the SDK at
321/// `composio-sdk/skills/`. The Skills are included at compile time,
322/// making the SDK fully self-contained.
323///
324/// If the Skills directory is not found, the function will return a
325/// `SkillsError::PathNotFound` error.
326///
327/// # Generated Content
328///
329/// The generated instructions include:
330///
331/// - **Overview**: Introduction from AGENTS.md consolidated reference
332/// - **Critical Rules**: Must-follow rules with CRITICAL impact
333/// - **Session Management**: Best practices for session creation and management
334/// - **Authentication**: Patterns for in-chat and manual authentication
335/// - **Toolkit-Specific Guidance**: Context-aware rules for the specified toolkit (if provided)
336///
337/// Each rule includes:
338/// - Description and impact level
339/// - Correct examples (✅)
340/// - Incorrect examples (❌)
341/// - Relevant tags
342///
343/// # Supported Toolkits
344///
345/// Common toolkits include:
346/// - `github` - GitHub integration
347/// - `gmail` - Gmail integration
348/// - `slack` - Slack integration
349/// - `jira` - Jira integration
350/// - `notion` - Notion integration
351/// - And 900+ more toolkits
352///
353/// For unknown toolkits, generic instructions are provided with a note that
354/// no toolkit-specific rules were found.
355///
356/// # Error Handling
357///
358/// ```no_run
359/// use composio_sdk::wizard::{generate_wizard_instructions, SkillsError};
360///
361/// # fn main() {
362/// match generate_wizard_instructions(Some("github")) {
363///     Ok(instructions) => {
364///         println!("Generated {} bytes of instructions", instructions.len());
365///         println!("{}", instructions);
366///     }
367///     Err(SkillsError::PathNotFound(path)) => {
368///         eprintln!("Skills repository not found at: {}", path.display());
369///         eprintln!("Run the build script to download it automatically.");
370///     }
371///     Err(e) => {
372///         eprintln!("Error generating instructions: {}", e);
373///     }
374/// }
375/// # }
376/// ```
377pub fn generate_wizard_instructions(toolkit: Option<&str>) -> Result<String, SkillsError> {
378    // Skills are now bundled within the SDK at compile time
379    let skills_path = concat!(env!("CARGO_MANIFEST_DIR"), "/skills");
380    
381    // Create SkillsExtractor
382    let skills = SkillsExtractor::new(skills_path);
383    
384    // Verify the Skills repository is accessible
385    skills.verify_path()?;
386    
387    // Create WizardInstructionGenerator
388    let generator = WizardInstructionGenerator::new(skills);
389    
390    // Generate instructions
391    generator.generate_composio_instructions(toolkit)
392}