diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/mod.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/mod.rs index bb1998cf76..cd281e21a3 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/mod.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/mod.rs @@ -1 +1,2 @@ +pub mod omni_gen_image_cost_and_generate_request; pub mod omni_gen_video_cost_and_generate_request; diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_image_cost_and_generate_request.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_image_cost_and_generate_request.rs new file mode 100644 index 0000000000..446d0eca60 --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_image_cost_and_generate_request.rs @@ -0,0 +1,50 @@ +use serde_derive::{Deserialize, Serialize}; +use utoipa::ToSchema; + +use enums::common::generation::common_aspect_ratio::CommonAspectRatio; +use enums::common::generation::common_image_model::CommonImageModel; +use enums::common::generation::common_quality::CommonQuality; +use enums::common::generation::common_resolution::CommonResolution; +use tokens::tokens::media_files::MediaFileToken; + +/// Shared request body for both the image cost estimate and image generation endpoints. +#[derive(Serialize, Deserialize, ToSchema, Debug)] +pub struct OmniGenImageCostAndGenerateRequest { + /// REQUIRED (even if marked optional) + /// Idempotency token to prevent duplicate requests. + /// If not supplied, we'll generate one for the required providers. + pub idempotency_token: Option, + + /// REQUIRED (even if marked optional) + /// Which model to use. + pub model: Option, + + /// The prompt for the image generation. + pub prompt: Option, + + /// Input images for image editing. + /// If present, we're doing image editing (image-to-image). + /// If absent, we're doing text-to-image. + pub image_media_tokens: Option>, + + /// The resolution to use. + pub resolution: Option, + + /// The aspect ratio to use. + pub aspect_ratio: Option, + + /// The quality to use. + pub quality: Option, + + /// How many images to generate. + pub image_batch_count: Option, + + /// Only for angle manipulation models. + pub horizontal_angle: Option, + + /// Only for angle manipulation models. + pub vertical_angle: Option, + + /// Only for angle manipulation models. + pub zoom: Option, +} diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_video_cost_and_generate_request.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_video_cost_and_generate_request.rs index 8f0222e8cb..dd836936c0 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_video_cost_and_generate_request.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_and_generate_requests/omni_gen_video_cost_and_generate_request.rs @@ -10,11 +10,13 @@ use tokens::tokens::media_files::MediaFileToken; /// Shared request body for both the video cost estimate and video generation endpoints. #[derive(Serialize, Deserialize, ToSchema, Debug)] pub struct OmniGenVideoCostAndGenerateRequest { + /// REQUIRED (even if marked optional) /// Idempotency token to prevent duplicate requests. - pub idempotency_token: String, + pub idempotency_token: Option, + /// REQUIRED (even if marked optional) /// Which model to use. - pub model: CommonVideoModel, + pub model: Option, /// The text prompt for the video generation. pub prompt: Option, diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/mod.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/mod.rs index 2fa4c396d3..7f9b8f7a82 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/mod.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/mod.rs @@ -1 +1,2 @@ +pub mod omni_gen_image_cost_response; pub mod omni_gen_video_cost_response; diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/omni_gen_image_cost_response.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/omni_gen_image_cost_response.rs new file mode 100644 index 0000000000..51b5e9dabd --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/cost_response/omni_gen_image_cost_response.rs @@ -0,0 +1,26 @@ +use serde_derive::{Deserialize, Serialize}; +use utoipa::ToSchema; + +/// Response body for the omni-gen image cost estimate endpoint. +#[derive(Serialize, Deserialize, ToSchema)] +pub struct OmniGenImageCostResponse { + pub success: bool, + + /// Estimated cost in credits. + pub cost_in_credits: Option, + + /// Estimated cost in USD cents. + pub cost_in_usd_cents: Option, + + /// Whether the generation is free for this user/plan. + pub is_free: bool, + + /// Whether the user has unlimited generations. + pub is_unlimited: bool, + + /// Whether the user is rate limited. + pub is_rate_limited: bool, + + /// Whether the output will have a watermark. + pub has_watermark: bool, +} diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/mod.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/mod.rs index 94869beec1..2c0ff6f1f7 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/mod.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/mod.rs @@ -1 +1,2 @@ +pub mod omni_gen_image_generate_response; pub mod omni_gen_video_generate_response; diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/omni_gen_image_generate_response.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/omni_gen_image_generate_response.rs new file mode 100644 index 0000000000..9038747048 --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/generate_response/omni_gen_image_generate_response.rs @@ -0,0 +1,10 @@ +use serde_derive::{Deserialize, Serialize}; +use tokens::tokens::generic_inference_jobs::InferenceJobToken; +use utoipa::ToSchema; + +/// Response body for the omni-gen image generation endpoint. +#[derive(Serialize, Deserialize, ToSchema)] +pub struct OmniGenImageGenerateResponse { + pub success: bool, + pub inference_job_token: InferenceJobToken, +} diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/mod.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/mod.rs index ad63ceac90..9af0a97e7b 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/mod.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/mod.rs @@ -1 +1,2 @@ +pub mod omni_gen_image_models; pub mod omni_gen_video_models; diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_image_models.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_image_models.rs new file mode 100644 index 0000000000..2339c9a276 --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_image_models.rs @@ -0,0 +1,32 @@ +use serde_derive::{Deserialize, Serialize}; +use utoipa::{IntoParams, ToSchema}; + +/// Query string parameters for the image models endpoint. +#[derive(Deserialize, IntoParams)] +pub struct OmniGenImageModelsQuery { + /// Which provider's models to list. Defaults to "artcraft" if absent. + pub provider: Option, +} + +/// The provider filter for the models endpoint. +#[derive(Serialize, Deserialize, ToSchema, Debug, Clone, Copy)] +#[serde(rename_all = "snake_case")] +pub enum OmniGenImageModelsProvider { + /// Only models available through ArtCraft. + Artcraft, + /// All known models across all providers. + All, +} + +impl Default for OmniGenImageModelsProvider { + fn default() -> Self { + Self::Artcraft + } +} + +/// Response body for the image models endpoint. +/// TBD — fields will be added later. +#[derive(Serialize, ToSchema)] +pub struct OmniGenImageModelsResponse { + pub success: bool, +} diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_video_models.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_video_models.rs index 2aa7bb0f2e..14b579298f 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_video_models.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/omni_gen/models/omni_gen_video_models.rs @@ -5,20 +5,20 @@ use utoipa::{IntoParams, ToSchema}; #[derive(Deserialize, IntoParams)] pub struct OmniGenVideoModelsQuery { /// Which provider's models to list. Defaults to "artcraft" if absent. - pub provider: Option, + pub provider: Option, } /// The provider filter for the models endpoint. #[derive(Serialize, Deserialize, ToSchema, Debug, Clone, Copy)] #[serde(rename_all = "snake_case")] -pub enum OmniGenModelsProvider { +pub enum OmniGenVideoModelsProvider { /// Only models available through ArtCraft. Artcraft, /// All known models across all providers. All, } -impl Default for OmniGenModelsProvider { +impl Default for OmniGenVideoModelsProvider { fn default() -> Self { Self::Artcraft } diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/image/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/image/mod.rs new file mode 100644 index 0000000000..757c9bfb83 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/image/mod.rs @@ -0,0 +1 @@ +pub mod omni_gen_image_cost_handler; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/image/omni_gen_image_cost_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/image/omni_gen_image_cost_handler.rs new file mode 100644 index 0000000000..db69908229 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/image/omni_gen_image_cost_handler.rs @@ -0,0 +1,31 @@ +use std::sync::Arc; + +use actix_web::web::Json; +use actix_web::{web, HttpRequest}; + +use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_image_cost_and_generate_request::OmniGenImageCostAndGenerateRequest; +use artcraft_api_defs::omni_gen::cost_response::omni_gen_image_cost_response::OmniGenImageCostResponse; + +use crate::http_server::common_responses::common_web_error::CommonWebError; +use crate::state::server_state::ServerState; + +/// Estimate the cost of an image generation. +#[utoipa::path( + post, + tag = "Omni Gen", + path = "/v1/omni_gen/cost/image", + request_body = OmniGenImageCostAndGenerateRequest, + responses( + (status = 200, description = "Success", body = OmniGenImageCostResponse), + (status = 400, description = "Bad input"), + (status = 401, description = "Unauthorized"), + (status = 500, description = "Server error"), + ), +)] +pub async fn omni_gen_image_cost_handler( + _http_request: HttpRequest, + _request: Json, + _server_state: web::Data>, +) -> Result, CommonWebError> { + todo!() +} diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/mod.rs index b04b953edb..c10a6ca15e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/cost/mod.rs @@ -1 +1,2 @@ +pub mod image; pub mod video; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/image/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/image/mod.rs new file mode 100644 index 0000000000..76043b3426 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/image/mod.rs @@ -0,0 +1 @@ +pub mod omni_gen_image_generate_handler; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/image/omni_gen_image_generate_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/image/omni_gen_image_generate_handler.rs new file mode 100644 index 0000000000..424bc816db --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/image/omni_gen_image_generate_handler.rs @@ -0,0 +1,32 @@ +use std::sync::Arc; + +use actix_web::web::Json; +use actix_web::{web, HttpRequest}; + +use artcraft_api_defs::omni_gen::cost_and_generate_requests::omni_gen_image_cost_and_generate_request::OmniGenImageCostAndGenerateRequest; +use artcraft_api_defs::omni_gen::generate_response::omni_gen_image_generate_response::OmniGenImageGenerateResponse; + +use crate::http_server::common_responses::common_web_error::CommonWebError; +use crate::state::server_state::ServerState; + +/// Generate an image using the omni-gen unified endpoint. +#[utoipa::path( + post, + tag = "Omni Gen", + path = "/v1/omni_gen/generate/image", + request_body = OmniGenImageCostAndGenerateRequest, + responses( + (status = 200, description = "Success", body = OmniGenImageGenerateResponse), + (status = 400, description = "Bad input"), + (status = 401, description = "Unauthorized"), + (status = 402, description = "Payment required"), + (status = 500, description = "Server error"), + ), +)] +pub async fn omni_gen_image_generate_handler( + _http_request: HttpRequest, + _request: Json, + _server_state: web::Data>, +) -> Result, CommonWebError> { + todo!() +} diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/mod.rs index b04b953edb..c10a6ca15e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/mod.rs @@ -1 +1,2 @@ +pub mod image; pub mod video; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/image/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/image/mod.rs new file mode 100644 index 0000000000..e4d7dda995 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/image/mod.rs @@ -0,0 +1 @@ +pub mod omni_gen_image_models_handler; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/image/omni_gen_image_models_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/image/omni_gen_image_models_handler.rs new file mode 100644 index 0000000000..8bdcbf8ef0 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/image/omni_gen_image_models_handler.rs @@ -0,0 +1,31 @@ +use std::sync::Arc; + +use actix_web::web::{Json, Query}; +use actix_web::{web, HttpRequest}; + +use artcraft_api_defs::omni_gen::models::omni_gen_image_models::{ + OmniGenImageModelsQuery, + OmniGenImageModelsResponse, +}; + +use crate::http_server::common_responses::common_web_error::CommonWebError; +use crate::state::server_state::ServerState; + +/// List available image models. +#[utoipa::path( + get, + tag = "Omni Gen", + path = "/v1/omni_gen/models/image", + params(OmniGenImageModelsQuery), + responses( + (status = 200, description = "Success", body = OmniGenImageModelsResponse), + (status = 500, description = "Server error"), + ), +)] +pub async fn omni_gen_image_models_handler( + _http_request: HttpRequest, + _query: Query, + _server_state: web::Data>, +) -> Result, CommonWebError> { + todo!() +} diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/mod.rs index b04b953edb..c10a6ca15e 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/models/mod.rs @@ -1 +1,2 @@ +pub mod image; pub mod video; diff --git a/crates/service/web/storyteller_web/src/http_server/routes/application_routes/omni_gen_routes.rs b/crates/service/web/storyteller_web/src/http_server/routes/application_routes/omni_gen_routes.rs index 13e1802fee..38e1e4b650 100644 --- a/crates/service/web/storyteller_web/src/http_server/routes/application_routes/omni_gen_routes.rs +++ b/crates/service/web/storyteller_web/src/http_server/routes/application_routes/omni_gen_routes.rs @@ -3,8 +3,11 @@ use actix_service::ServiceFactory; use actix_web::dev::{ServiceRequest, ServiceResponse}; use actix_web::{web, App, Error, HttpResponse}; +use crate::http_server::endpoints::omni_gen::cost::image::omni_gen_image_cost_handler::omni_gen_image_cost_handler; use crate::http_server::endpoints::omni_gen::cost::video::omni_gen_video_cost_handler::omni_gen_video_cost_handler; +use crate::http_server::endpoints::omni_gen::generate::image::omni_gen_image_generate_handler::omni_gen_image_generate_handler; use crate::http_server::endpoints::omni_gen::generate::video::omni_gen_video_generate_handler::omni_gen_video_generate_handler; +use crate::http_server::endpoints::omni_gen::models::image::omni_gen_image_models_handler::omni_gen_image_models_handler; use crate::http_server::endpoints::omni_gen::models::video::omni_gen_video_models_handler::omni_gen_video_models_handler; pub fn add_omni_gen_routes(app: App) -> App @@ -24,18 +27,30 @@ where .route(web::post().to(omni_gen_video_cost_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) + .service(web::resource("/image") + .route(web::post().to(omni_gen_image_cost_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) ) .service(web::scope("/generate") .service(web::resource("/video") .route(web::post().to(omni_gen_video_generate_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) + .service(web::resource("/image") + .route(web::post().to(omni_gen_image_generate_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) ) .service(web::scope("/models") .service(web::resource("/video") .route(web::get().to(omni_gen_video_models_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) + .service(web::resource("/image") + .route(web::get().to(omni_gen_image_models_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) ) ) }