fix: include configured and workspace skills in slash menu discovery

This commit is contained in:
cyq
2026-05-24 02:20:09 +08:00
committed by Hunter Bown
parent 41590edfd8
commit cb70daf35c
2 changed files with 83 additions and 6 deletions
+39 -4
View File
@@ -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
+44 -2
View File
@@ -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(