diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_dev.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_dev.rs index 4080aa6b80..92241c5822 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_dev.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_dev.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -16,38 +19,45 @@ pub async fn execute_fal_flux_1_dev( plan: &PlanFalFlux1Dev, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if let Some(image_url) = &plan.maybe_image_url { + let (webhook_response, outbound_request) = if let Some(image_url) = &plan.maybe_image_url { // Image-to-image mode + let request = Flux1DevEditImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_url: image_url.clone(), + num_images: plan.num_images.to_edit(), + }; + let outbound: Arc = Arc::new(request.clone()); let args = Flux1DevEditImageArgs { - request: Flux1DevEditImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_url: image_url.clone(), - num_images: plan.num_images.to_edit(), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_flux_1_dev_edit_image_webhook(args) + let resp = enqueue_flux_1_dev_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { // Text-to-image mode + let request = Flux1DevRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + aspect_ratio: plan.aspect_ratio, + num_images: plan.num_images.to_t2i(), + }; + let outbound: Arc = Arc::new(request.clone()); let args = Flux1DevArgs { - request: Flux1DevRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - aspect_ratio: plan.aspect_ratio, - num_images: plan.num_images.to_t2i(), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_flux_1_dev_text_to_image_webhook(args) + let resp = enqueue_flux_1_dev_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_schnell.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_schnell.rs index 07b738f3fc..735df6f1dc 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_schnell.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_1_schnell.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -16,38 +19,45 @@ pub async fn execute_fal_flux_1_schnell( plan: &PlanFalFlux1Schnell, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if let Some(image_url) = &plan.maybe_image_url { + let (webhook_response, outbound_request) = if let Some(image_url) = &plan.maybe_image_url { // Image-to-image (redux) mode + let request = Flux1SchnellEditImageRequest { + image_url: image_url.clone(), + num_images: plan.num_images.to_edit(), + image_size: plan.edit_image_size, + }; + let outbound: Arc = Arc::new(request.clone()); let args = Flux1SchnellEditImageArgs { - request: Flux1SchnellEditImageRequest { - image_url: image_url.clone(), - num_images: plan.num_images.to_edit(), - image_size: plan.edit_image_size, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_flux_1_schnell_edit_image_webhook(args) + let resp = enqueue_flux_1_schnell_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { // Text-to-image mode + let request = Flux1SchnellRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + aspect_ratio: plan.t2i_aspect_ratio, + num_images: plan.num_images.to_t2i(), + }; + let outbound: Arc = Arc::new(request.clone()); let args = Flux1SchnellArgs { - request: Flux1SchnellRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - aspect_ratio: plan.t2i_aspect_ratio, - num_images: plan.num_images.to_t2i(), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_flux_1_schnell_text_to_image_webhook(args) + let resp = enqueue_flux_1_schnell_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1.rs index a5e58dbe9c..c871e942e2 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,12 +16,14 @@ pub async fn execute_fal_flux_pro_1p1( plan: &PlanFalFluxPro11, fal_client: &RouterFalClient, ) -> Result { + let request = FluxPro11Request { + prompt: plan.prompt.clone().unwrap_or_default(), + aspect_ratio: plan.aspect_ratio, + num_images: plan.num_images.to_fal(), + }; + let outbound_request: Arc = Arc::new(request.clone()); let args = FluxPro11Args { - request: FluxPro11Request { - prompt: plan.prompt.clone().unwrap_or_default(), - aspect_ratio: plan.aspect_ratio, - num_images: plan.num_images.to_fal(), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; @@ -30,5 +35,6 @@ pub async fn execute_fal_flux_pro_1p1( Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1_ultra.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1_ultra.rs index 5ff4d0a915..be689f43a7 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1_ultra.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_flux_pro_1p1_ultra.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,12 +16,14 @@ pub async fn execute_fal_flux_pro_1p1_ultra( plan: &PlanFalFluxPro11Ultra, fal_client: &RouterFalClient, ) -> Result { + let request = FluxPro11UltraRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + aspect_ratio: plan.aspect_ratio, + num_images: plan.num_images.to_fal(), + }; + let outbound_request: Arc = Arc::new(request.clone()); let args = FluxPro11UltraArgs { - request: FluxPro11UltraRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - aspect_ratio: plan.aspect_ratio, - num_images: plan.num_images.to_fal(), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; @@ -30,5 +35,6 @@ pub async fn execute_fal_flux_pro_1p1_ultra( Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1.rs index d45b23cfd2..0af4c18787 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,46 +21,53 @@ pub async fn execute_fal_gpt_image_1( plan: &PlanFalGptImage1, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { + let request = EnqueueGptImage1TextToImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + num_images: plan.num_images.to_t2i(), + image_size: plan.image_size.map(|s| s.to_t2i()), + quality: Some(plan.quality.to_t2i()), + background: None, + output_format: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueGptImage1TextToImageArgs { - request: EnqueueGptImage1TextToImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - num_images: plan.num_images.to_t2i(), - image_size: plan.image_size.map(|s| s.to_t2i()), - quality: Some(plan.quality.to_t2i()), - background: None, - output_format: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gpt_image_1_text_to_image_webhook(args) + let resp = enqueue_gpt_image_1_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { + let request = EnqueueGptImage1EditImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_urls: plan.image_urls.clone(), + num_images: plan.num_images.to_edit(), + mask_image_url: None, + image_size: plan.image_size.map(|s| s.to_edit()), + quality: Some(plan.quality.to_edit()), + input_fidelity: None, + background: None, + output_format: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueGptImage1EditImageArgs { - request: EnqueueGptImage1EditImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_urls: plan.image_urls.clone(), - num_images: plan.num_images.to_edit(), - mask_image_url: None, - image_size: plan.image_size.map(|s| s.to_edit()), - quality: Some(plan.quality.to_edit()), - input_fidelity: None, - background: None, - output_format: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gpt_image_1_edit_image_webhook(args) + let resp = enqueue_gpt_image_1_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1p5.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1p5.rs index 37c4510cd1..46361e36c8 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1p5.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_1p5.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,45 +21,52 @@ pub async fn execute_fal_gpt_image_1p5( plan: &PlanFalGptImage1p5, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { + let request = EnqueueGptImage1p5TextToImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + num_images: plan.num_images.to_t2i(), + image_size: plan.image_size.map(|s| s.to_t2i()), + background: None, + quality: Some(plan.quality.to_t2i()), + output_format: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueGptImage1p5TextToImageArgs { - request: EnqueueGptImage1p5TextToImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - num_images: plan.num_images.to_t2i(), - image_size: plan.image_size.map(|s| s.to_t2i()), - background: None, - quality: Some(plan.quality.to_t2i()), - output_format: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gpt_image_1p5_text_to_image_webhook(args) + let resp = enqueue_gpt_image_1p5_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { + let request = EnqueueGptImage1p5EditImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_urls: plan.image_urls.clone(), + num_images: plan.num_images.to_edit(), + mask_image_url: None, + image_size: plan.image_size.map(|s| s.to_edit()), + background: None, + quality: Some(plan.quality.to_edit()), + input_fidelity: None, + output_format: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueGptImage1p5EditImageArgs { - request: EnqueueGptImage1p5EditImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_urls: plan.image_urls.clone(), - num_images: plan.num_images.to_edit(), - mask_image_url: None, - image_size: plan.image_size.map(|s| s.to_edit()), - background: None, - quality: Some(plan.quality.to_edit()), - input_fidelity: None, - output_format: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gpt_image_1p5_image_edit_webhook(args) + let resp = enqueue_gpt_image_1p5_image_edit_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_2.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_2.rs index 8fdf45de52..5740c552e6 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_2.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_gpt_image_2.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,43 +21,50 @@ pub async fn execute_fal_gpt_image_2( plan: &PlanFalGptImage2, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { + let request = EnqueueGptImage2TextToImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + num_images: plan.num_images.to_t2i(), + image_size: plan.image_size.map(|s| s.to_t2i()), + quality: Some(plan.quality.to_t2i()), + output_format: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueGptImage2TextToImageArgs { - request: EnqueueGptImage2TextToImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - num_images: plan.num_images.to_t2i(), - image_size: plan.image_size.map(|s| s.to_t2i()), - quality: Some(plan.quality.to_t2i()), - output_format: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gpt_image_2_text_to_image_webhook(args) + let resp = enqueue_gpt_image_2_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { + let request = EnqueueGptImage2EditImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_urls: plan.image_urls.clone(), + num_images: plan.num_images.to_edit(), + mask_url: None, + image_size: plan.image_size.map(|s| s.to_edit()), + quality: Some(plan.quality.to_edit()), + output_format: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueGptImage2EditImageArgs { - request: EnqueueGptImage2EditImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_urls: plan.image_urls.clone(), - num_images: plan.num_images.to_edit(), - mask_url: None, - image_size: plan.image_size.map(|s| s.to_edit()), - quality: Some(plan.quality.to_edit()), - output_format: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gpt_image_2_edit_image_webhook(args) + let resp = enqueue_gpt_image_2_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana.rs index 5a3e6631f9..03cf930657 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -20,40 +23,47 @@ pub async fn execute_fal_nano_banana( plan: &PlanFalNanoBanana, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { // Text-to-image mode + let request = Gemini25FlashTextToImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + num_images: to_t2i_num_images(plan.num_images), + aspect_ratio: plan.t2i_aspect_ratio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = Gemini25FlashTextToImageArgs { - request: Gemini25FlashTextToImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - num_images: to_t2i_num_images(plan.num_images), - aspect_ratio: plan.t2i_aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gemini_25_flash_text_to_image_webhook(args) + let resp = enqueue_gemini_25_flash_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { // Image-edit mode + let request = Gemini25FlashEditRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_urls: plan.image_urls.clone(), + num_images: to_edit_num_images(plan.num_images), + aspect_ratio: plan.edit_aspect_ratio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = Gemini25FlashEditArgs { - request: Gemini25FlashEditRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_urls: plan.image_urls.clone(), - num_images: to_edit_num_images(plan.num_images), - aspect_ratio: plan.edit_aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_gemini_25_flash_edit_webhook(args) + let resp = enqueue_gemini_25_flash_edit_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_2.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_2.rs index c1802bea93..94dc5df554 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_2.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_2.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -22,42 +25,49 @@ pub async fn execute_fal_nano_banana_2( plan: &PlanFalNanaBanana2, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { // Text-to-image mode + let request = EnqueueNanoBanana2TextToImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + num_images: to_t2i_num_images(plan.num_images), + resolution: plan.resolution.map(to_t2i_resolution), + aspect_ratio: plan.t2i_aspect_ratio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueNanoBanana2TextToImageArgs { - request: EnqueueNanoBanana2TextToImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - num_images: to_t2i_num_images(plan.num_images), - resolution: plan.resolution.map(to_t2i_resolution), - aspect_ratio: plan.t2i_aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_nano_banana_2_text_to_image_webhook(args) + let resp = enqueue_nano_banana_2_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { // Image-edit mode + let request = EnqueueNanoBanana2EditImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_urls: plan.image_urls.clone(), + num_images: to_edit_num_images(plan.num_images), + resolution: plan.resolution.map(to_edit_resolution), + aspect_ratio: plan.edit_aspect_ratio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueNanoBanana2EditImageArgs { - request: EnqueueNanoBanana2EditImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_urls: plan.image_urls.clone(), - num_images: to_edit_num_images(plan.num_images), - resolution: plan.resolution.map(to_edit_resolution), - aspect_ratio: plan.edit_aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_nano_banana_2_edit_image_webhook(args) + let resp = enqueue_nano_banana_2_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_pro.rs index a3a67941d5..3e87b91528 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_nano_banana_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -21,42 +24,49 @@ pub async fn execute_fal_nano_banana_pro( plan: &PlanFalNanaBananaPro, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { // Text-to-image mode + let request = EnqueueNanoBananaProTextToImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + num_images: to_t2i_num_images(plan.num_images), + resolution: plan.resolution.map(to_t2i_resolution), + aspect_ratio: plan.t2i_aspect_ratio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueNanoBananaProTextToImageArgs { - request: EnqueueNanoBananaProTextToImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - num_images: to_t2i_num_images(plan.num_images), - resolution: plan.resolution.map(to_t2i_resolution), - aspect_ratio: plan.t2i_aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_nano_banana_pro_text_to_image_webhook(args) + let resp = enqueue_nano_banana_pro_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { // Image-edit mode + let request = EnqueueNanoBananaProEditImageRequest { + prompt: plan.prompt.as_deref().unwrap_or("").to_string(), + image_urls: plan.image_urls.clone(), + num_images: to_edit_num_images(plan.num_images), + resolution: plan.resolution.map(to_edit_resolution), + aspect_ratio: plan.edit_aspect_ratio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueNanoBananaProEditImageArgs { - request: EnqueueNanoBananaProEditImageRequest { - prompt: plan.prompt.as_deref().unwrap_or("").to_string(), - image_urls: plan.image_urls.clone(), - num_images: to_edit_num_images(plan.num_images), - resolution: plan.resolution.map(to_edit_resolution), - aspect_ratio: plan.edit_aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_nano_banana_pro_image_edit_webhook(args) + let resp = enqueue_nano_banana_pro_image_edit_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4.rs index ee622b9626..d45086f673 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,39 +21,46 @@ pub async fn execute_fal_seedream_4( plan: &PlanFalSeedream4, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { + let request = EnqueueBytedanceSeedreamV4TextToImageRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + num_images: Some(plan.num_images.to_t2i()), + max_images: None, + image_size: plan.image_size.map(|s| s.to_t2i()), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueBytedanceSeedreamV4TextToImageArgs { - request: EnqueueBytedanceSeedreamV4TextToImageRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - num_images: Some(plan.num_images.to_t2i()), - max_images: None, - image_size: plan.image_size.map(|s| s.to_t2i()), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_bytedance_seedream_v4_text_to_image_webhook(args) + let resp = enqueue_bytedance_seedream_v4_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { + let request = EnqueueBytedanceSeedreamV4EditImageRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + image_urls: plan.image_urls.clone(), + num_images: Some(plan.num_images.to_edit()), + max_images: None, + image_size: plan.image_size.map(|s| s.to_edit()), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueBytedanceSeedreamV4EditImageArgs { - request: EnqueueBytedanceSeedreamV4EditImageRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - image_urls: plan.image_urls.clone(), - num_images: Some(plan.num_images.to_edit()), - max_images: None, - image_size: plan.image_size.map(|s| s.to_edit()), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_bytedance_seedream_v4_edit_image_webhook(args) + let resp = enqueue_bytedance_seedream_v4_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4p5.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4p5.rs index 43970dcfcf..b87cd06573 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4p5.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_4p5.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,39 +21,46 @@ pub async fn execute_fal_seedream_4p5( plan: &PlanFalSeedream4p5, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { + let request = EnqueueBytedanceSeedreamV4p5TextToImageRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + num_images: Some(plan.num_images.to_t2i()), + max_images: None, + image_size: plan.image_size.map(|s| s.to_t2i()), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueBytedanceSeedreamV4p5TextToImageArgs { - request: EnqueueBytedanceSeedreamV4p5TextToImageRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - num_images: Some(plan.num_images.to_t2i()), - max_images: None, - image_size: plan.image_size.map(|s| s.to_t2i()), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_bytedance_seedream_v4p5_text_to_image_webhook(args) + let resp = enqueue_bytedance_seedream_v4p5_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { + let request = EnqueueBytedanceSeedreamV4p5EditImageRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + image_urls: plan.image_urls.clone(), + num_images: Some(plan.num_images.to_edit()), + max_images: None, + image_size: plan.image_size.map(|s| s.to_edit()), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueBytedanceSeedreamV4p5EditImageArgs { - request: EnqueueBytedanceSeedreamV4p5EditImageRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - image_urls: plan.image_urls.clone(), - num_images: Some(plan.num_images.to_edit()), - max_images: None, - image_size: plan.image_size.map(|s| s.to_edit()), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_bytedance_seedream_v4p5_edit_image_webhook(args) + let resp = enqueue_bytedance_seedream_v4p5_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_5_lite.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_5_lite.rs index 6198258a6d..a9d435bde2 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_5_lite.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/execute/fal/generate_image_fal_seedream_5_lite.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,39 +21,46 @@ pub async fn execute_fal_seedream_5_lite( plan: &PlanFalSeedream5Lite, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = if plan.image_urls.is_empty() { + let (webhook_response, outbound_request) = if plan.image_urls.is_empty() { + let request = EnqueueBytedanceSeedreamV5LiteTextToImageRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + num_images: Some(plan.num_images.to_t2i()), + max_images: None, + image_size: plan.image_size.map(|s| s.to_t2i()), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueBytedanceSeedreamV5LiteTextToImageArgs { - request: EnqueueBytedanceSeedreamV5LiteTextToImageRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - num_images: Some(plan.num_images.to_t2i()), - max_images: None, - image_size: plan.image_size.map(|s| s.to_t2i()), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_bytedance_seedream_v5_lite_text_to_image_webhook(args) + let resp = enqueue_bytedance_seedream_v5_lite_text_to_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } else { + let request = EnqueueBytedanceSeedreamV5LiteEditImageRequest { + prompt: plan.prompt.clone().unwrap_or_default(), + image_urls: plan.image_urls.clone(), + num_images: Some(plan.num_images.to_edit()), + max_images: None, + image_size: plan.image_size.map(|s| s.to_edit()), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueBytedanceSeedreamV5LiteEditImageArgs { - request: EnqueueBytedanceSeedreamV5LiteEditImageRequest { - prompt: plan.prompt.clone().unwrap_or_default(), - image_urls: plan.image_urls.clone(), - num_images: Some(plan.num_images.to_edit()), - max_images: None, - image_size: plan.image_size.map(|s| s.to_edit()), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_bytedance_seedream_v5_lite_edit_image_webhook(args) + let resp = enqueue_bytedance_seedream_v5_lite_edit_image_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) }; Ok(GenerateImageResponse::Fal(FalImageResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/generate_image_response.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/generate_image_response.rs index f04171f29c..b238126474 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/generate_image_response.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_image/generate_image_response.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use tokens::tokens::generic_inference_jobs::InferenceJobToken; #[derive(Clone, Debug)] @@ -9,6 +12,11 @@ pub struct ArtcraftImageResponsePayload { pub struct FalImageResponsePayload { pub request_id: Option, pub gateway_request_id: Option, + + /// The outbound request that was sent to Fal. + /// Stored as a trait object so any Request type can be captured. + /// Use `format!("{:?}", ...)` or `format!("{:#?}", ...)` to print. + pub maybe_outbound_request: Option>, } #[derive(Clone, Debug)] diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_1_6_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_1_6_pro.rs index ad0b5cf552..d8baeddcb2 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_1_6_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_1_6_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,14 +16,18 @@ pub async fn execute_fal_kling_1_6_pro( plan: &PlanFalKling16Pro, fal_client: &RouterFalClient, ) -> Result { + let request = Kling1p6ProRequest { + image_url: plan.image_url.clone(), + end_frame_image_url: plan.end_image_url.clone(), + prompt: plan.prompt.clone(), + duration: plan.duration, + aspect_ratio: plan.aspect_ratio, + }; + + let outbound_request: Arc = Arc::new(request.clone()); + let args = Kling1p6ProArgs { - request: Kling1p6ProRequest { - image_url: plan.image_url.clone(), - end_frame_image_url: plan.end_image_url.clone(), - prompt: plan.prompt.clone(), - duration: plan.duration, - aspect_ratio: plan.aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; @@ -32,5 +39,6 @@ pub async fn execute_fal_kling_1_6_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_master.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_master.rs index bd2d812de2..471bc77d6d 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_master.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_master.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,13 +16,17 @@ pub async fn execute_fal_kling_2_1_master( plan: &PlanFalKling21Master, fal_client: &RouterFalClient, ) -> Result { + let request = Kling2p1MasterRequest { + image_url: plan.image_url.clone(), + prompt: plan.prompt.clone(), + duration: plan.duration, + aspect_ratio: plan.aspect_ratio, + }; + + let outbound_request: Arc = Arc::new(request.clone()); + let args = Kling2p1MasterArgs { - request: Kling2p1MasterRequest { - image_url: plan.image_url.clone(), - prompt: plan.prompt.clone(), - duration: plan.duration, - aspect_ratio: plan.aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; @@ -31,5 +38,6 @@ pub async fn execute_fal_kling_2_1_master( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_pro.rs index ebbfe65f74..42a54d470b 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_1_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,14 +16,18 @@ pub async fn execute_fal_kling_2_1_pro( plan: &PlanFalKling21Pro, fal_client: &RouterFalClient, ) -> Result { + let request = Kling2p1ProRequest { + image_url: plan.image_url.clone(), + end_frame_image_url: plan.end_image_url.clone(), + prompt: plan.prompt.clone(), + duration: plan.duration, + aspect_ratio: plan.aspect_ratio, + }; + + let outbound_request: Arc = Arc::new(request.clone()); + let args = Kling2p1ProArgs { - request: Kling2p1ProRequest { - image_url: plan.image_url.clone(), - end_frame_image_url: plan.end_image_url.clone(), - prompt: plan.prompt.clone(), - duration: plan.duration, - aspect_ratio: plan.aspect_ratio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; @@ -32,5 +39,6 @@ pub async fn execute_fal_kling_2_1_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs index c6c80912f1..2eb0033c21 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_5_turbo_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -22,33 +25,37 @@ pub async fn execute_fal_kling_2_5_turbo_pro( plan: &PlanFalKling2p5TurboPro, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalKling2p5TurboProMode::TextToVideo => { + let request = EnqueueKlingV2p5TurboProTextToVideoRequest { + prompt: plan.prompt.clone(), + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKlingV2p5TurboProTextToVideoArgs { - request: EnqueueKlingV2p5TurboProTextToVideoRequest { - prompt: plan.prompt.clone(), - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_v2p5_turbo_pro_text_to_video_webhook(args).await + (enqueue_kling_v2p5_turbo_pro_text_to_video_webhook(args).await, outbound) } FalKling2p5TurboProMode::ImageToVideo { image_url, end_image_url } => { + let request = EnqueueKlingV2p5TurboProImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + tail_image_url: end_image_url.clone(), + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_i2v_duration), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKlingV2p5TurboProImageToVideoArgs { - request: EnqueueKlingV2p5TurboProImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - tail_image_url: end_image_url.clone(), - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_i2v_duration), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_v2p5_turbo_pro_image_to_video_webhook(args).await + (enqueue_kling_v2p5_turbo_pro_image_to_video_webhook(args).await, outbound) } }; @@ -58,6 +65,7 @@ pub async fn execute_fal_kling_2_5_turbo_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs index 5f0e316764..46046ed76c 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_2_6_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -21,34 +24,38 @@ pub async fn execute_fal_kling_2_6_pro( plan: &PlanFalKling2p6Pro, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalKling2p6ProMode::TextToVideo => { + let request = EnqueueKlingV2p6ProTextToVideoRequest { + prompt: plan.prompt.clone(), + generate_audio: plan.generate_audio, + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKlingV2p6ProTextToVideoArgs { - request: EnqueueKlingV2p6ProTextToVideoRequest { - prompt: plan.prompt.clone(), - generate_audio: plan.generate_audio, - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_v2p6_pro_text_to_video_webhook(args).await + (enqueue_kling_v2p6_pro_text_to_video_webhook(args).await, outbound) } FalKling2p6ProMode::ImageToVideo { image_url } => { + let request = EnqueueKlingV2p6ProImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + generate_audio: plan.generate_audio, + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_i2v_duration), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKlingV2p6ProImageToVideoArgs { - request: EnqueueKlingV2p6ProImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - generate_audio: plan.generate_audio, - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_i2v_duration), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_v2p6_pro_image_to_video_webhook(args).await + (enqueue_kling_v2p6_pro_image_to_video_webhook(args).await, outbound) } }; @@ -58,6 +65,7 @@ pub async fn execute_fal_kling_2_6_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs index 292ce7179b..56c417c9ff 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -22,38 +25,42 @@ pub async fn execute_fal_kling_3p0_pro( plan: &PlanFalKling3p0Pro, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalKling3p0Mode::TextToVideo => { + let request = EnqueueKling3p0ProTextToVideoRequest { + prompt: plan.prompt.clone(), + generate_audio: plan.generate_audio, + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), + shot_type: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKling3p0ProTextToVideoArgs { - request: EnqueueKling3p0ProTextToVideoRequest { - prompt: plan.prompt.clone(), - generate_audio: plan.generate_audio, - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), - shot_type: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_3p0_pro_text_to_video_webhook(args).await + (enqueue_kling_3p0_pro_text_to_video_webhook(args).await, outbound) } FalKling3p0Mode::ImageToVideo { image_url, end_image_url } => { + let request = EnqueueKling3p0ProImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + end_image_url: end_image_url.clone(), + generate_audio: plan.generate_audio, + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_i2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), + shot_type: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKling3p0ProImageToVideoArgs { - request: EnqueueKling3p0ProImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - end_image_url: end_image_url.clone(), - generate_audio: plan.generate_audio, - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_i2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), - shot_type: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_3p0_pro_image_to_video_webhook(args).await + (enqueue_kling_3p0_pro_image_to_video_webhook(args).await, outbound) } }; @@ -63,6 +70,7 @@ pub async fn execute_fal_kling_3p0_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs index 7d83a81ead..14c47a0cec 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_kling_3p0_standard.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -23,38 +26,42 @@ pub async fn execute_fal_kling_3p0_standard( plan: &PlanFalKling3p0Standard, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalKling3p0Mode::TextToVideo => { + let request = EnqueueKling3p0StandardTextToVideoRequest { + prompt: plan.prompt.clone(), + generate_audio: plan.generate_audio, + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), + shot_type: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKling3p0StandardTextToVideoArgs { - request: EnqueueKling3p0StandardTextToVideoRequest { - prompt: plan.prompt.clone(), - generate_audio: plan.generate_audio, - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), - shot_type: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_3p0_standard_text_to_video_webhook(args).await + (enqueue_kling_3p0_standard_text_to_video_webhook(args).await, outbound) } FalKling3p0Mode::ImageToVideo { image_url, end_image_url } => { + let request = EnqueueKling3p0StandardImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + end_image_url: end_image_url.clone(), + generate_audio: plan.generate_audio, + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration.map(to_i2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), + shot_type: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueKling3p0StandardImageToVideoArgs { - request: EnqueueKling3p0StandardImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - end_image_url: end_image_url.clone(), - generate_audio: plan.generate_audio, - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration.map(to_i2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), - shot_type: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_kling_3p0_standard_image_to_video_webhook(args).await + (enqueue_kling_3p0_standard_image_to_video_webhook(args).await, outbound) } }; @@ -64,6 +71,7 @@ pub async fn execute_fal_kling_3p0_standard( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1_0_lite.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1_0_lite.rs index 6675c88db7..c8c9c5119b 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1_0_lite.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1_0_lite.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,17 +16,21 @@ pub async fn execute_fal_seedance_1_0_lite( plan: &PlanFalSeedance10Lite, fal_client: &RouterFalClient, ) -> Result { + let request = Seedance1LiteRequest { + image_url: plan.image_url.clone(), + end_frame_image_url: plan.end_image_url.clone(), + prompt: plan.prompt.clone(), + duration: plan.duration, + resolution: plan.resolution, + aspect_ratio: plan.aspect_ratio, + camera_fixed: false, + seed: None, + }; + + let outbound_request: Arc = Arc::new(request.clone()); + let args = Seedance1LiteArgs { - request: Seedance1LiteRequest { - image_url: plan.image_url.clone(), - end_frame_image_url: plan.end_image_url.clone(), - prompt: plan.prompt.clone(), - duration: plan.duration, - resolution: plan.resolution, - aspect_ratio: plan.aspect_ratio, - camera_fixed: false, - seed: None, - }, + request, api_key: &fal_client.api_key, webhook_url: fal_client.webhook_url.as_str(), }; @@ -35,5 +42,6 @@ pub async fn execute_fal_seedance_1_0_lite( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs index ce048e3932..4031db8be9 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_seedance_1p5_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -23,36 +26,40 @@ pub async fn execute_fal_seedance_1p5_pro( plan: &PlanFalSeedance1p5Pro, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalSeedance1p5ProMode::TextToVideo => { + let request = EnqueueSeedance1p5ProTextToVideoRequest { + prompt: plan.prompt.clone(), + resolution: plan.resolution.map(to_t2v_resolution), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), + generate_audio: plan.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueSeedance1p5ProTextToVideoArgs { - request: EnqueueSeedance1p5ProTextToVideoRequest { - prompt: plan.prompt.clone(), - resolution: plan.resolution.map(to_t2v_resolution), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), - generate_audio: plan.generate_audio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_seedance_1p5_pro_text_to_video_webhook(args).await + (enqueue_seedance_1p5_pro_text_to_video_webhook(args).await, outbound) } FalSeedance1p5ProMode::ImageToVideo { image_url, end_image_url } => { + let request = EnqueueSeedance1p5ProImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + end_image_url: end_image_url.clone(), + resolution: plan.resolution.map(to_i2v_resolution), + duration: plan.duration.map(to_i2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), + generate_audio: plan.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueSeedance1p5ProImageToVideoArgs { - request: EnqueueSeedance1p5ProImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - end_image_url: end_image_url.clone(), - resolution: plan.resolution.map(to_i2v_resolution), - duration: plan.duration.map(to_i2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), - generate_audio: plan.generate_audio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_seedance_1p5_pro_image_to_video_webhook(args).await + (enqueue_seedance_1p5_pro_image_to_video_webhook(args).await, outbound) } }; @@ -62,6 +69,7 @@ pub async fn execute_fal_seedance_1p5_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs index db159544c6..68b93a372c 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -22,34 +25,38 @@ pub async fn execute_fal_sora_2( plan: &PlanFalSora2, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalSora2Mode::TextToVideo => { // Text-to-video does not support Auto aspect ratio or Auto resolution. + let request = EnqueueSora2TextToVideoRequest { + prompt: plan.prompt.clone(), + resolution: plan.resolution.and_then(to_t2v_resolution), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueSora2TextToVideoArgs { - request: EnqueueSora2TextToVideoRequest { - prompt: plan.prompt.clone(), - resolution: plan.resolution.and_then(to_t2v_resolution), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_sora_2_text_to_video_webhook(args).await + (enqueue_sora_2_text_to_video_webhook(args).await, outbound) } FalSora2Mode::ImageToVideo { image_url } => { + let request = EnqueueSora2ImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + duration: plan.duration.map(to_i2v_duration), + resolution: plan.resolution.map(to_i2v_resolution), + aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueSora2ImageToVideoArgs { - request: EnqueueSora2ImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - duration: plan.duration.map(to_i2v_duration), - resolution: plan.resolution.map(to_i2v_resolution), - aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_sora_2_image_to_video_webhook(args).await + (enqueue_sora_2_image_to_video_webhook(args).await, outbound) } }; @@ -59,6 +66,7 @@ pub async fn execute_fal_sora_2( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs index 870fa44a57..5818cbe626 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_sora_2_pro.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -23,34 +26,38 @@ pub async fn execute_fal_sora_2_pro( plan: &PlanFalSora2Pro, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalSora2ProMode::TextToVideo => { // Text-to-video does not support Auto aspect ratio or Auto resolution. + let request = EnqueueSora2ProTextToVideoRequest { + prompt: plan.prompt.clone(), + resolution: plan.resolution.and_then(to_t2v_resolution), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueSora2ProTextToVideoArgs { - request: EnqueueSora2ProTextToVideoRequest { - prompt: plan.prompt.clone(), - resolution: plan.resolution.and_then(to_t2v_resolution), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.and_then(to_t2v_aspect_ratio), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_sora_2_pro_text_to_video_webhook(args).await + (enqueue_sora_2_pro_text_to_video_webhook(args).await, outbound) } FalSora2ProMode::ImageToVideo { image_url } => { + let request = EnqueueSora2ProImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: image_url.clone(), + duration: plan.duration.map(to_i2v_duration), + resolution: plan.resolution.map(to_i2v_resolution), + aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueSora2ProImageToVideoArgs { - request: EnqueueSora2ProImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: image_url.clone(), - duration: plan.duration.map(to_i2v_duration), - resolution: plan.resolution.map(to_i2v_resolution), - aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_sora_2_pro_image_to_video_webhook(args).await + (enqueue_sora_2_pro_image_to_video_webhook(args).await, outbound) } }; @@ -60,6 +67,7 @@ pub async fn execute_fal_sora_2_pro( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs index 3d3f54547d..20e4983ffc 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_2.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -18,42 +21,49 @@ pub async fn execute_fal_veo_2( plan: &PlanFalVeo2, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalVeo2Mode::TextToVideo => { + let request = Veo2TextToVideoRequest { + prompt: plan.prompt.clone(), + negative_prompt: plan.negative_prompt.clone(), + duration: plan.duration, + aspect_ratio: plan.aspect_ratio.unwrap_or(Veo2AspectRatio::Auto), + }; + let outbound: Arc = Arc::new(request.clone()); let args = Veo2TextToVideoArgs { - request: Veo2TextToVideoRequest { - prompt: plan.prompt.clone(), - negative_prompt: plan.negative_prompt.clone(), - duration: plan.duration, - aspect_ratio: plan.aspect_ratio.unwrap_or(Veo2AspectRatio::Auto), - }, + request, api_key: &fal_client.api_key, webhook_url: fal_client.webhook_url.as_str(), }; - enqueue_veo_2_text_to_video_webhook(args) + let resp = enqueue_veo_2_text_to_video_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } FalVeo2Mode::ImageToVideo { image_url } => { // Image-to-video does not support aspect_ratio — the output // inherits the source image's aspect ratio. + let request = Veo2Request { + image_url: image_url.to_string(), + prompt: plan.prompt.clone(), + duration: plan.duration, + }; + let outbound: Arc = Arc::new(request.clone()); let args = Veo2Args { - request: Veo2Request { - image_url: image_url.to_string(), - prompt: plan.prompt.clone(), - duration: plan.duration, - }, + request, api_key: &fal_client.api_key, webhook_url: fal_client.webhook_url.as_str(), }; - enqueue_veo_2_image_to_video_webhook(args) + let resp = enqueue_veo_2_image_to_video_webhook(args) .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) } }; Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs index 43dcc9a013..73043f2a14 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -17,6 +20,60 @@ use fal_client::requests::webhook::video::text::enqueue_veo_3_text_to_video_webh Veo3TextToVideoArgs, Veo3TextToVideoRequest, }; +pub async fn execute_fal_veo_3( + plan: &PlanFalVeo3, + fal_client: &RouterFalClient, +) -> Result { + let (webhook_response, outbound_request) = match &plan.mode { + FalVeo3Mode::TextToVideo => { + let request = Veo3TextToVideoRequest { + prompt: plan.prompt.clone(), + negative_prompt: plan.negative_prompt.clone(), + duration: to_t2v_duration(plan.duration), + aspect_ratio: plan.t2v_aspect_ratio.map(to_t2v_aspect_ratio).unwrap_or(Veo3T2vAspectRatio::Default), + resolution: to_t2v_resolution(plan.resolution), + generate_audio: plan.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); + let args = Veo3TextToVideoArgs { + request, + api_key: &fal_client.api_key, + webhook_url: fal_client.webhook_url.as_str(), + }; + let resp = enqueue_veo_3_text_to_video_webhook(args) + .await + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) + } + FalVeo3Mode::ImageToVideo { image_url } => { + let request = Veo3Request { + image_url: image_url.to_string(), + prompt: plan.prompt.clone(), + duration: to_i2v_duration(plan.duration), + aspect_ratio: plan.i2v_aspect_ratio.map(to_i2v_aspect_ratio).unwrap_or(Veo3I2vAspectRatio::Auto), + resolution: to_i2v_resolution(plan.resolution), + generate_audio: plan.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); + let args = Veo3Args { + request, + api_key: &fal_client.api_key, + webhook_url: fal_client.webhook_url.as_str(), + }; + let resp = enqueue_veo_3_image_to_video_webhook(args) + .await + .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))?; + (resp, outbound) + } + }; + + Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { + request_id: webhook_response.request_id, + gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), + })) +} + fn to_i2v_duration(d: FalVeo3Duration) -> Veo3I2vDuration { match d { FalVeo3Duration::Default => Veo3I2vDuration::Default, @@ -66,50 +123,3 @@ fn to_i2v_aspect_ratio(ar: FalVeo3I2vAspectRatio) -> Veo3I2vAspectRatio { FalVeo3I2vAspectRatio::TallNineSixteen => Veo3I2vAspectRatio::TallNineSixteen, } } - -pub async fn execute_fal_veo_3( - plan: &PlanFalVeo3, - fal_client: &RouterFalClient, -) -> Result { - let webhook_response = match &plan.mode { - FalVeo3Mode::TextToVideo => { - let args = Veo3TextToVideoArgs { - request: Veo3TextToVideoRequest { - prompt: plan.prompt.clone(), - negative_prompt: plan.negative_prompt.clone(), - duration: to_t2v_duration(plan.duration), - aspect_ratio: plan.t2v_aspect_ratio.map(to_t2v_aspect_ratio).unwrap_or(Veo3T2vAspectRatio::Default), - resolution: to_t2v_resolution(plan.resolution), - generate_audio: plan.generate_audio, - }, - api_key: &fal_client.api_key, - webhook_url: fal_client.webhook_url.as_str(), - }; - enqueue_veo_3_text_to_video_webhook(args) - .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? - } - FalVeo3Mode::ImageToVideo { image_url } => { - let args = Veo3Args { - request: Veo3Request { - image_url: image_url.to_string(), - prompt: plan.prompt.clone(), - duration: to_i2v_duration(plan.duration), - aspect_ratio: plan.i2v_aspect_ratio.map(to_i2v_aspect_ratio).unwrap_or(Veo3I2vAspectRatio::Auto), - resolution: to_i2v_resolution(plan.resolution), - generate_audio: plan.generate_audio, - }, - api_key: &fal_client.api_key, - webhook_url: fal_client.webhook_url.as_str(), - }; - enqueue_veo_3_image_to_video_webhook(args) - .await - .map_err(|e| ArtcraftRouterError::Provider(ProviderError::Fal(e)))? - } - }; - - Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { - request_id: webhook_response.request_id, - gateway_request_id: webhook_response.gateway_request_id, - })) -} diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3_fast.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3_fast.rs index 358017d2ba..35b6b65ffd 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3_fast.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3_fast.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -13,15 +16,19 @@ pub async fn execute_fal_veo_3_fast( plan: &PlanFalVeo3Fast, fal_client: &RouterFalClient, ) -> Result { + let request = Veo3FastRequest { + prompt: plan.prompt.clone(), + image_url: plan.start_frame_url.clone(), + aspect_ratio: plan.aspect_ratio, + duration: plan.duration, + resolution: plan.resolution, + generate_audio: plan.generate_audio, + }; + + let outbound_request: Arc = Arc::new(request.clone()); + let args = Veo3FastArgs { - request: Veo3FastRequest { - prompt: plan.prompt.clone(), - image_url: plan.start_frame_url.clone(), - aspect_ratio: plan.aspect_ratio, - duration: plan.duration, - resolution: plan.resolution, - generate_audio: plan.generate_audio, - }, + request, api_key: &fal_client.api_key, webhook_url: fal_client.webhook_url.as_str(), }; @@ -33,5 +40,6 @@ pub async fn execute_fal_veo_3_fast( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs index c28aa09a21..00f1cfb6ff 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -30,55 +33,61 @@ pub async fn execute_fal_veo_3p1( plan: &PlanFalVeo3p1, fal_client: &RouterFalClient, ) -> Result { - let webhook_response = match &plan.mode { + let (webhook_response, outbound_request) = match &plan.mode { FalVeo3p1Mode::TextToVideo => { + let request = EnqueueVeo3p1TextToVideoRequest { + prompt: plan.prompt.clone(), + duration: plan.duration.map(to_t2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), + resolution: plan.resolution.map(to_t2v_resolution), + generate_audio: plan.generate_audio, + enhance_prompt: None, + negative_prompt: plan.negative_prompt.clone(), + seed: None, + auto_fix: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueVeo3p1TextToVideoArgs { - request: EnqueueVeo3p1TextToVideoRequest { - prompt: plan.prompt.clone(), - duration: plan.duration.map(to_t2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_t2v_aspect_ratio), - resolution: plan.resolution.map(to_t2v_resolution), - generate_audio: plan.generate_audio, - enhance_prompt: None, - negative_prompt: plan.negative_prompt.clone(), - seed: None, - auto_fix: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_veo_3p1_text_to_video_webhook(args).await + (enqueue_veo_3p1_text_to_video_webhook(args).await, outbound) } FalVeo3p1Mode::ImageToVideo { start_frame_url } => { + let request = EnqueueVeo3p1ImageToVideoRequest { + prompt: plan.prompt.clone(), + image_url: start_frame_url.clone(), + duration: plan.duration.map(to_i2v_duration), + aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), + resolution: plan.resolution.map(to_i2v_resolution), + generate_audio: plan.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueVeo3p1ImageToVideoArgs { - request: EnqueueVeo3p1ImageToVideoRequest { - prompt: plan.prompt.clone(), - image_url: start_frame_url.clone(), - duration: plan.duration.map(to_i2v_duration), - aspect_ratio: plan.aspect_ratio.map(to_i2v_aspect_ratio), - resolution: plan.resolution.map(to_i2v_resolution), - generate_audio: plan.generate_audio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_veo_3p1_image_to_video_webhook(args).await + (enqueue_veo_3p1_image_to_video_webhook(args).await, outbound) } FalVeo3p1Mode::FirstLastFrame { first_frame_url, last_frame_url } => { + let request = EnqueueVeo3p1FirstLastFrameImageToVideoRequest { + prompt: plan.prompt.clone(), + first_frame_url: first_frame_url.clone(), + last_frame_url: last_frame_url.clone(), + duration: plan.duration.map(to_flf_duration), + aspect_ratio: plan.aspect_ratio.map(to_flf_aspect_ratio), + resolution: plan.resolution.map(to_flf_resolution), + generate_audio: plan.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueVeo3p1FirstLastFrameImageToVideoArgs { - request: EnqueueVeo3p1FirstLastFrameImageToVideoRequest { - prompt: plan.prompt.clone(), - first_frame_url: first_frame_url.clone(), - last_frame_url: last_frame_url.clone(), - duration: plan.duration.map(to_flf_duration), - aspect_ratio: plan.aspect_ratio.map(to_flf_aspect_ratio), - resolution: plan.resolution.map(to_flf_resolution), - generate_audio: plan.generate_audio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_veo_3p1_first_last_frame_image_to_video_webhook(args).await + (enqueue_veo_3p1_first_last_frame_image_to_video_webhook(args).await, outbound) } }; @@ -88,6 +97,7 @@ pub async fn execute_fal_veo_3p1( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs index ad07079bcb..0a0ee21520 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/fal/generate_video_fal_veo_3p1_fast.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use crate::client::router_fal_client::RouterFalClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; @@ -33,55 +36,61 @@ pub async fn execute_fal_veo_3p1_fast( ) -> Result { let inner = &plan.inner; - let webhook_response = match &inner.mode { + let (webhook_response, outbound_request) = match &inner.mode { FalVeo3p1Mode::TextToVideo => { + let request = EnqueueVeo3p1FastTextToVideoRequest { + prompt: inner.prompt.clone(), + duration: inner.duration.map(to_t2v_duration), + aspect_ratio: inner.aspect_ratio.map(to_t2v_aspect_ratio), + resolution: inner.resolution.map(to_t2v_resolution), + generate_audio: inner.generate_audio, + enhance_prompt: None, + negative_prompt: inner.negative_prompt.clone(), + seed: None, + auto_fix: None, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueVeo3p1FastTextToVideoArgs { - request: EnqueueVeo3p1FastTextToVideoRequest { - prompt: inner.prompt.clone(), - duration: inner.duration.map(to_t2v_duration), - aspect_ratio: inner.aspect_ratio.map(to_t2v_aspect_ratio), - resolution: inner.resolution.map(to_t2v_resolution), - generate_audio: inner.generate_audio, - enhance_prompt: None, - negative_prompt: inner.negative_prompt.clone(), - seed: None, - auto_fix: None, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_veo_3p1_fast_text_to_video_webhook(args).await + (enqueue_veo_3p1_fast_text_to_video_webhook(args).await, outbound) } FalVeo3p1Mode::ImageToVideo { start_frame_url } => { + let request = EnqueueVeo3p1FastImageToVideoRequest { + prompt: inner.prompt.clone(), + image_url: start_frame_url.clone(), + duration: inner.duration.map(to_i2v_duration), + aspect_ratio: inner.aspect_ratio.map(to_i2v_aspect_ratio), + resolution: inner.resolution.map(to_i2v_resolution), + generate_audio: inner.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueVeo3p1FastImageToVideoArgs { - request: EnqueueVeo3p1FastImageToVideoRequest { - prompt: inner.prompt.clone(), - image_url: start_frame_url.clone(), - duration: inner.duration.map(to_i2v_duration), - aspect_ratio: inner.aspect_ratio.map(to_i2v_aspect_ratio), - resolution: inner.resolution.map(to_i2v_resolution), - generate_audio: inner.generate_audio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_veo_3p1_fast_image_to_video_webhook(args).await + (enqueue_veo_3p1_fast_image_to_video_webhook(args).await, outbound) } FalVeo3p1Mode::FirstLastFrame { first_frame_url, last_frame_url } => { + let request = EnqueueVeo3p1FastFirstLastFrameImageToVideoRequest { + prompt: inner.prompt.clone(), + first_frame_url: first_frame_url.clone(), + last_frame_url: last_frame_url.clone(), + duration: inner.duration.map(to_flf_duration), + aspect_ratio: inner.aspect_ratio.map(to_flf_aspect_ratio), + resolution: inner.resolution.map(to_flf_resolution), + generate_audio: inner.generate_audio, + }; + let outbound: Arc = Arc::new(request.clone()); let args = EnqueueVeo3p1FastFirstLastFrameImageToVideoArgs { - request: EnqueueVeo3p1FastFirstLastFrameImageToVideoRequest { - prompt: inner.prompt.clone(), - first_frame_url: first_frame_url.clone(), - last_frame_url: last_frame_url.clone(), - duration: inner.duration.map(to_flf_duration), - aspect_ratio: inner.aspect_ratio.map(to_flf_aspect_ratio), - resolution: inner.resolution.map(to_flf_resolution), - generate_audio: inner.generate_audio, - }, + request, webhook_url: fal_client.webhook_url.as_str(), api_key: &fal_client.api_key, }; - enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook(args).await + (enqueue_veo_3p1_fast_first_last_frame_image_to_video_webhook(args).await, outbound) } }; @@ -91,6 +100,7 @@ pub async fn execute_fal_veo_3p1_fast( Ok(GenerateVideoResponse::Fal(FalVideoResponsePayload { request_id: webhook_response.request_id, gateway_request_id: webhook_response.gateway_request_id, + maybe_outbound_request: Some(outbound_request), })) } diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_response.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_response.rs index d9e8ba911b..f8c9839841 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_response.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_response.rs @@ -1,3 +1,6 @@ +use std::fmt::Debug; +use std::sync::Arc; + use muapi_client::api_types::request_id::RequestId as MuapiRequestId; use tokens::tokens::generic_inference_jobs::InferenceJobToken; @@ -24,6 +27,11 @@ pub struct Seedance2proVideoResponsePayload { pub struct FalVideoResponsePayload { pub request_id: Option, pub gateway_request_id: Option, + + /// The outbound request that was sent to Fal. + /// Stored as a trait object so any Request type can be captured. + /// Use `format!("{:?}", ...)` or `format!("{:#?}", ...)` to print. + pub maybe_outbound_request: Option>, } #[derive(Clone, Debug)] 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 index 032566e360..513d546958 100644 --- 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 @@ -188,6 +188,23 @@ pub async fn omni_gen_image_generate_handler( AdvancedCommonWebError::from_error(e) })?; + // ==================== DEBUG LOG: FAL REQUEST ==================== // + + if let GenerateImageResponse::Fal(ref fal_payload) = generation_response { + if let Some(ref outbound_request) = fal_payload.maybe_outbound_request { + if let Err(err) = insert_debug_log(InsertDebugLogArgs { + apriori_debug_log_event_token: Some(&debug_log_event_token), + maybe_creator_user_token: Some(user_token), + debug_log_type: DebugLogType::FalRequest, + message: &format!("{:#?}", outbound_request), + mysql_executor: &mut *mysql_connection, + phantom: Default::default(), + }).await { + warn!("Failed to insert Fal request debug log: {:?}", err); + } + } + } + let external_job_id = match &generation_response { GenerateImageResponse::Artcraft(p) => { p.inference_job_token.as_str().to_string() diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs index 8d5053a030..fc7bc42780 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/omni_gen/generate/video/omni_gen_video_generate_handler.rs @@ -225,6 +225,23 @@ pub async fn omni_gen_video_generate_handler( warn!("Failed to insert HTTP request debug log: {:?}", err); } + // ==================== DEBUG LOG: FAL REQUEST ==================== // + + if let GenerateVideoResponse::Fal(ref fal_payload) = pipeline_result.response { + if let Some(ref outbound_request) = fal_payload.maybe_outbound_request { + if let Err(err) = insert_debug_log(InsertDebugLogArgs { + apriori_debug_log_event_token: Some(&debug_log_event_token), + maybe_creator_user_token: Some(user_token), + debug_log_type: DebugLogType::FalRequest, + message: &format!("{:#?}", outbound_request), + mysql_executor: &mut *mysql_connection, + phantom: Default::default(), + }).await { + warn!("Failed to insert Fal request debug log: {:?}", err); + } + } + } + // ==================== WRITE RESULT ==================== // let ip_address = get_request_ip(&http_request);