agent_config/agents/cline/
skills.rs1use std::path::PathBuf;
5
6use crate::agents::planning as agent_planning;
7use crate::error::AgentConfigError;
8use crate::integration::{InstallReport, SkillSurface, UninstallReport};
9use crate::paths;
10use crate::plan::{InstallPlan, UninstallPlan};
11use crate::scope::{Scope, ScopeKind};
12use crate::spec::SkillSpec;
13use crate::status::StatusReport;
14use crate::util::{ownership, skills_dir};
15
16use super::ClineAgent;
17
18impl ClineAgent {
19 pub(super) fn skills_root(scope: &Scope) -> Result<PathBuf, AgentConfigError> {
20 Ok(match scope {
21 Scope::Global => paths::home_dir()?.join(".cline").join("skills"),
22 Scope::Local(p) => p.join(".cline").join("skills"),
23 })
24 }
25}
26
27impl SkillSurface for ClineAgent {
28 fn id(&self) -> &'static str {
29 "cline"
30 }
31
32 fn supported_skill_scopes(&self) -> &'static [ScopeKind] {
33 &[ScopeKind::Global, ScopeKind::Local]
34 }
35
36 fn skill_status(
37 &self,
38 scope: &Scope,
39 name: &str,
40 expected_owner: &str,
41 ) -> Result<StatusReport, AgentConfigError> {
42 SkillSpec::validate_name(name)?;
43 let root = Self::skills_root(scope)?;
44 let (dir, manifest, ledger) = skills_dir::paths_for_status(&root, name);
45 let recorded = ownership::owner_of(&ledger, name)?;
46 Ok(StatusReport::for_skill(
47 name,
48 dir,
49 manifest,
50 ledger,
51 expected_owner,
52 recorded,
53 ))
54 }
55
56 fn plan_install_skill(
57 &self,
58 scope: &Scope,
59 spec: &SkillSpec,
60 ) -> Result<InstallPlan, AgentConfigError> {
61 agent_planning::skill_install(
62 SkillSurface::id(self),
63 scope,
64 spec,
65 Self::skills_root(scope),
66 )
67 }
68
69 fn plan_uninstall_skill(
70 &self,
71 scope: &Scope,
72 name: &str,
73 owner_tag: &str,
74 ) -> Result<UninstallPlan, AgentConfigError> {
75 agent_planning::skill_uninstall(
76 SkillSurface::id(self),
77 scope,
78 name,
79 owner_tag,
80 Self::skills_root(scope),
81 )
82 }
83
84 fn install_skill(
85 &self,
86 scope: &Scope,
87 spec: &SkillSpec,
88 ) -> Result<InstallReport, AgentConfigError> {
89 let root = Self::skills_root(scope)?;
90 scope.ensure_contained(&root)?;
91 skills_dir::install(&root, spec)
92 }
93
94 fn uninstall_skill(
95 &self,
96 scope: &Scope,
97 name: &str,
98 owner_tag: &str,
99 ) -> Result<UninstallReport, AgentConfigError> {
100 let root = Self::skills_root(scope)?;
101 scope.ensure_contained(&root)?;
102 skills_dir::uninstall(&root, name, owner_tag)
103 }
104}