-
Notifications
You must be signed in to change notification settings - Fork 2.6k
chore: move list recipes and archive recipe to goose server #4422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
61e8aef
added list recipe route
lifeizhou-ap 0e1f9ef
Merge branch 'main' into lifei/more-recipe-tracking
lifeizhou-ap ed77066
list_recipe wip
lifeizhou-ap c703516
added list recipe endpoints
lifeizhou-ap 4433b92
generate open api
lifeizhou-ap 429d3ab
fixed the attribute name
lifeizhou-ap 8043c08
update ui to use api to list recipes. todo: load recipe, and remove s…
lifeizhou-ap f9510c4
return recipe id
lifeizhou-ap f872413
removed unused functions in ui
lifeizhou-ap 6b7cbe1
move archive recipe to goose server
lifeizhou-ap b92d4ed
Merge branch 'main' into lifei/move-list-archive-recipes-server
lifeizhou-ap 17d5a51
show locale date string
lifeizhou-ap 030303d
removed archive
lifeizhou-ap 73a3311
Revert "removed archive"
lifeizhou-ap 0c4fb89
changed archive to delete
lifeizhou-ap 1753564
ui change
lifeizhou-ap 987a587
list all recipes without include archived query
lifeizhou-ap 85836c3
used built-in hash
lifeizhou-ap 310e35f
move recipe manifest to server as view object
lifeizhou-ap 3ad6ae1
removed recipe mod in goose server and moved it into router mod
lifeizhou-ap File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -53,3 +53,4 @@ path = "src/bin/generate_schema.rs" | |
| [dev-dependencies] | ||
| tower = "0.5" | ||
| async-trait = "0.1" | ||
| tempfile = "3.15.0" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| use std::fs; | ||
| use std::hash::DefaultHasher; | ||
| use std::hash::{Hash, Hasher}; | ||
| use std::path::PathBuf; | ||
|
|
||
| use anyhow::Result; | ||
| use etcetera::{choose_app_strategy, AppStrategy}; | ||
|
|
||
| use goose::config::APP_STRATEGY; | ||
| use goose::recipe::read_recipe_file_content::read_recipe_file; | ||
| use goose::recipe::Recipe; | ||
|
|
||
| use std::path::Path; | ||
|
|
||
| use serde::{Deserialize, Serialize}; | ||
| use utoipa::ToSchema; | ||
|
|
||
| pub struct RecipeManifestWithPath { | ||
| pub id: String, | ||
| pub name: String, | ||
| pub is_global: bool, | ||
| pub recipe: Recipe, | ||
| pub file_path: PathBuf, | ||
| pub last_modified: String, | ||
| } | ||
|
|
||
| fn short_id_from_path(path: &str) -> String { | ||
| let mut hasher = DefaultHasher::new(); | ||
| path.hash(&mut hasher); | ||
| let h = hasher.finish(); | ||
| format!("{:016x}", h) | ||
| } | ||
|
|
||
| fn load_recipes_from_path(path: &PathBuf) -> Result<Vec<RecipeManifestWithPath>> { | ||
| let mut recipe_manifests_with_path = Vec::new(); | ||
| if path.exists() { | ||
| for entry in fs::read_dir(path)? { | ||
| let path = entry?.path(); | ||
| if path.extension() == Some("yaml".as_ref()) { | ||
| let Ok(recipe_file) = read_recipe_file(path.clone()) else { | ||
| continue; | ||
| }; | ||
| let Ok(recipe) = Recipe::from_content(&recipe_file.content) else { | ||
| continue; | ||
| }; | ||
| let Ok(recipe_metadata) = RecipeManifestMetadata::from_yaml_file(&path) else { | ||
| continue; | ||
| }; | ||
| let Ok(last_modified) = fs::metadata(path.clone()).map(|m| { | ||
| chrono::DateTime::<chrono::Utc>::from(m.modified().unwrap()).to_rfc3339() | ||
| }) else { | ||
| continue; | ||
| }; | ||
|
|
||
| let manifest_with_path = RecipeManifestWithPath { | ||
| id: short_id_from_path(recipe_file.file_path.to_string_lossy().as_ref()), | ||
| name: recipe_metadata.name, | ||
| is_global: recipe_metadata.is_global, | ||
| recipe, | ||
| file_path: recipe_file.file_path, | ||
| last_modified, | ||
| }; | ||
| recipe_manifests_with_path.push(manifest_with_path); | ||
| } | ||
| } | ||
| } | ||
| Ok(recipe_manifests_with_path) | ||
| } | ||
|
|
||
| pub fn get_all_recipes_manifests() -> Result<Vec<RecipeManifestWithPath>> { | ||
| let current_dir = std::env::current_dir()?; | ||
| let local_recipe_path = current_dir.join(".goose/recipes"); | ||
|
|
||
| let global_recipe_path = choose_app_strategy(APP_STRATEGY.clone()) | ||
| .expect("goose requires a home dir") | ||
| .config_dir() | ||
| .join("recipes"); | ||
|
|
||
| let mut recipe_manifests_with_path = Vec::new(); | ||
|
|
||
| recipe_manifests_with_path.extend(load_recipes_from_path(&local_recipe_path)?); | ||
| recipe_manifests_with_path.extend(load_recipes_from_path(&global_recipe_path)?); | ||
| recipe_manifests_with_path.sort_by(|a, b| b.last_modified.cmp(&a.last_modified)); | ||
|
|
||
| Ok(recipe_manifests_with_path) | ||
| } | ||
|
|
||
| // this is a temporary struct to deserilize the UI recipe files. should not be used for other purposes. | ||
| #[derive(Serialize, Deserialize, Debug, Clone, ToSchema)] | ||
| struct RecipeManifestMetadata { | ||
| pub name: String, | ||
| #[serde(rename = "isGlobal")] | ||
| pub is_global: bool, | ||
| } | ||
|
|
||
| impl RecipeManifestMetadata { | ||
| pub fn from_yaml_file(path: &Path) -> Result<Self> { | ||
| let content = fs::read_to_string(path) | ||
| .map_err(|e| anyhow::anyhow!("Failed to read file {}: {}", path.display(), e))?; | ||
| let metadata = serde_yaml::from_str::<Self>(&content) | ||
| .map_err(|e| anyhow::anyhow!("Failed to parse YAML: {}", e))?; | ||
| Ok(metadata) | ||
| } | ||
| } | ||
|
|
||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| use std::fs; | ||
| use tempfile::tempdir; | ||
|
|
||
| #[test] | ||
| fn test_from_yaml_file_success() { | ||
| let temp_dir = tempdir().unwrap(); | ||
| let file_path = temp_dir.path().join("test_recipe.yaml"); | ||
|
|
||
| let yaml_content = r#" | ||
| name: "Test Recipe" | ||
| isGlobal: true | ||
| recipe: recipe_content | ||
| "#; | ||
|
|
||
| fs::write(&file_path, yaml_content).unwrap(); | ||
|
|
||
| let result = RecipeManifestMetadata::from_yaml_file(&file_path).unwrap(); | ||
|
|
||
| assert_eq!(result.name, "Test Recipe"); | ||
| assert_eq!(result.is_global, true); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This in memory map maintains the mapping of recipe id (hashed based on recipe path) and recipe path. recipe id is the key of map