bake_agent_context/agent/context/
mod.rs1mod exclude;
5mod index;
6mod installer;
7mod skill;
8
9pub use index::ContextIndex;
10pub use installer::{ContextFile, ContextPackage, Installer};
11pub use skill::{Skill, install_skills, list_skills};
12
13use bake::{Context, Error, Result};
14
15fn installer(context: &mut Context) -> Result<Installer> {
16 if let Some(installer) = context.get::<Installer>() {
17 return Ok(installer.clone());
18 }
19
20 let installer = Installer::new(context.root())?;
21 context.insert(installer.clone());
22 Ok(installer)
23}
24
25#[bake::task]
27pub fn list(context: &mut Context, package: Option<String>) -> Result<String> {
28 let installer = installer(context)?;
29
30 if let Some(package) = package {
31 let Some(package) = installer.find_package(&package)? else {
32 return Ok(format!("No context found for crate '{package}'"));
33 };
34
35 let files = installer.list_context_files(&package)?;
36 if files.is_empty() {
37 return Ok(format!(
38 "No context files found for crate '{}'.",
39 package.selector()
40 ));
41 }
42 let mut output = format!("Context files for crate '{}':", package.selector());
43 for file in files {
44 output.push_str(&format!("\n {}", file.path.display()));
45 }
46 return Ok(output);
47 }
48
49 let mut packages = Vec::new();
50 for package in installer.packages() {
51 if !installer.list_context_files(package)?.is_empty() {
52 packages.push(package);
53 }
54 }
55 if packages.is_empty() {
56 return Ok("No dependency context files found".to_owned());
57 }
58
59 let mut output = String::from("Crates with context available:");
60 for package in packages {
61 output.push_str(&format!("\n {} ({})", package.selector(), package.version));
62 }
63 Ok(output)
64}
65
66#[bake::task]
68pub fn show(
69 context: &mut Context,
70 #[bake(named)] package: String,
71 #[bake(named)] file: String,
72) -> Result<String> {
73 let installer = installer(context)?;
74 let Some(content) = installer.show_context_file(&package, &file)? else {
75 return Err(Error::new(format!(
76 "context file {file:?} was not found in crate {package:?}"
77 )));
78 };
79 Ok(content)
80}
81
82#[bake::task]
84pub fn install(context: &mut Context, package: Option<String>) -> Result<String> {
85 let installer = installer(context)?;
86 let installed_context = if let Some(package) = package.as_deref() {
87 if installer.install_package(package)? {
88 vec![package.to_owned()]
89 } else {
90 Vec::new()
91 }
92 } else {
93 installer.install_all()?
94 };
95 let installed_skills = install_skills(&installer, package.as_deref(), None)?;
96
97 ContextIndex::new(context.root())
98 .with_packages(installer.packages())
99 .update_index()?;
100
101 let mut output = Vec::new();
102 if !installed_context.is_empty() {
103 output.push(format!(
104 "Installed context from: {}",
105 installed_context.join(", ")
106 ));
107 }
108 if !installed_skills.is_empty() {
109 output.push(format!("Installed skills: {}", installed_skills.join(", ")));
110 }
111
112 if output.is_empty() {
113 Ok("No dependency context or skills were installed".to_owned())
114 } else {
115 Ok(output.join("\n"))
116 }
117}
118
119#[bake::task(name = "agent:context:skill:list")]
121pub fn skill_list(context: &mut Context, package: Option<String>) -> Result<String> {
122 let installer = installer(context)?;
123 let skills = list_skills(&installer, package.as_deref())?;
124 if skills.is_empty() {
125 return Ok("No dependency skills found".to_owned());
126 }
127
128 let mut output = String::from("Available dependency skills:");
129 for skill in skills {
130 output.push_str(&format!(
131 "\n {} ({}) — {}",
132 skill.name,
133 skill.package_selector(),
134 skill.description
135 ));
136 }
137 Ok(output)
138}
139
140#[bake::task(name = "agent:context:skill:install")]
142pub fn skill_install(
143 context: &mut Context,
144 package: Option<String>,
145 skill: Option<String>,
146) -> Result<String> {
147 let installer = installer(context)?;
148 let installed = install_skills(&installer, package.as_deref(), skill.as_deref())?;
149 if installed.is_empty() {
150 Ok("No dependency skills were installed".to_owned())
151 } else {
152 Ok(format!("Installed skills: {}", installed.join(", ")))
153 }
154}
155
156#[bake::task(name = "agent:context:index")]
158pub fn index(context: &mut Context) -> Result<String> {
159 let installer = installer(context)?;
160 ContextIndex::new(context.root())
161 .with_packages(installer.packages())
162 .update_index()?;
163 Ok("Updated .agents/context/index.md".to_owned())
164}