oxios_kernel/skill/
format.rs1#![allow(missing_docs)]
2use std::path::Path;
5
6use serde::{Deserialize, Serialize};
7use serde_yaml::Value;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
11#[serde(rename_all = "snake_case")]
12pub enum SkillFormat {
13 Oxios,
14 OpenClaw,
15 ClaudeCode,
16 AgentSkills,
17}
18
19impl std::fmt::Display for SkillFormat {
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 match self {
22 SkillFormat::Oxios => write!(f, "oxios"),
23 SkillFormat::OpenClaw => write!(f, "openclaw"),
24 SkillFormat::ClaudeCode => write!(f, "claude_code"),
25 SkillFormat::AgentSkills => write!(f, "agent_skills"),
26 }
27 }
28}
29
30pub fn detect_format(value: &Value) -> SkillFormat {
31 if let Some(meta) = value.get("metadata") {
32 if meta.get("openclaw").is_some()
33 || meta.get("clawdbot").is_some()
34 || meta.get("clawdis").is_some()
35 {
36 return SkillFormat::OpenClaw;
37 }
38 }
39 for key in &[
40 "allowed-tools",
41 "arguments",
42 "when_to_use",
43 "argument-hint",
44 "effort",
45 "hooks",
46 "paths",
47 ] {
48 if value.get(*key).is_some() {
49 return SkillFormat::ClaudeCode;
50 }
51 }
52 for key in &[
53 "requires",
54 "install",
55 "primaryEnv",
56 "primary-env",
57 "skillKey",
58 "skill-key",
59 ] {
60 if value.get(*key).is_some() {
61 return SkillFormat::Oxios;
62 }
63 }
64 SkillFormat::AgentSkills
65}
66
67pub fn resolve_format(value: &Value, skill_dir: &Path) -> SkillFormat {
68 if skill_dir.join(".clawhub").join("origin.json").exists() {
69 return SkillFormat::OpenClaw;
70 }
71 detect_format(value)
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 #[test]
78 fn test_detect_oxios() {
79 let v: Value = serde_yaml::from_str("name: test\nrequires:\n bins:\n - git\n").unwrap();
80 assert_eq!(detect_format(&v), SkillFormat::Oxios);
81 }
82 #[test]
83 fn test_detect_openclaw() {
84 let v: Value = serde_yaml::from_str(
85 "name: test\nmetadata:\n openclaw:\n requires:\n env:\n - KEY\n",
86 )
87 .unwrap();
88 assert_eq!(detect_format(&v), SkillFormat::OpenClaw);
89 }
90 #[test]
91 fn test_detect_claude() {
92 let v: Value = serde_yaml::from_str("name: test\nallowed-tools: Read Grep\n").unwrap();
93 assert_eq!(detect_format(&v), SkillFormat::ClaudeCode);
94 }
95 #[test]
96 fn test_detect_standard() {
97 let v: Value = serde_yaml::from_str("name: test\ndescription: A skill\n").unwrap();
98 assert_eq!(detect_format(&v), SkillFormat::AgentSkills);
99 }
100}