mirror of
https://github.com/block/goose.git
synced 2026-06-01 22:11:07 +02:00
Allow sharing nested skill files
Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
This commit is contained in:
@@ -103,6 +103,24 @@ fn has_sequence_with_remaining(path: &Path, sequence: &[&str], remaining: usize)
|
||||
})
|
||||
}
|
||||
|
||||
fn has_sequence_with_min_remaining(
|
||||
path: &Path,
|
||||
sequence: &[&str],
|
||||
minimum_remaining: usize,
|
||||
) -> bool {
|
||||
let components = path_components(path);
|
||||
components
|
||||
.windows(sequence.len())
|
||||
.enumerate()
|
||||
.any(|(index, window)| {
|
||||
window
|
||||
.iter()
|
||||
.map(String::as_str)
|
||||
.eq(sequence.iter().copied())
|
||||
&& components.len() >= index + sequence.len() + minimum_remaining
|
||||
})
|
||||
}
|
||||
|
||||
fn is_shareable_agent_file(path: &Path) -> bool {
|
||||
path.extension().and_then(|extension| extension.to_str()) == Some("md")
|
||||
&& (has_sequence_with_remaining(path, &[".agents", "agents"], 1)
|
||||
@@ -111,11 +129,11 @@ fn is_shareable_agent_file(path: &Path) -> bool {
|
||||
|
||||
fn is_shareable_skill_file(path: &Path) -> bool {
|
||||
path.file_name().and_then(|name| name.to_str()) == Some("SKILL.md")
|
||||
&& (has_sequence_with_remaining(path, &[".agents", "skills"], 2)
|
||||
|| has_sequence_with_remaining(path, &[".goose", "skills"], 2)
|
||||
|| has_sequence_with_remaining(path, &[".claude", "skills"], 2)
|
||||
|| has_sequence_with_remaining(path, &[".config", "agents", "skills"], 2)
|
||||
|| has_sequence_with_remaining(path, &["goose", "skills"], 2)
|
||||
&& (has_sequence_with_min_remaining(path, &[".agents", "skills"], 2)
|
||||
|| has_sequence_with_min_remaining(path, &[".goose", "skills"], 2)
|
||||
|| has_sequence_with_min_remaining(path, &[".claude", "skills"], 2)
|
||||
|| has_sequence_with_min_remaining(path, &[".config", "agents", "skills"], 2)
|
||||
|| has_sequence_with_min_remaining(path, &["goose", "skills"], 2)
|
||||
|| is_plugin_skill_file(path))
|
||||
}
|
||||
|
||||
@@ -125,7 +143,7 @@ fn is_plugin_skill_file(path: &Path) -> bool {
|
||||
window[0] == "goose"
|
||||
&& window[1] == "plugins"
|
||||
&& window[3] == "skills"
|
||||
&& components.len() == index + 6
|
||||
&& components.len() >= index + 6
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -281,6 +281,13 @@ fn shareable_source_validation_accepts_agent_and_skill_files() {
|
||||
.join("skills")
|
||||
.join("review")
|
||||
.join("SKILL.md");
|
||||
let nested_skill_file = dir
|
||||
.path()
|
||||
.join(".agents")
|
||||
.join("skills")
|
||||
.join("team")
|
||||
.join("review")
|
||||
.join("SKILL.md");
|
||||
let config_skill_file = dir
|
||||
.path()
|
||||
.join("Block")
|
||||
@@ -297,21 +304,47 @@ fn shareable_source_validation_accepts_agent_and_skill_files() {
|
||||
.join("skills")
|
||||
.join("plugin-review")
|
||||
.join("SKILL.md");
|
||||
let nested_plugin_skill_file = dir
|
||||
.path()
|
||||
.join("Block")
|
||||
.join("goose")
|
||||
.join("plugins")
|
||||
.join("plugin-a")
|
||||
.join("skills")
|
||||
.join("team")
|
||||
.join("plugin-review")
|
||||
.join("SKILL.md");
|
||||
fs::create_dir_all(agent_file.parent().expect("agent parent")).expect("agent dir");
|
||||
fs::create_dir_all(skill_file.parent().expect("skill parent")).expect("skill dir");
|
||||
fs::create_dir_all(nested_skill_file.parent().expect("nested skill parent"))
|
||||
.expect("nested skill dir");
|
||||
fs::create_dir_all(config_skill_file.parent().expect("config skill parent"))
|
||||
.expect("config skill dir");
|
||||
fs::create_dir_all(plugin_skill_file.parent().expect("plugin skill parent"))
|
||||
.expect("plugin skill dir");
|
||||
fs::create_dir_all(
|
||||
nested_plugin_skill_file
|
||||
.parent()
|
||||
.expect("nested plugin skill parent"),
|
||||
)
|
||||
.expect("nested plugin skill dir");
|
||||
fs::write(&agent_file, "---\nname: Helper\n---\n").expect("agent file");
|
||||
fs::write(&skill_file, "---\nname: review\n---\n").expect("skill file");
|
||||
fs::write(&nested_skill_file, "---\nname: team-review\n---\n").expect("nested skill file");
|
||||
fs::write(&config_skill_file, "---\nname: legacy\n---\n").expect("config skill file");
|
||||
fs::write(&plugin_skill_file, "---\nname: plugin-review\n---\n").expect("plugin skill file");
|
||||
fs::write(
|
||||
&nested_plugin_skill_file,
|
||||
"---\nname: nested-plugin-review\n---\n",
|
||||
)
|
||||
.expect("nested plugin skill file");
|
||||
|
||||
assert!(validate_shareable_source_file(&agent_file).is_ok());
|
||||
assert!(validate_shareable_source_file(&skill_file).is_ok());
|
||||
assert!(validate_shareable_source_file(&nested_skill_file).is_ok());
|
||||
assert!(validate_shareable_source_file(&config_skill_file).is_ok());
|
||||
assert!(validate_shareable_source_file(&plugin_skill_file).is_ok());
|
||||
assert!(validate_shareable_source_file(&nested_plugin_skill_file).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user