systemprompt_agent/models/
skill.rs1use anyhow::{anyhow, Result};
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 pub skill_id: SkillId,
10 pub file_path: String,
11 pub name: String,
12 pub description: String,
13 pub instructions: String,
14 pub enabled: bool,
15 pub tags: Vec<String>,
16 pub category_id: Option<CategoryId>,
17 pub source_id: SourceId,
18 pub created_at: DateTime<Utc>,
19 pub updated_at: DateTime<Utc>,
20}
21
22impl Skill {
23 pub fn from_json_row(row: &JsonRow) -> Result<Self> {
24 let skill_id = SkillId::new(
25 row.get("skill_id")
26 .and_then(|v| v.as_str())
27 .ok_or_else(|| anyhow!("Missing skill_id"))?,
28 );
29
30 let file_path = row
31 .get("file_path")
32 .and_then(|v| v.as_str())
33 .ok_or_else(|| anyhow!("Missing file_path"))?
34 .to_string();
35
36 let name = row
37 .get("name")
38 .and_then(|v| v.as_str())
39 .ok_or_else(|| anyhow!("Missing name"))?
40 .to_string();
41
42 let description = row
43 .get("description")
44 .and_then(|v| v.as_str())
45 .ok_or_else(|| anyhow!("Missing description"))?
46 .to_string();
47
48 let instructions = row
49 .get("instructions")
50 .and_then(|v| v.as_str())
51 .ok_or_else(|| anyhow!("Missing instructions"))?
52 .to_string();
53
54 let enabled = row
55 .get("enabled")
56 .and_then(|v| v.as_bool())
57 .ok_or_else(|| anyhow!("Missing enabled"))?;
58
59 let tags = row
60 .get("tags")
61 .and_then(|v| v.as_array())
62 .map(|arr| {
63 arr.iter()
64 .filter_map(|v| v.as_str().map(String::from))
65 .collect()
66 })
67 .unwrap_or_else(Vec::new);
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(|v| systemprompt_database::parse_database_datetime(v))
83 .ok_or_else(|| anyhow!("Missing or invalid created_at"))?;
84
85 let updated_at = row
86 .get("updated_at")
87 .and_then(|v| systemprompt_database::parse_database_datetime(v))
88 .ok_or_else(|| anyhow!("Missing or invalid updated_at"))?;
89
90 Ok(Self {
91 skill_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: String,
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}