1use codex_protocol::protocol::Product;
2use codex_protocol::protocol::SkillScope;
3use codex_utils_absolute_path::AbsolutePathBuf;
4use codex_utils_path_uri::PathUri;
5
6#[derive(Debug, Clone, PartialEq)]
8pub struct SkillMetadata {
9 pub name: String,
10 pub description: String,
11 pub short_description: Option<String>,
12 pub interface: Option<SkillInterface>,
13 pub dependencies: Option<SkillDependencies>,
14 pub policy: Option<SkillPolicy>,
15 pub path_to_skills_md: AbsolutePathBuf,
17 pub scope: SkillScope,
18 pub plugin_id: Option<String>,
19}
20
21impl SkillMetadata {
22 pub fn allows_implicit_invocation(&self) -> bool {
23 self.policy
24 .as_ref()
25 .and_then(|policy| policy.allow_implicit_invocation)
26 .unwrap_or(true)
27 }
28
29 pub fn matches_product_restriction_for_product(
30 &self,
31 restriction_product: Option<Product>,
32 ) -> bool {
33 matches_product_restriction(self.policy.as_ref(), restriction_product)
34 }
35}
36
37#[derive(Clone, Debug, PartialEq, Eq)]
39pub struct EnvironmentSkillMetadata {
40 pub path_to_skills_md: PathUri,
41 pub name: String,
42 pub description: String,
43 pub short_description: Option<String>,
44 pub dependencies: Option<SkillDependencies>,
45 pub policy: Option<SkillPolicy>,
46}
47
48impl EnvironmentSkillMetadata {
49 pub fn allows_implicit_invocation(&self) -> bool {
50 self.policy
51 .as_ref()
52 .and_then(|policy| policy.allow_implicit_invocation)
53 .unwrap_or(true)
54 }
55
56 pub fn matches_product_restriction(&self, restriction_product: Option<Product>) -> bool {
57 matches_product_restriction(self.policy.as_ref(), restriction_product)
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, Default)]
62pub struct SkillPolicy {
63 pub allow_implicit_invocation: Option<bool>,
64 pub products: Vec<Product>,
67}
68
69#[derive(Debug, Clone, PartialEq, Eq)]
70pub struct SkillInterface {
71 pub display_name: Option<String>,
72 pub short_description: Option<String>,
73 pub icon_small: Option<AbsolutePathBuf>,
74 pub icon_large: Option<AbsolutePathBuf>,
75 pub brand_color: Option<String>,
76 pub default_prompt: Option<String>,
77}
78
79#[derive(Debug, Clone, PartialEq, Eq)]
80pub struct SkillDependencies {
81 pub tools: Vec<SkillToolDependency>,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct SkillToolDependency {
86 pub r#type: String,
87 pub value: String,
88 pub description: Option<String>,
89 pub transport: Option<String>,
90 pub command: Option<String>,
91 pub url: Option<String>,
92}
93
94#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
95pub enum SkillConfigRuleSelector {
96 Name(String),
97 Path(AbsolutePathBuf),
98}
99
100#[derive(Debug, Clone, PartialEq, Eq, Hash)]
101pub struct SkillConfigRule {
102 pub selector: SkillConfigRuleSelector,
103 pub enabled: bool,
104}
105
106#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)]
107pub struct SkillConfigRules {
108 pub entries: Vec<SkillConfigRule>,
109}
110
111fn matches_product_restriction(
112 policy: Option<&SkillPolicy>,
113 restriction_product: Option<Product>,
114) -> bool {
115 match policy {
116 Some(policy) => {
117 policy.products.is_empty()
118 || restriction_product
119 .is_some_and(|product| product.matches_product_restriction(&policy.products))
120 }
121 None => true,
122 }
123}
124
125#[cfg(test)]
126#[path = "model_tests.rs"]
127mod tests;