Skip to main content

vtcode_core/skills/
model.rs

1use crate::skills::types::SkillManifest;
2use serde::{Deserialize, Serialize};
3use std::path::PathBuf;
4
5/// Skill scope indicating where the skill is defined
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default, Hash)]
7#[serde(rename_all = "snake_case")]
8pub enum SkillScope {
9    /// User-level skill (`~/.agents/skills`)
10    #[default]
11    User,
12    /// Repository-level skill (`.agents/skills`)
13    Repo,
14    /// System-level bundled skill
15    System,
16    /// Admin-level skill (`/etc/codex/skills`)
17    Admin,
18}
19
20#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
21pub struct SkillMetadata {
22    pub name: String,
23    pub description: String,
24    #[serde(default)]
25    pub short_description: Option<String>,
26    pub path: PathBuf,
27    pub scope: SkillScope,
28    #[serde(default)]
29    pub manifest: Option<Box<SkillManifest>>,
30}
31
32#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
33pub struct SkillErrorInfo {
34    pub path: PathBuf,
35    pub message: String,
36}
37
38#[derive(Debug, Clone, Default)]
39pub struct SkillLoadOutcome {
40    pub skills: Vec<SkillMetadata>,
41    pub errors: Vec<SkillErrorInfo>,
42}
43
44#[cfg(test)]
45mod tests {
46    use super::SkillMetadata;
47    use crate::skills::types::SkillManifest;
48
49    #[test]
50    fn boxed_manifest_is_smaller_than_inline_option() {
51        use std::mem::size_of;
52
53        assert!(size_of::<Option<Box<SkillManifest>>>() < size_of::<Option<SkillManifest>>());
54        assert!(size_of::<SkillMetadata>() < size_of::<SkillMetadataInlineManifest>());
55    }
56
57    #[expect(dead_code)]
58    struct SkillMetadataInlineManifest {
59        name: String,
60        description: String,
61        short_description: Option<String>,
62        path: std::path::PathBuf,
63        scope: super::SkillScope,
64        manifest: Option<SkillManifest>,
65    }
66}