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
20 changes: 19 additions & 1 deletion crates/goose-server/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
49 changes: 41 additions & 8 deletions crates/goose-server/src/routes/recipe.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -21,41 +22,53 @@ pub struct CreateRecipeRequest {
author: Option<AuthorRequest>,
}

#[derive(Debug, Deserialize)]
#[derive(Debug, Deserialize, ToSchema)]
pub struct AuthorRequest {
#[serde(default)]
contact: Option<String>,
#[serde(default)]
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>,
Expand Down Expand Up @@ -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> {
Expand All @@ -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> {
Expand Down
17 changes: 9 additions & 8 deletions crates/goose/src/recipe/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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")]
Expand Down Expand Up @@ -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
Expand All @@ -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>,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down
Loading
Loading