Skip to main content

systemprompt_models/services/
skills.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use super::IncludableString;
5use super::ai::ToolModelConfig;
6
7const fn default_true() -> bool {
8    true
9}
10
11pub const SKILL_CONFIG_FILENAME: &str = "config.yaml";
12pub const DEFAULT_SKILL_CONTENT_FILE: &str = "index.md";
13
14#[derive(Debug, Clone, Default, Serialize, Deserialize)]
15pub struct SkillsConfig {
16    #[serde(default = "default_true")]
17    pub enabled: bool,
18
19    #[serde(default)]
20    pub auto_discover: bool,
21
22    #[serde(default)]
23    pub skills_path: Option<String>,
24
25    #[serde(default)]
26    pub skills: HashMap<String, SkillConfig>,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct SkillConfig {
31    pub id: String,
32    pub name: String,
33    pub description: String,
34
35    #[serde(default = "default_true")]
36    pub enabled: bool,
37
38    #[serde(default)]
39    pub tags: Vec<String>,
40
41    #[serde(default)]
42    pub instructions: Option<IncludableString>,
43
44    #[serde(default)]
45    pub assigned_agents: Vec<String>,
46
47    #[serde(default)]
48    pub mcp_servers: Vec<String>,
49
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub model_config: Option<ToolModelConfig>,
52}
53
54#[derive(Debug, Clone, Deserialize)]
55pub struct DiskSkillConfig {
56    pub id: String,
57    pub name: String,
58    pub description: String,
59    #[serde(default = "default_true")]
60    pub enabled: bool,
61    #[serde(default)]
62    pub file: String,
63    #[serde(default)]
64    pub tags: Vec<String>,
65    #[serde(default)]
66    pub category: Option<String>,
67}
68
69impl DiskSkillConfig {
70    pub fn content_file(&self) -> &str {
71        if self.file.is_empty() {
72            DEFAULT_SKILL_CONTENT_FILE
73        } else {
74            &self.file
75        }
76    }
77}
78
79pub fn strip_frontmatter(content: &str) -> String {
80    let parts: Vec<&str> = content.splitn(3, "---").collect();
81    if parts.len() >= 3 {
82        parts[2].trim().to_string()
83    } else {
84        content.to_string()
85    }
86}