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}