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