fix: handle non exist subrecipe path (#5287)

This commit is contained in:
Lifei Zhou
2025-10-22 09:05:18 +11:00
committed by GitHub
parent d836a10af1
commit e720733259
4 changed files with 67 additions and 18 deletions
@@ -242,18 +242,26 @@ settings:
temperature: 0.7
sub_recipes:
- path: existing_sub_recipe.yaml
name: existing_sub_recipe
name: existing_sub_recipe
response:
json_schema:
type: object
properties:
result:
type: string
"#;
let sub_recipe_content = r#"
title: existing_sub_recipe
description: An existing sub recipe
instructions: sub recipe instructions
prompt: sub recipe prompt
"#;
let temp_dir = tempfile::tempdir().unwrap();
let recipe_path: std::path::PathBuf = temp_dir.path().join("test_recipe.yaml");
let sub_recipe_path: std::path::PathBuf = temp_dir.path().join("existing_sub_recipe.yaml");
std::fs::write(&recipe_path, test_recipe_content).unwrap();
std::fs::write(&sub_recipe_path, sub_recipe_content).unwrap();
let canonical_recipe_path = recipe_path.canonicalize().unwrap();
(temp_dir, canonical_recipe_path)
}
+9 -12
View File
@@ -70,9 +70,7 @@ where
if let Some(ref mut sub_recipes) = recipe.sub_recipes {
for sub_recipe in sub_recipes {
if let Ok(resolved_path) = resolve_sub_recipe_path(&sub_recipe.path, recipe_dir) {
sub_recipe.path = resolved_path;
}
sub_recipe.path = resolve_sub_recipe_path(&sub_recipe.path, recipe_dir)?;
}
}
@@ -122,18 +120,17 @@ fn resolve_sub_recipe_path(
parent_recipe_dir: &Path,
) -> Result<String, RecipeError> {
let path = if Path::new(sub_recipe_path).is_absolute() {
sub_recipe_path.to_string()
Path::new(sub_recipe_path).to_path_buf()
} else {
parent_recipe_dir
.join(sub_recipe_path)
.to_str()
.ok_or_else(|| RecipeError::RecipeParsing {
source: anyhow::anyhow!("Invalid sub-recipe path: {}", sub_recipe_path),
})?
.to_string()
parent_recipe_dir.join(sub_recipe_path)
};
if !path.exists() {
return Err(RecipeError::RecipeParsing {
source: anyhow::anyhow!("Sub-recipe file does not exist: {}", path.display()),
});
}
Ok(path)
Ok(path.display().to_string())
}
#[cfg(test)]
+37 -3
View File
@@ -435,6 +435,14 @@ mod sub_recipe_path_resolution {
let temp_dir = tempfile::tempdir().unwrap();
let parent_dir = temp_dir.path();
// Create the sub-recipe file
let sub_recipe_content = r#"
version: 1.0.0
title: Child Recipe
description: A child recipe
instructions: Child instructions"#;
create_recipe_file(parent_dir, "sub-recipes", "child.yaml", sub_recipe_content);
let result = resolve_sub_recipe_path("./sub-recipes/child.yaml", parent_dir);
assert!(result.is_ok());
@@ -446,11 +454,37 @@ mod sub_recipe_path_resolution {
fn test_resolve_sub_recipe_path_absolute() {
let temp_dir = tempfile::tempdir().unwrap();
let parent_dir = temp_dir.path();
let absolute_path = "/absolute/path/to/recipe.yaml";
let result = resolve_sub_recipe_path(absolute_path, parent_dir);
let sub_recipe_content = r#"
version: 1.0.0
title: Absolute Recipe
description: A recipe with absolute path
instructions: Absolute instructions"#;
let absolute_path =
create_recipe_file(parent_dir, "absolute", "recipe.yaml", sub_recipe_content);
let absolute_path_str = absolute_path.to_str().unwrap();
let result = resolve_sub_recipe_path(absolute_path_str, parent_dir);
assert!(result.is_ok());
assert_eq!(result.unwrap(), absolute_path);
assert_eq!(result.unwrap(), absolute_path_str);
}
#[test]
fn test_resolve_sub_recipe_path_nonexistent() {
let temp_dir = tempfile::tempdir().unwrap();
let parent_dir = temp_dir.path();
let result = resolve_sub_recipe_path("./sub-recipes/nonexistent.yaml", parent_dir);
assert!(result.is_err());
match result {
Err(RecipeError::RecipeParsing { source }) => {
let error_msg = source.to_string();
assert!(error_msg.contains("Sub-recipe file does not exist"));
assert!(error_msg.contains("nonexistent.yaml"));
}
_ => panic!("Expected RecipeError::RecipeParsing"),
}
}
#[test]
+12 -2
View File
@@ -7,7 +7,7 @@ import { substituteParameters } from '../utils/providerUtils';
import { updateSessionUserRecipeValues } from '../api';
import { useChatContext } from '../contexts/ChatContext';
import { ChatType } from '../types/chat';
import { toastSuccess } from '../toasts';
import { toastError, toastSuccess } from '../toasts';
export const useRecipeManager = (chat: ChatType, recipe?: Recipe | null) => {
const [isParameterModalOpen, setIsParameterModalOpen] = useState(false);
@@ -181,7 +181,17 @@ export const useRecipeManager = (chat: ChatType, recipe?: Recipe | null) => {
}
setIsParameterModalOpen(false);
} catch (error) {
console.error('Failed to update system prompt with parameters:', error);
let error_message = 'unknown error';
if (typeof error === 'object' && error !== null && 'message' in error) {
error_message = error.message as string;
} else if (typeof error === 'string') {
error_message = error;
}
console.error('Failed to render recipe with parameters:', error);
toastError({
title: 'Recipe Rendering Failed',
msg: error_message,
});
}
};