fix: include configured and workspace skills in slash menu discovery
This commit is contained in:
@@ -1705,7 +1705,7 @@ impl App {
|
||||
let plan_state = new_shared_plan_state();
|
||||
|
||||
let skills_dir = resolve_skills_dir(&workspace, &global_skills_dir, config);
|
||||
let cached_skills = Self::discover_cached_skills(&workspace);
|
||||
let cached_skills = Self::discover_cached_skills(&workspace, &skills_dir);
|
||||
|
||||
let input_history = crate::composer_history::load_history();
|
||||
let (initial_input_text, initial_input_cursor) = match initial_input {
|
||||
@@ -1922,8 +1922,11 @@ impl App {
|
||||
}
|
||||
}
|
||||
|
||||
fn discover_cached_skills(workspace: &std::path::Path) -> Vec<(String, String)> {
|
||||
crate::skills::discover_in_workspace(workspace)
|
||||
fn discover_cached_skills(
|
||||
workspace: &std::path::Path,
|
||||
skills_dir: &std::path::Path,
|
||||
) -> Vec<(String, String)> {
|
||||
crate::skills::discover_for_workspace_and_dir(workspace, skills_dir)
|
||||
.list()
|
||||
.iter()
|
||||
.map(|s| (s.name.clone(), s.description.clone()))
|
||||
@@ -1931,7 +1934,8 @@ impl App {
|
||||
}
|
||||
|
||||
pub fn refresh_skill_cache(&mut self) {
|
||||
self.cached_skills = Self::discover_cached_skills(&self.workspace);
|
||||
let skills_dir = self.skills_dir.clone();
|
||||
self.cached_skills = Self::discover_cached_skills(&self.workspace, &skills_dir);
|
||||
}
|
||||
|
||||
pub fn submit_api_key(&mut self) -> Result<SavedCredential, ApiKeyError> {
|
||||
@@ -5109,6 +5113,37 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cached_skills_include_configured_directory() {
|
||||
let tmp = tempfile::TempDir::new().expect("tempdir");
|
||||
let workspace = tmp.path().join("workspace");
|
||||
|
||||
let configured_dir = tmp.path().join("configured-skills");
|
||||
let configured_skill_dir = configured_dir.join("configured-skill");
|
||||
std::fs::create_dir_all(&configured_skill_dir).expect("configured skill dir");
|
||||
std::fs::write(
|
||||
configured_skill_dir.join("SKILL.md"),
|
||||
"---\nname: configured-skill\ndescription: Configured skill\n---\nbody\n",
|
||||
)
|
||||
.expect("write configured skill");
|
||||
|
||||
let mut options = test_options(false);
|
||||
options.workspace = workspace.clone();
|
||||
options.skills_dir = configured_dir.clone();
|
||||
let mut config = Config::default();
|
||||
config.skills_dir = Some(configured_dir.to_string_lossy().into_owned());
|
||||
let app = App::new(options, &config);
|
||||
|
||||
assert!(
|
||||
app.cached_skills
|
||||
.iter()
|
||||
.any(|(name, description)| name == "configured-skill"
|
||||
&& description == "Configured skill"),
|
||||
"configured skill dir should be merged: {:?}",
|
||||
app.cached_skills
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paste_consolidates_oversized_text_into_paste_file_visibly() {
|
||||
// Visible-before-submit consolidation (paste UX): when a single
|
||||
|
||||
@@ -15,7 +15,7 @@ use unicode_width::UnicodeWidthStr;
|
||||
use crate::commands;
|
||||
use crate::localization::Locale;
|
||||
use crate::palette;
|
||||
use crate::skills::SkillRegistry;
|
||||
use crate::skills;
|
||||
use crate::tools::spec::ApprovalRequirement;
|
||||
use crate::tools::spec::ToolCapability;
|
||||
use crate::tools::{ToolContext, ToolRegistryBuilder};
|
||||
@@ -78,7 +78,7 @@ pub fn build_entries(
|
||||
});
|
||||
}
|
||||
|
||||
let skills = SkillRegistry::discover(skills_dir);
|
||||
let skills = skills::discover_for_workspace_and_dir(workspace, skills_dir);
|
||||
for skill in skills.list() {
|
||||
entries.push(CommandPaletteEntry {
|
||||
section: PaletteSection::Skill,
|
||||
@@ -798,6 +798,7 @@ impl ModalView for CommandPaletteView {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::path::Path;
|
||||
use tempfile::TempDir;
|
||||
|
||||
fn palette_entry(
|
||||
section: PaletteSection,
|
||||
@@ -920,6 +921,47 @@ mod tests {
|
||||
assert_eq!(view.entries[view.filtered[0]].label, "skill:search");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_palette_skills_use_workspace_and_configured_directories() {
|
||||
let tmp = TempDir::new().expect("tempdir");
|
||||
let workspace = tmp.path().join("workspace");
|
||||
let workspace_skill_dir = workspace
|
||||
.join(".agents")
|
||||
.join("skills")
|
||||
.join("workspace-skill");
|
||||
std::fs::create_dir_all(&workspace_skill_dir).expect("create workspace skill dir");
|
||||
std::fs::write(
|
||||
workspace_skill_dir.join("SKILL.md"),
|
||||
"---\nname: workspace-skill\ndescription: Workspace skill\ngithub: https://example.com\n---\nbody",
|
||||
)
|
||||
.expect("write workspace skill");
|
||||
|
||||
let configured_dir = tmp.path().join("configured-skills");
|
||||
let configured_skill_dir = configured_dir.join("configured-skill");
|
||||
std::fs::create_dir_all(&configured_skill_dir).expect("create configured skill dir");
|
||||
std::fs::write(
|
||||
configured_skill_dir.join("SKILL.md"),
|
||||
"---\nname: configured-skill\ndescription: Configured skill\n---\nbody",
|
||||
)
|
||||
.expect("write configured skill");
|
||||
|
||||
let entries = build_entries(
|
||||
Locale::En,
|
||||
configured_dir.as_path(),
|
||||
workspace.as_path(),
|
||||
Path::new("mcp.json"),
|
||||
None,
|
||||
);
|
||||
let skill_labels = entries
|
||||
.iter()
|
||||
.filter(|entry| entry.section == PaletteSection::Skill)
|
||||
.map(|entry| entry.label.as_str())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(skill_labels.contains(&"skill:workspace-skill"));
|
||||
assert!(skill_labels.contains(&"skill:configured-skill"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn command_palette_command_entries_include_links_and_config_but_not_removed_commands() {
|
||||
let entries = build_entries(
|
||||
|
||||
Reference in New Issue
Block a user