gitdataai/libs/agent/skills/mod.rs

155 lines
5.2 KiB
Rust

//! Built-in skills for the AI agent.
//!
//! This module provides pre-defined, system-level skills that can be
//! automatically enabled for projects or selectively injected based on context.
//!
//! # Built-in Skills
//!
//! ## Git Operations
//! - `git-log`: Analyze commit history and understand code evolution
//! - `git-diff`: Understand code changes between commits or branches
//! - `git-branch`: Manage branches and understand branch relationships
//! - `file-reader`: Read file contents and search for patterns in code
//!
//! ## Code Quality
//! - `code-review`: Expert code review with security, performance, and quality checks
//! - `code-explainer`: Explain complex code in simple, accessible terms
//!
//! ## Project Management
//! - `repo-manager`: List, create, and manage project repositories
//! - `issue-manager`: Manage issues with triage, labels, and priorities
//! - `board-manager`: Manage project boards, cards, and kanban workflows
//! - `member-manager`: Manage team members, roles, and permissions
//!
//! ## Development Productivity
//! - `pr-summary`: Generate clear PR summaries
//! - `issue-triage`: Classify and prioritize issues
//! - `doc-generator`: Generate README and API documentation
//! - `test-generator`: Write comprehensive unit tests
//! - `commit-message`: Generate conventional commit messages
//!
//! ## Utilities
//! - `http-requester`: Make HTTP requests and test APIs
//!
//! # Trigger System
//!
//! Skills are activated through three mechanisms:
//!
//! ## 1. Active Triggers (Highest Priority)
//! User explicitly invokes a skill:
//! - `用 code-review` / `use code-review`
//! - `@code-review` / `skill:code-review`
//! - Natural language: "帮我做 code review"
//!
//! ## 2. Passive Triggers (Medium Priority)
//! Tool calls trigger related skills:
//! - Tool `git_diff` called → activates `git-diff` skill
//! - Tool `list_issues_exec` called → activates `issue-manager` skill
//!
//! ## 3. Auto Triggers (Background)
//! Keyword matching based on conversation context:
//! - Configurable overlap threshold (default: 0.15)
//! - Maximum auto-injected skills (default: 3)
//!
//! # Usage
//!
//! ```rust,ignore
//! use agent::{get_skill, is_built_in_skill, all_skill_slugs};
//!
//! // Check if a slug is a built-in skill
//! if is_built_in_skill("code-review") {
//! let skill = get_skill("code-review").unwrap();
//! // Use skill.name, skill.description, skill.content
//! }
//!
//! // List all built-in skills
//! for slug in all_skill_slugs() {
//! println!("Available: {}", slug);
//! }
//! ```
mod templates;
pub use templates::BuiltInSkill;
pub use templates::SKILL_TEMPLATES;
/// Get a built-in skill by its slug.
pub fn get_skill(slug: &str) -> Option<&'static BuiltInSkill> {
SKILL_TEMPLATES.get(slug)
}
/// Get all built-in skill slugs.
pub fn all_skill_slugs() -> impl Iterator<Item = &'static str> {
SKILL_TEMPLATES.keys().copied()
}
/// Get all built-in skills.
pub fn all_skills() -> impl Iterator<Item = &'static BuiltInSkill> {
SKILL_TEMPLATES.values()
}
/// Check if a slug corresponds to a built-in skill.
pub fn is_built_in_skill(slug: &str) -> bool {
SKILL_TEMPLATES.contains_key(slug)
}
/// Check if a tool name should trigger any built-in skill.
/// Returns the skill slug if found.
pub fn get_skill_by_tool(tool_name: &str) -> Option<&'static BuiltInSkill> {
for skill in SKILL_TEMPLATES.values() {
if skill.trigger_tools.iter().any(|t| *t == tool_name) {
return Some(skill);
}
}
None
}
/// Check if any keyword matches a built-in skill.
/// Returns the best matching skill based on keyword overlap.
pub fn match_skill_by_keyword(keywords: &[&str]) -> Option<&'static BuiltInSkill> {
let mut best_match: Option<&BuiltInSkill> = None;
let mut best_score = 0;
for skill in SKILL_TEMPLATES.values() {
let score = skill
.trigger_keywords
.iter()
.filter(|kw| {
keywords
.iter()
.any(|k| k.to_lowercase().contains(&kw.to_lowercase()))
})
.count();
if score > best_score {
best_score = score;
best_match = Some(skill);
}
}
if best_score > 0 { best_match } else { None }
}
/// Get skills grouped by category.
pub fn skills_by_category() -> std::collections::HashMap<&'static str, Vec<&'static BuiltInSkill>> {
let mut categories: std::collections::HashMap<&'static str, Vec<&'static BuiltInSkill>> =
std::collections::HashMap::new();
for skill in SKILL_TEMPLATES.values() {
let category = match skill.slug {
"git-log" | "git-diff" | "git-branch" => "Git Operations",
"code-review" | "code-explainer" => "Code Quality",
"repo-manager" | "issue-manager" | "board-manager" | "member-manager" => {
"Project Management"
}
"pr-summary" | "issue-triage" | "doc-generator" | "test-generator"
| "commit-message" => "Development Productivity",
"file-reader" | "http-requester" => "Utilities",
_ => "Other",
};
categories.entry(category).or_default().push(skill);
}
categories
}