refactor: Use openapi for recipe endpoint types and in frontend (#3548)

This commit is contained in:
Jarrod Sibbison
2025-07-21 19:40:13 +10:00
committed by GitHub
parent a996227381
commit d085126709
10 changed files with 863 additions and 132 deletions
+19 -1
View File
@@ -318,7 +318,10 @@ derive_utoipa!(Annotations as AnnotationsSchema);
super::routes::schedule::unpause_schedule,
super::routes::schedule::kill_running_job,
super::routes::schedule::inspect_running_job,
super::routes::schedule::sessions_handler
super::routes::schedule::sessions_handler,
super::routes::recipe::create_recipe,
super::routes::recipe::encode_recipe,
super::routes::recipe::decode_recipe
),
components(schemas(
super::routes::config_management::UpsertConfigQuery,
@@ -375,6 +378,21 @@ derive_utoipa!(Annotations as AnnotationsSchema);
super::routes::schedule::ListSchedulesResponse,
super::routes::schedule::SessionsQuery,
super::routes::schedule::SessionDisplayInfo,
super::routes::recipe::CreateRecipeRequest,
super::routes::recipe::AuthorRequest,
super::routes::recipe::CreateRecipeResponse,
super::routes::recipe::EncodeRecipeRequest,
super::routes::recipe::EncodeRecipeResponse,
super::routes::recipe::DecodeRecipeRequest,
super::routes::recipe::DecodeRecipeResponse,
goose::recipe::Recipe,
goose::recipe::Author,
goose::recipe::Settings,
goose::recipe::RecipeParameter,
goose::recipe::RecipeParameterInputType,
goose::recipe::RecipeParameterRequirement,
goose::recipe::Response,
goose::recipe::SubRecipe,
))
)]
pub struct ApiDoc;
+41 -8
View File
@@ -5,10 +5,11 @@ use goose::message::Message;
use goose::recipe::Recipe;
use goose::recipe_deeplink;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use crate::state::AppState;
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct CreateRecipeRequest {
messages: Vec<Message>,
// Required metadata
@@ -21,7 +22,7 @@ pub struct CreateRecipeRequest {
author: Option<AuthorRequest>,
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct AuthorRequest {
#[serde(default)]
contact: Option<String>,
@@ -29,33 +30,45 @@ pub struct AuthorRequest {
metadata: Option<String>,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, ToSchema)]
pub struct CreateRecipeResponse {
recipe: Option<Recipe>,
error: Option<String>,
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct EncodeRecipeRequest {
recipe: Recipe,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, ToSchema)]
pub struct EncodeRecipeResponse {
deeplink: String,
}
#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct DecodeRecipeRequest {
deeplink: String,
}
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, ToSchema)]
pub struct DecodeRecipeResponse {
recipe: Recipe,
}
/// Create a Recipe configuration from the current state of an agent
#[utoipa::path(
post,
path = "/recipes/create",
request_body = CreateRecipeRequest,
responses(
(status = 200, description = "Recipe created successfully", body = CreateRecipeResponse),
(status = 400, description = "Bad request"),
(status = 412, description = "Precondition failed - Agent not available"),
(status = 500, description = "Internal server error")
),
tag = "Recipe Management"
)]
/// Create a Recipe configuration from the current session
async fn create_recipe(
State(state): State<Arc<AppState>>,
Json(request): Json<CreateRecipeRequest>,
@@ -105,6 +118,16 @@ async fn create_recipe(
}
}
#[utoipa::path(
post,
path = "/recipes/encode",
request_body = EncodeRecipeRequest,
responses(
(status = 200, description = "Recipe encoded successfully", body = EncodeRecipeResponse),
(status = 400, description = "Bad request")
),
tag = "Recipe Management"
)]
async fn encode_recipe(
Json(request): Json<EncodeRecipeRequest>,
) -> Result<Json<EncodeRecipeResponse>, StatusCode> {
@@ -117,6 +140,16 @@ async fn encode_recipe(
}
}
#[utoipa::path(
post,
path = "/recipes/decode",
request_body = DecodeRecipeRequest,
responses(
(status = 200, description = "Recipe decoded successfully", body = DecodeRecipeResponse),
(status = 400, description = "Bad request")
),
tag = "Recipe Management"
)]
async fn decode_recipe(
Json(request): Json<DecodeRecipeRequest>,
) -> Result<Json<DecodeRecipeResponse>, StatusCode> {
+9 -8
View File
@@ -6,6 +6,7 @@ use std::fmt;
use crate::agents::extension::ExtensionConfig;
use serde::de::Deserializer;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
pub mod build_recipe;
pub mod read_recipe_file_content;
@@ -67,7 +68,7 @@ fn default_version() -> String {
/// sub_recipes: None,
/// };
///
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct Recipe {
// Required fields
#[serde(default = "default_version")]
@@ -110,7 +111,7 @@ pub struct Recipe {
pub sub_recipes: Option<Vec<SubRecipe>>, // sub-recipes for the recipe
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct Author {
#[serde(skip_serializing_if = "Option::is_none")]
pub contact: Option<String>, // creator/contact information of the recipe
@@ -119,7 +120,7 @@ pub struct Author {
pub metadata: Option<String>, // any additional metadata for the author
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct Settings {
#[serde(skip_serializing_if = "Option::is_none")]
pub goose_provider: Option<String>,
@@ -131,13 +132,13 @@ pub struct Settings {
pub temperature: Option<f32>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct Response {
#[serde(skip_serializing_if = "Option::is_none")]
pub json_schema: Option<serde_json::Value>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct SubRecipe {
pub name: String,
pub path: String,
@@ -172,7 +173,7 @@ where
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum RecipeParameterRequirement {
Required,
@@ -190,7 +191,7 @@ impl fmt::Display for RecipeParameterRequirement {
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum RecipeParameterInputType {
String,
@@ -210,7 +211,7 @@ impl fmt::Display for RecipeParameterInputType {
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct RecipeParameter {
pub key: String,
pub input_type: RecipeParameterInputType,