fix: handle non exist subrecipe path (#5287)
This commit is contained in:
@@ -242,18 +242,26 @@ settings:
|
|||||||
temperature: 0.7
|
temperature: 0.7
|
||||||
sub_recipes:
|
sub_recipes:
|
||||||
- path: existing_sub_recipe.yaml
|
- path: existing_sub_recipe.yaml
|
||||||
name: existing_sub_recipe
|
name: existing_sub_recipe
|
||||||
response:
|
response:
|
||||||
json_schema:
|
json_schema:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
result:
|
result:
|
||||||
type: string
|
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 temp_dir = tempfile::tempdir().unwrap();
|
||||||
let recipe_path: std::path::PathBuf = temp_dir.path().join("test_recipe.yaml");
|
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(&recipe_path, test_recipe_content).unwrap();
|
||||||
|
std::fs::write(&sub_recipe_path, sub_recipe_content).unwrap();
|
||||||
let canonical_recipe_path = recipe_path.canonicalize().unwrap();
|
let canonical_recipe_path = recipe_path.canonicalize().unwrap();
|
||||||
(temp_dir, canonical_recipe_path)
|
(temp_dir, canonical_recipe_path)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,9 +70,7 @@ where
|
|||||||
|
|
||||||
if let Some(ref mut sub_recipes) = recipe.sub_recipes {
|
if let Some(ref mut sub_recipes) = recipe.sub_recipes {
|
||||||
for sub_recipe in 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 = resolve_sub_recipe_path(&sub_recipe.path, recipe_dir)?;
|
||||||
sub_recipe.path = resolved_path;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,18 +120,17 @@ fn resolve_sub_recipe_path(
|
|||||||
parent_recipe_dir: &Path,
|
parent_recipe_dir: &Path,
|
||||||
) -> Result<String, RecipeError> {
|
) -> Result<String, RecipeError> {
|
||||||
let path = if Path::new(sub_recipe_path).is_absolute() {
|
let path = if Path::new(sub_recipe_path).is_absolute() {
|
||||||
sub_recipe_path.to_string()
|
Path::new(sub_recipe_path).to_path_buf()
|
||||||
} else {
|
} else {
|
||||||
parent_recipe_dir
|
parent_recipe_dir.join(sub_recipe_path)
|
||||||
.join(sub_recipe_path)
|
|
||||||
.to_str()
|
|
||||||
.ok_or_else(|| RecipeError::RecipeParsing {
|
|
||||||
source: anyhow::anyhow!("Invalid sub-recipe path: {}", sub_recipe_path),
|
|
||||||
})?
|
|
||||||
.to_string()
|
|
||||||
};
|
};
|
||||||
|
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)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -435,6 +435,14 @@ mod sub_recipe_path_resolution {
|
|||||||
let temp_dir = tempfile::tempdir().unwrap();
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
let parent_dir = temp_dir.path();
|
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);
|
let result = resolve_sub_recipe_path("./sub-recipes/child.yaml", parent_dir);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
@@ -446,11 +454,37 @@ mod sub_recipe_path_resolution {
|
|||||||
fn test_resolve_sub_recipe_path_absolute() {
|
fn test_resolve_sub_recipe_path_absolute() {
|
||||||
let temp_dir = tempfile::tempdir().unwrap();
|
let temp_dir = tempfile::tempdir().unwrap();
|
||||||
let parent_dir = temp_dir.path();
|
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!(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]
|
#[test]
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import { substituteParameters } from '../utils/providerUtils';
|
|||||||
import { updateSessionUserRecipeValues } from '../api';
|
import { updateSessionUserRecipeValues } from '../api';
|
||||||
import { useChatContext } from '../contexts/ChatContext';
|
import { useChatContext } from '../contexts/ChatContext';
|
||||||
import { ChatType } from '../types/chat';
|
import { ChatType } from '../types/chat';
|
||||||
import { toastSuccess } from '../toasts';
|
import { toastError, toastSuccess } from '../toasts';
|
||||||
|
|
||||||
export const useRecipeManager = (chat: ChatType, recipe?: Recipe | null) => {
|
export const useRecipeManager = (chat: ChatType, recipe?: Recipe | null) => {
|
||||||
const [isParameterModalOpen, setIsParameterModalOpen] = useState(false);
|
const [isParameterModalOpen, setIsParameterModalOpen] = useState(false);
|
||||||
@@ -181,7 +181,17 @@ export const useRecipeManager = (chat: ChatType, recipe?: Recipe | null) => {
|
|||||||
}
|
}
|
||||||
setIsParameterModalOpen(false);
|
setIsParameterModalOpen(false);
|
||||||
} catch (error) {
|
} 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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user