From 702bdc87777ad86f71d761853ee7a0803c3a2f5a Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 3 Apr 2026 03:37:04 -0400 Subject: [PATCH] tauri characters via artcraft_router (#1293) --- .../artcraft_router/src/api/character_list_ref.rs | 9 +++++++++ .../artcraft/artcraft_router/src/api/mod.rs | 1 + .../estimate_video_cost_artcraft_kling3p0_pro.rs | 1 + ...estimate_video_cost_artcraft_kling3p0_standard.rs | 1 + .../estimate_video_cost_artcraft_seedance1p5_pro.rs | 1 + .../estimate_video_cost_artcraft_seedance2p0.rs | 1 + .../artcraft/generate_video_artcraft_seedance2p0.rs | 2 +- .../generate_video/generate_video_request.rs | 5 +++++ .../plan_generate_video_artcraft_kling3p0_pro.rs | 1 + ...plan_generate_video_artcraft_kling3p0_standard.rs | 1 + .../plan_generate_video_artcraft_seedance1p5_pro.rs | 1 + .../plan_generate_video_artcraft_seedance2p0.rs | 12 ++++++++++++ .../artcraft/artcraft_router/src/test_helpers.rs | 1 + .../artcraft/handle_artcraft_seedance_2p0.rs | 8 +++++--- .../artcraft/handle_artcraft_video_via_router.rs | 2 ++ .../image_to_video/enqueue_image_to_video_command.rs | 5 +++++ .../video/estimate_video_cost_handler.rs | 1 + 17 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 crates/api_clients/artcraft/artcraft_router/src/api/character_list_ref.rs diff --git a/crates/api_clients/artcraft/artcraft_router/src/api/character_list_ref.rs b/crates/api_clients/artcraft/artcraft_router/src/api/character_list_ref.rs new file mode 100644 index 0000000000..b986f30941 --- /dev/null +++ b/crates/api_clients/artcraft/artcraft_router/src/api/character_list_ref.rs @@ -0,0 +1,9 @@ +use tokens::tokens::characters::CharacterToken; + +/// Forward-compatible character reference list. +#[derive(Copy, Clone)] +pub enum CharacterListRef<'a> { + CharacterTokens(&'a Vec), + + // In the future, we may have other identifiers for characters. +} diff --git a/crates/api_clients/artcraft/artcraft_router/src/api/mod.rs b/crates/api_clients/artcraft/artcraft_router/src/api/mod.rs index 458ca33b3f..c3d3386130 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/api/mod.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/api/mod.rs @@ -1,4 +1,5 @@ pub mod audio_list_ref; +pub mod character_list_ref; pub mod common_aspect_ratio; pub mod common_image_model; pub mod common_resolution; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs index 99dbf3e9ce..3fbc8c902d 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_pro.rs @@ -71,6 +71,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: Some(duration_seconds), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs index cac7c7deb5..af970efd7b 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_kling3p0_standard.rs @@ -71,6 +71,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: Some(duration_seconds), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs index a4cb68c8f5..fea12432b4 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance1p5_pro.rs @@ -74,6 +74,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: Some(duration_seconds), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance2p0.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance2p0.rs index 4a539ee772..bb6f64d2c8 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance2p0.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/cost/artcraft/estimate_video_cost_artcraft_seedance2p0.rs @@ -69,6 +69,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: Some(duration_seconds), diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/artcraft/generate_video_artcraft_seedance2p0.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/artcraft/generate_video_artcraft_seedance2p0.rs index 849d828251..06d406f5f1 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/artcraft/generate_video_artcraft_seedance2p0.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/execute/artcraft/generate_video_artcraft_seedance2p0.rs @@ -20,10 +20,10 @@ pub async fn execute_artcraft_seedance2p0( reference_image_media_tokens: plan.reference_images.map(|tokens| tokens.to_owned()), reference_video_media_tokens: plan.reference_videos.map(|tokens| tokens.to_owned()), reference_audio_media_tokens: plan.reference_audio.map(|tokens| tokens.to_owned()), + reference_character_tokens: plan.reference_characters.map(|tokens| tokens.to_owned()), aspect_ratio: plan.aspect_ratio, duration_seconds: plan.duration_seconds, batch_count: Some(plan.batch_count), - reference_character_tokens: None, }; let response = seedance_2p0_multi_function_video_gen( diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request.rs index 1cfcce94aa..27688d4a32 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/generate_video_request.rs @@ -1,7 +1,9 @@ +use tokens::tokens::characters::CharacterToken; use crate::api::common_aspect_ratio::CommonAspectRatio; use crate::api::common_resolution::CommonResolution; use crate::api::common_video_model::CommonVideoModel; use crate::api::audio_list_ref::AudioListRef; +use crate::api::character_list_ref::CharacterListRef; use crate::api::image_list_ref::ImageListRef; use crate::api::image_ref::ImageRef; use crate::api::provider::Provider; @@ -47,6 +49,9 @@ pub struct GenerateVideoRequest<'a> { /// Reference audio (optional). pub reference_audio: Option>, + /// Reference characters (optional). + pub reference_character_tokens: Option>, + /// The resolution to use pub resolution: Option, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_pro.rs index 80260ac532..51a32b8337 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_pro.rs @@ -180,6 +180,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: None, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_standard.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_standard.rs index 2371322715..677b36af46 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_standard.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_kling3p0_standard.rs @@ -180,6 +180,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: None, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance1p5_pro.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance1p5_pro.rs index 648e790b7c..64dcefdccf 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance1p5_pro.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance1p5_pro.rs @@ -197,6 +197,7 @@ mod tests { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: None, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance2p0.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance2p0.rs index 8c21de366e..47ea91c454 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance2p0.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video/plan/artcraft/plan_generate_video_artcraft_seedance2p0.rs @@ -11,6 +11,7 @@ use crate::generate::generate_video::video_generation_plan::VideoGenerationPlan; use artcraft_api_defs::generate::video::multi_function::seedance_2p0_multi_function_video_gen::{ Seedance2p0AspectRatio, Seedance2p0BatchCount, }; +use tokens::tokens::characters::CharacterToken; use tokens::tokens::media_files::MediaFileToken; #[derive(Debug, Clone)] @@ -21,6 +22,7 @@ pub struct PlanArtcraftSeedance2p0<'a> { pub reference_images: Option<&'a Vec>, pub reference_videos: Option<&'a Vec>, pub reference_audio: Option<&'a Vec>, + pub reference_characters: Option<&'a Vec>, pub aspect_ratio: Option, pub duration_seconds: Option, pub batch_count: Seedance2p0BatchCount, @@ -49,6 +51,7 @@ pub fn plan_generate_video_artcraft_seedance2p0<'a>( reference_images, reference_videos, reference_audio, + reference_characters: resolve_character_list_ref(request.reference_character_tokens), aspect_ratio, duration_seconds, batch_count, @@ -56,6 +59,15 @@ pub fn plan_generate_video_artcraft_seedance2p0<'a>( })) } +fn resolve_character_list_ref<'a>( + character_list_ref: Option>, +) -> Option<&'a Vec> { + match character_list_ref { + None => None, + Some(crate::api::character_list_ref::CharacterListRef::CharacterTokens(tokens)) => Some(tokens), + } +} + fn resolve_image_ref<'a>( image_ref: Option>, ) -> Result, ArtcraftRouterError> { diff --git a/crates/api_clients/artcraft/artcraft_router/src/test_helpers.rs b/crates/api_clients/artcraft/artcraft_router/src/test_helpers.rs index 5d9443a971..275840441c 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/test_helpers.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/test_helpers.rs @@ -292,6 +292,7 @@ pub fn base_video_request() -> GenerateVideoRequest<'static> { reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: None, aspect_ratio: None, duration_seconds: None, diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_seedance_2p0.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_seedance_2p0.rs index dd010ca090..a4661619f6 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_seedance_2p0.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_seedance_2p0.rs @@ -3,12 +3,14 @@ use crate::core::commands::enqueue::image_to_video::enqueue_image_to_video_comma use crate::core::commands::enqueue::task_enqueue_success::TaskEnqueueSuccess; use crate::core::events::generation_events::common::GenerationModel; use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; -use artcraft_router::api::common_video_model::CommonVideoModel; +use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet; use artcraft_router::api::audio_list_ref::AudioListRef; +use artcraft_router::api::character_list_ref::CharacterListRef; +use artcraft_router::api::common_video_model::CommonVideoModel; use artcraft_router::api::image_list_ref::ImageListRef; use artcraft_router::api::image_ref::ImageRef; -use artcraft_router::api::video_list_ref::VideoListRef; use artcraft_router::api::provider::Provider; +use artcraft_router::api::video_list_ref::VideoListRef; use artcraft_router::client::request_mismatch_mitigation_strategy::RequestMismatchMitigationStrategy; use artcraft_router::client::router_artcraft_client::RouterArtcraftClient; use artcraft_router::client::router_client::RouterClient; @@ -16,7 +18,6 @@ use artcraft_router::generate::generate_video::generate_video_request::GenerateV use enums::common::generation_provider::GenerationProvider; use enums::tauri::tasks::task_type::TaskType; use log::{error, info}; -use artcraft_client::credentials::storyteller_credential_set::StorytellerCredentialSet; pub(super) async fn handle_artcraft_seedance_2p0( request: &EnqueueImageToVideoRequest, @@ -42,6 +43,7 @@ pub(super) async fn handle_artcraft_seedance_2p0( reference_images, reference_videos: request.reference_video_media_tokens.as_ref().map(VideoListRef::MediaFileTokens), reference_audio: request.reference_audio_media_tokens.as_ref().map(AudioListRef::MediaFileTokens), + reference_character_tokens: request.reference_character_tokens.as_ref().map(CharacterListRef::CharacterTokens), resolution: None, aspect_ratio: request.aspect_ratio, duration_seconds: request.duration_seconds, diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_video_via_router.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_video_via_router.rs index 0113d1e618..d8fbc5af2d 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_video_via_router.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/artcraft/handle_artcraft_video_via_router.rs @@ -3,6 +3,7 @@ use crate::core::commands::enqueue::image_to_video::enqueue_image_to_video_comma use crate::core::commands::enqueue::task_enqueue_success::TaskEnqueueSuccess; use crate::core::events::generation_events::common::GenerationModel; use crate::core::state::app_env_configs::app_env_configs::AppEnvConfigs; +use artcraft_router::api::character_list_ref::CharacterListRef; use artcraft_router::api::common_video_model::CommonVideoModel; use artcraft_router::api::image_ref::ImageRef; use artcraft_router::api::provider::Provider; @@ -40,6 +41,7 @@ pub(super) async fn handle_artcraft_video_via_router( reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: request.reference_character_tokens.as_ref().map(CharacterListRef::CharacterTokens), resolution: None, aspect_ratio: request.aspect_ratio, duration_seconds: request.duration_seconds, diff --git a/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/enqueue_image_to_video_command.rs b/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/enqueue_image_to_video_command.rs index c2a6b22516..afd3dbe19b 100644 --- a/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/enqueue_image_to_video_command.rs +++ b/crates/desktop/artcraft/src/core/commands/enqueue/image_to_video/enqueue_image_to_video_command.rs @@ -29,6 +29,7 @@ use enums::tauri::ux::tauri_command_caller::TauriCommandCaller; use log::{error, info, warn}; use serde_derive::{Deserialize, Serialize}; use tauri::{AppHandle, State}; +use tokens::tokens::characters::CharacterToken; use tokens::tokens::media_files::MediaFileToken; /// This is used in the Tauri command bridge. @@ -123,6 +124,10 @@ pub struct EnqueueImageToVideoRequest { /// Reference audio for the video generation (e.g. voices, lip sync, music, etc.) pub reference_audio_media_tokens: Option>, + /// Optional character tokens to reference in the prompt. + /// Characters are referenced in prompts as @CharacterName. + pub reference_character_tokens: Option>, + /// Optional. /// Text prompt used to direct the video. pub prompt: Option, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/cost_estimate/video/estimate_video_cost_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/cost_estimate/video/estimate_video_cost_handler.rs index 1aafbfdd70..4dce7e82b2 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/generate/cost_estimate/video/estimate_video_cost_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/generate/cost_estimate/video/estimate_video_cost_handler.rs @@ -48,6 +48,7 @@ pub async fn estimate_video_cost_handler( reference_images: None, reference_videos: None, reference_audio: None, + reference_character_tokens: None, resolution: router_resolution, aspect_ratio: router_aspect_ratio, duration_seconds: request.duration_seconds,