use serde::Deserialize;
use serde::Serialize;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SkillInfo {
pub name: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub path: Option<String>,
#[serde(default)]
pub builtin: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub content: Option<String>,
#[serde(flatten)]
pub extra: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SkillDirs {
#[serde(default)]
pub dirs: Vec<String>,
#[serde(flatten)]
pub extra: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SkillGetRequest {
pub name: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_skill_info_minimal() {
let json = r#"{"name": "code-review"}"#;
let skill: SkillInfo = serde_json::from_str(json).unwrap();
assert_eq!(skill.name, "code-review");
assert!(skill.description.is_none());
assert!(!skill.builtin);
}
#[test]
fn test_skill_info_full() {
let json = r#"{
"name": "code-review",
"description": "Review code for issues",
"path": "/skills/code-review.md",
"builtin": true,
"content": "Please review the following code..."
}"#;
let skill: SkillInfo = serde_json::from_str(json).unwrap();
assert_eq!(skill.name, "code-review");
assert_eq!(
skill.description,
Some("Review code for issues".to_string())
);
assert_eq!(skill.path, Some("/skills/code-review.md".to_string()));
assert!(skill.builtin);
assert!(skill.content.is_some());
}
#[test]
fn test_skill_dirs() {
let json = r#"{"dirs": ["/project/.opencode/skills", "/home/user/.opencode/skills"]}"#;
let dirs: SkillDirs = serde_json::from_str(json).unwrap();
assert_eq!(dirs.dirs.len(), 2);
}
#[test]
fn test_skill_extra_fields_preserved() {
let json = r#"{
"name": "test-skill",
"futureField": "value"
}"#;
let skill: SkillInfo = serde_json::from_str(json).unwrap();
assert_eq!(skill.extra["futureField"], "value");
}
}