Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions crates/goose-server/src/routes/recipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ pub struct SaveRecipeRequest {
#[derive(Debug, Serialize, ToSchema)]
pub struct SaveRecipeResponse {
id: String,
file_name: String,
file_path: String,
}
#[derive(Debug, Deserialize, ToSchema)]
pub struct ParseRecipeRequest {
Expand Down Expand Up @@ -459,9 +461,18 @@ async fn save_recipe(
};

match local_recipes::save_recipe_to_file(request.recipe, file_path.clone()) {
Ok(save_file_path) => Ok(Json(SaveRecipeResponse {
id: short_id_from_path(&save_file_path.display().to_string()),
})),
Ok(save_file_path) => {
let file_name = save_file_path
.file_name()
.map(|n| n.to_string_lossy().to_string())
.unwrap_or_default();
let file_path_str = save_file_path.display().to_string();
Ok(Json(SaveRecipeResponse {
id: short_id_from_path(&file_path_str),
file_name,
file_path: file_path_str,
}))
}
Err(e) => Err(ErrorResponse {
message: e.to_string(),
status: StatusCode::INTERNAL_SERVER_ERROR,
Expand Down
10 changes: 9 additions & 1 deletion ui/desktop/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -7562,9 +7562,17 @@
"SaveRecipeResponse": {
"type": "object",
"required": [
"id"
"id",
"file_name",
"file_path"
],
"properties": {
"file_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"id": {
"type": "string"
}
Expand Down
2 changes: 2 additions & 0 deletions ui/desktop/src/api/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,8 @@ export type SaveRecipeRequest = {
};

export type SaveRecipeResponse = {
file_name: string;
file_path: string;
id: string;
};

Expand Down
39 changes: 36 additions & 3 deletions ui/desktop/src/components/recipes/CreateEditRecipeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface CreateEditRecipeModalProps {
recipe?: Recipe;
isCreateMode?: boolean;
recipeId?: string | null;
onRecipeSaved?: (savedRecipeId: string) => void;
}

export default function CreateEditRecipeModal({
Expand All @@ -28,6 +29,7 @@ export default function CreateEditRecipeModal({
recipe,
isCreateMode = false,
recipeId,
onRecipeSaved,
}: CreateEditRecipeModalProps) {
const getInitialValues = React.useCallback((): RecipeFormData => {
if (recipe) {
Expand All @@ -44,6 +46,13 @@ export default function CreateEditRecipeModal({
model: recipe.settings?.goose_model ?? undefined,
provider: recipe.settings?.goose_provider ?? undefined,
extensions: recipe.extensions || undefined,
subRecipes: (recipe.sub_recipes || []).map((sr) => ({
name: sr.name,
path: sr.path,
description: sr.description || undefined,
values: sr.values || undefined,
sequential_when_repeated: sr.sequential_when_repeated ?? false,
})),
};
}
return {
Expand All @@ -57,6 +66,7 @@ export default function CreateEditRecipeModal({
model: undefined,
provider: undefined,
extensions: undefined,
subRecipes: [],
};
}, [recipe]);

Expand All @@ -75,6 +85,7 @@ export default function CreateEditRecipeModal({
const [model, setModel] = useState(form.state.values.model);
const [provider, setProvider] = useState(form.state.values.provider);
const [extensions, setExtensions] = useState(form.state.values.extensions);
const [subRecipes, setSubRecipes] = useState(form.state.values.subRecipes);

// Subscribe to form changes to update local state
useEffect(() => {
Expand All @@ -89,6 +100,7 @@ export default function CreateEditRecipeModal({
setModel(form.state.values.model);
setProvider(form.state.values.provider);
setExtensions(form.state.values.extensions);
setSubRecipes(form.state.values.subRecipes);
});
}, [form]);
const [copied, setCopied] = useState(false);
Expand Down Expand Up @@ -137,6 +149,21 @@ export default function CreateEditRecipeModal({
}
}

// Format subrecipes for API (convert from form data to API format)
const formattedSubRecipes =
subRecipes.length > 0
? subRecipes.map((subRecipe) => ({
name: subRecipe.name,
path: subRecipe.path,
description: subRecipe.description || undefined,
values:
subRecipe.values && Object.keys(subRecipe.values).length > 0
? subRecipe.values
: undefined,
sequential_when_repeated: subRecipe.sequential_when_repeated,
}))
: undefined;

const cleanedExtensions = extensions?.map(
(extension: ExtensionConfig & { envs?: unknown; enabled?: boolean }) => {
const { envs: _envs, enabled: _enabled, ...rest } = extension;
Expand Down Expand Up @@ -172,6 +199,7 @@ export default function CreateEditRecipeModal({
prompt: prompt || undefined,
parameters: formattedParameters,
response: responseConfig,
sub_recipes: formattedSubRecipes,
extensions: cleanedExtensions,
settings,
};
Expand All @@ -184,6 +212,7 @@ export default function CreateEditRecipeModal({
prompt,
parameters,
jsonSchema,
subRecipes,
model,
provider,
extensions,
Expand Down Expand Up @@ -258,6 +287,7 @@ export default function CreateEditRecipeModal({
activities,
parameters,
jsonSchema,
subRecipes,
model,
provider,
extensions,
Expand Down Expand Up @@ -293,7 +323,11 @@ export default function CreateEditRecipeModal({
try {
const recipe = getCurrentRecipe();

await saveRecipe(recipe, recipeId);
const { id: savedRecipeId } = await saveRecipe(recipe, recipeId);

if (onRecipeSaved) {
onRecipeSaved(savedRecipeId);
}

onClose(true);

Expand Down Expand Up @@ -327,9 +361,8 @@ export default function CreateEditRecipeModal({
try {
const recipe = getCurrentRecipe();

const savedId = await saveRecipe(recipe, recipeId);
const { id: savedId } = await saveRecipe(recipe, recipeId);

// Close modal first
onClose(true);

window.electron.createChatWindow({ recipeId: savedId });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export default function CreateRecipeFromSessionModal({
activities: [] as string[],
parameters: [] as RecipeParameter[],
jsonSchema: '',
subRecipes: [],
Comment thread
Abhijay007 marked this conversation as resolved.
recipeName: '',
global: true,
} as RecipeFormData,
Expand Down Expand Up @@ -156,6 +157,20 @@ export default function CreateRecipeFromSessionModal({

setIsCreating(true);
try {
const formattedSubRecipes =
formData.subRecipes.length > 0
? formData.subRecipes.map((subRecipe) => ({
name: subRecipe.name,
path: subRecipe.path,
description: subRecipe.description || undefined,
values:
subRecipe.values && Object.keys(subRecipe.values).length > 0
? subRecipe.values
: undefined,
sequential_when_repeated: subRecipe.sequential_when_repeated,
}))
: undefined;

const recipe: Recipe = {
title: formData.title,
description: formData.description,
Expand All @@ -180,9 +195,10 @@ export default function CreateRecipeFromSessionModal({
json_schema: JSON.parse(formData.jsonSchema),
}
: undefined,
sub_recipes: formattedSubRecipes,
};

const recipeId = await saveRecipe(recipe, null);
const { id: recipeId } = await saveRecipe(recipe, null);

onRecipeCreated?.(recipe);
onClose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ vi.mock('../../../toasts', () => ({
}));

vi.mock('../../../recipe/recipe_management', () => ({
saveRecipe: vi.fn(),
saveRecipe: vi.fn().mockResolvedValue({ id: 'mock-recipe-id', fileName: 'mock-recipe.yaml' }),
}));

vi.mock('../../ConfigContext', () => ({
Expand Down
Loading
Loading