Skip to main content

cosh_tools/skills/
types.rs

1//! All public and internal types for the skill reader tool.
2
3use std::path::PathBuf;
4
5use schemars::JsonSchema;
6use serde::{Deserialize, Serialize};
7use thiserror::Error;
8
9// Public types
10
11/// Input for `skills_read`.
12#[derive(Debug, Clone, Deserialize, JsonSchema)]
13pub struct SkillsReadInput {
14    /// Name of the skill to read.
15    pub name: String,
16}
17
18/// Input for `skills_read_asset`.
19#[derive(Debug, Clone, Deserialize, JsonSchema)]
20pub struct SkillsReadAssetInput {
21    /// Name of the skill that owns the asset.
22    pub name: String,
23    /// Relative path to the asset file within the skill directory.
24    pub asset_path: String,
25}
26
27/// Input for `skills_match_skills`.
28#[derive(Debug, Clone, Deserialize, JsonSchema)]
29pub struct SkillsMatchInput {
30    /// File paths to match against skill glob patterns.
31    pub match_paths: Vec<String>,
32}
33
34/// Lightweight metadata returned in list / match results and system prompts.
35#[derive(Debug, Clone, Serialize)]
36pub struct SkillInfo {
37    pub name: String,
38    pub description: String,
39}
40
41/// Full skill content returned by the `read` action.
42#[derive(Debug, Clone, Serialize)]
43pub struct SkillContent {
44    pub info: SkillInfo,
45    /// SKILL.md body with frontmatter stripped.
46    pub body: String,
47}
48
49/// Where to look for skills.
50#[derive(Debug, Clone)]
51pub enum SkillSource {
52    /// A directory on the local filesystem that contains skill subdirectories.
53    Directory { path: String },
54    /// An in-memory skill provided directly by the caller.
55    Embedded { skill: EmbeddedSkill },
56}
57
58/// An inline skill that does not require filesystem access.
59#[derive(Debug, Clone)]
60pub struct EmbeddedSkill {
61    pub name: String,
62    pub description: String,
63    /// Full SKILL.md content, including frontmatter and body.
64    pub content: String,
65    pub globs: Vec<String>,
66    pub always_apply: bool,
67}
68
69/// Actions the tool can perform.
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub enum SkillAction {
72    List,
73    Read,
74    ReadAsset,
75    Match,
76}
77
78/// The schema passed by the caller — carries all policy.
79///
80/// Zero hardcoded paths, names, or policies. Everything is supplied here.
81#[derive(Debug, Clone)]
82pub struct SkillSchema {
83    pub action: SkillAction,
84    /// Ordered list of sources. First source wins on name collision.
85    pub sources: Vec<SkillSource>,
86    /// Target skill name for `read` / `read_asset`.
87    pub skill_name: Option<String>,
88    /// Relative sub-path inside a skill directory for `read_asset`.
89    pub asset_path: Option<String>,
90    /// Active file paths to match skill globs against.
91    pub match_paths: Vec<String>,
92    /// Whether to scan directories recursively.
93    pub recursive: bool,
94    /// Glob-style skill name exclusions.
95    pub ignore: Vec<String>,
96    /// Allowlist — when non-empty, only skills whose name appears here are
97    /// returned. Empty means all skills pass.
98    pub include: Vec<String>,
99}
100
101/// Output of a skill tool invocation.
102#[derive(Debug, Clone, Serialize)]
103pub enum SkillOutput {
104    List { skills: Vec<SkillInfo> },
105    Read { skill: SkillContent },
106    ReadAsset { content: String },
107    Match { matched: Vec<SkillInfo> },
108}
109
110/// Error type for skill operations.
111#[derive(Debug, Error)]
112pub enum SkillError {
113    #[error("skill not found: {0}")]
114    NotFound(String),
115    #[error("path traversal detected: {0}")]
116    PathTraversal(String),
117    #[error("invalid action: {0}")]
118    InvalidAction(String),
119    #[error("invalid source: {0}")]
120    InvalidSource(String),
121}
122
123// Internal types (shared across sub-modules)
124
125/// Parsed frontmatter metadata from a SKILL.md file.
126#[derive(Debug, Default)]
127pub struct Frontmatter {
128    pub name: Option<String>,
129    pub description: Option<String>,
130    pub globs: Vec<String>,
131    pub always_apply: bool,
132}
133
134/// A discovered skill before dedup and output conversion.
135#[derive(Debug, Clone)]
136pub struct RawSkill {
137    pub source_key: String,
138    pub name: String,
139    pub description: String,
140    /// Directory containing SKILL.md (base for asset resolution).
141    pub base_dir: PathBuf,
142    /// Body with frontmatter stripped.
143    pub body: String,
144    pub globs: Vec<String>,
145    pub always_apply: bool,
146}