fix(summon): skip non-recipe project config files (#9808)
Signed-off-by: Douwe M Osinga <douwe@sidewalklabs.com> Co-authored-by: Douwe M Osinga <douwe@sidewalklabs.com>
This commit is contained in:
@@ -142,6 +142,7 @@ fn parse_agent_content(content: &str, path: &Path) -> Option<SourceEntry> {
|
||||
fn scan_recipes_from_dir(
|
||||
dir: &Path,
|
||||
kind: SourceType,
|
||||
suppress_config_warnings: bool,
|
||||
sources: &mut Vec<SourceEntry>,
|
||||
seen: &mut std::collections::HashSet<String>,
|
||||
) {
|
||||
@@ -187,6 +188,13 @@ fn scan_recipes_from_dir(
|
||||
});
|
||||
}
|
||||
Err(e) => {
|
||||
// The working directory commonly contains project config like package.json
|
||||
// and tsconfig.json, which parse as valid JSON but lack Recipe fields. In that
|
||||
// case treat them as "not a recipe" rather than warning. Dedicated recipe
|
||||
// directories still warn so a real recipe with a typo is not silently dropped.
|
||||
if suppress_config_warnings && e.to_string().contains("missing field") {
|
||||
continue;
|
||||
}
|
||||
warn!("Failed to parse recipe {}: {}", path.display(), e);
|
||||
}
|
||||
}
|
||||
@@ -239,7 +247,6 @@ pub fn discover_filesystem_sources(working_dir: &Path) -> Vec<SourceEntry> {
|
||||
let config = Paths::config_dir();
|
||||
|
||||
let local_recipe_dirs: Vec<PathBuf> = vec![
|
||||
working_dir.to_path_buf(),
|
||||
working_dir.join(".goose/recipes"),
|
||||
working_dir.join(".agents/recipes"),
|
||||
];
|
||||
@@ -278,8 +285,16 @@ pub fn discover_filesystem_sources(working_dir: &Path) -> Vec<SourceEntry> {
|
||||
.flatten()
|
||||
.collect();
|
||||
|
||||
scan_recipes_from_dir(
|
||||
working_dir,
|
||||
SourceType::Recipe,
|
||||
true,
|
||||
&mut sources,
|
||||
&mut seen,
|
||||
);
|
||||
|
||||
for dir in local_recipe_dirs {
|
||||
scan_recipes_from_dir(&dir, SourceType::Recipe, &mut sources, &mut seen);
|
||||
scan_recipes_from_dir(&dir, SourceType::Recipe, false, &mut sources, &mut seen);
|
||||
}
|
||||
|
||||
for dir in local_agent_dirs {
|
||||
@@ -287,7 +302,7 @@ pub fn discover_filesystem_sources(working_dir: &Path) -> Vec<SourceEntry> {
|
||||
}
|
||||
|
||||
for dir in global_recipe_dirs {
|
||||
scan_recipes_from_dir(&dir, SourceType::Recipe, &mut sources, &mut seen);
|
||||
scan_recipes_from_dir(&dir, SourceType::Recipe, false, &mut sources, &mut seen);
|
||||
}
|
||||
|
||||
for dir in global_agent_dirs {
|
||||
@@ -2072,6 +2087,40 @@ You review code."#;
|
||||
assert_eq!(sources[0].name, "reviewer");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_recipe_scan_skips_non_recipe_project_config_files() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
fs::write(
|
||||
temp_dir.path().join("package.json"),
|
||||
r#"{"scripts":{"test":"cargo test"}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
temp_dir.path().join("tsconfig.json"),
|
||||
r#"{"compilerOptions":{"strict":true}}"#,
|
||||
)
|
||||
.unwrap();
|
||||
fs::write(
|
||||
temp_dir.path().join("valid.yaml"),
|
||||
"title: Valid\ndescription: Real recipe\ninstructions: Run valid steps",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let mut sources = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
scan_recipes_from_dir(
|
||||
temp_dir.path(),
|
||||
SourceType::Recipe,
|
||||
true,
|
||||
&mut sources,
|
||||
&mut seen,
|
||||
);
|
||||
|
||||
assert_eq!(sources.len(), 1);
|
||||
assert_eq!(sources[0].name, "valid");
|
||||
assert_eq!(sources[0].description, "Real recipe");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_discover_recipes_and_agents() {
|
||||
let temp_dir = TempDir::new().unwrap();
|
||||
|
||||
Reference in New Issue
Block a user