systemprompt_agent/models/
skill.rs1use anyhow::{Result, anyhow};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use systemprompt_database::JsonRow;
5use systemprompt_identifiers::{CategoryId, SkillId, SourceId};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
8pub struct Skill {
9 #[serde(rename = "skill_id")]
10 pub id: SkillId,
11 pub file_path: String,
12 pub name: String,
13 pub description: String,
14 pub instructions: String,
15 pub enabled: bool,
16 pub tags: Vec<String>,
17 pub category_id: Option<CategoryId>,
18 pub source_id: SourceId,
19 pub created_at: DateTime<Utc>,
20 pub updated_at: DateTime<Utc>,
21}
22
23impl Skill {
24 pub fn from_json_row(row: &JsonRow) -> Result<Self> {
25 let id = SkillId::new(
26 row.get("skill_id")
27 .and_then(|v| v.as_str())
28 .ok_or_else(|| anyhow!("Missing skill_id"))?,
29 );
30
31 let file_path = row
32 .get("file_path")
33 .and_then(|v| v.as_str())
34 .ok_or_else(|| anyhow!("Missing file_path"))?
35 .to_string();
36
37 let name = row
38 .get("name")
39 .and_then(|v| v.as_str())
40 .ok_or_else(|| anyhow!("Missing name"))?
41 .to_string();
42
43 let description = row
44 .get("description")
45 .and_then(|v| v.as_str())
46 .ok_or_else(|| anyhow!("Missing description"))?
47 .to_string();
48
49 let instructions = row
50 .get("instructions")
51 .and_then(|v| v.as_str())
52 .ok_or_else(|| anyhow!("Missing instructions"))?
53 .to_string();
54
55 let enabled = row
56 .get("enabled")
57 .and_then(serde_json::Value::as_bool)
58 .ok_or_else(|| anyhow!("Missing enabled"))?;
59
60 let tags = row
61 .get("tags")
62 .and_then(|v| v.as_array())
63 .map_or_else(Vec::new, |arr| {
64 arr.iter()
65 .filter_map(|v| v.as_str().map(String::from))
66 .collect()
67 });
68
69 let category_id = row
70 .get("category_id")
71 .and_then(|v| v.as_str())
72 .map(CategoryId::new);
73
74 let source_id = SourceId::new(
75 row.get("source_id")
76 .and_then(|v| v.as_str())
77 .ok_or_else(|| anyhow!("Missing source_id"))?,
78 );
79
80 let created_at = row
81 .get("created_at")
82 .and_then(systemprompt_database::parse_database_datetime)
83 .ok_or_else(|| anyhow!("Missing or invalid created_at"))?;
84
85 let updated_at = row
86 .get("updated_at")
87 .and_then(systemprompt_database::parse_database_datetime)
88 .ok_or_else(|| anyhow!("Missing or invalid updated_at"))?;
89
90 Ok(Self {
91 id,
92 file_path,
93 name,
94 description,
95 instructions,
96 enabled,
97 tags,
98 category_id,
99 source_id,
100 created_at,
101 updated_at,
102 })
103 }
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
107pub struct SkillMetadata {
108 pub id: SkillId,
109 pub name: String,
110 pub description: String,
111 pub enabled: bool,
112 pub file: String,
113 pub assigned_agents: Vec<String>,
114 pub tags: Vec<String>,
115}