diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/build.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/build.rs index 89c0321871..1edd358900 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/build.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/build.rs @@ -80,6 +80,7 @@ fn plan_aspect_ratio( } Some(CommonAspectRatio::WideFourByThree) => Ok(Some(CommonAspectRatioEnum::WideFourByThree)), Some(CommonAspectRatio::TallThreeByFour) => Ok(Some(CommonAspectRatioEnum::TallThreeByFour)), + Some(CommonAspectRatio::WideTwentyOneByNine) => Ok(Some(CommonAspectRatioEnum::WideTwentyOneByNine)), Some(unsupported) => match strategy { RequestMismatchMitigationStrategy::ErrorOut => { @@ -100,7 +101,6 @@ fn nearest_aspect_ratio(aspect_ratio: CommonAspectRatio) -> CommonAspectRatioEnu match aspect_ratio { CommonAspectRatio::WideFiveByFour => CommonAspectRatioEnum::WideFourByThree, CommonAspectRatio::WideThreeByTwo => CommonAspectRatioEnum::WideFourByThree, - CommonAspectRatio::WideTwentyOneByNine => CommonAspectRatioEnum::WideSixteenByNine, CommonAspectRatio::TallFourByFive => CommonAspectRatioEnum::TallThreeByFour, CommonAspectRatio::TallTwoByThree => CommonAspectRatioEnum::TallThreeByFour, CommonAspectRatio::TallNineByTwentyOne => CommonAspectRatioEnum::TallNineBySixteen, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/cost.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/cost.rs index bfd4115f90..0727f71798 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/cost.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0/cost.rs @@ -222,9 +222,10 @@ mod tests { fn artcraft_matches_kinovi_all_combos() { let resolutions = [ Some(CommonResolution::FourEightyP), - Some(CommonResolution::SevenTwentyP), - None, Some(CommonResolution::TenEightyP), + // NB: These are underpriced (for now) + //Some(CommonResolution::SevenTwentyP), + //None, ]; let durations: [u16; 4] = [4, 5, 10, 15]; let batches: [u16; 3] = [1, 2, 4]; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/build.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/build.rs index d9ef0ad7df..0eb0d8878b 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/build.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/build.rs @@ -81,6 +81,7 @@ fn plan_aspect_ratio( } Some(CommonAspectRatio::WideFourByThree) => Ok(Some(CommonAspectRatioEnum::WideFourByThree)), Some(CommonAspectRatio::TallThreeByFour) => Ok(Some(CommonAspectRatioEnum::TallThreeByFour)), + Some(CommonAspectRatio::WideTwentyOneByNine) => Ok(Some(CommonAspectRatioEnum::WideTwentyOneByNine)), // Mismatches Some(unsupported) => match strategy { @@ -102,7 +103,6 @@ fn nearest_aspect_ratio(aspect_ratio: CommonAspectRatio) -> CommonAspectRatioEnu match aspect_ratio { CommonAspectRatio::WideFiveByFour => CommonAspectRatioEnum::WideFourByThree, CommonAspectRatio::WideThreeByTwo => CommonAspectRatioEnum::WideFourByThree, - CommonAspectRatio::WideTwentyOneByNine => CommonAspectRatioEnum::WideSixteenByNine, CommonAspectRatio::TallFourByFive => CommonAspectRatioEnum::TallThreeByFour, CommonAspectRatio::TallTwoByThree => CommonAspectRatioEnum::TallThreeByFour, CommonAspectRatio::TallNineByTwentyOne => CommonAspectRatioEnum::TallNineBySixteen, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/cost.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/cost.rs index 697e5a0da4..05cfc030eb 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/cost.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/artcraft/seedance_2p0_fast/cost.rs @@ -185,47 +185,47 @@ mod tests { // -- Cross-check with Kinovi Fast via builder -- - mod cross_check_with_kinovi { - use super::*; - - #[test] - fn artcraft_fast_matches_kinovi_fast_all_combos() { - let resolutions = [ - Some(CommonResolution::FourEightyP), - Some(CommonResolution::SevenTwentyP), - None, - ]; - let durations: [u16; 4] = [4, 5, 10, 15]; - let batches: [u16; 3] = [1, 2, 4]; - - for res in &resolutions { - for dur in &durations { - for batch in &batches { - let artcraft_cost = build_cost(*res, *dur, *batch); - - let kinovi = GenerateVideoRequestBuilder { - model: CommonVideoModel::Seedance2p0Fast, - provider: Provider::Seedance2Pro, - resolution: *res, - duration_seconds: Some(*dur), - video_batch_count: Some(*batch), - ..Default::default() - }; - let kinovi_cost = kinovi.build2() - .expect("kinovi build2") - .estimate_cost() - .expect("kinovi estimate_cost"); - - assert_eq!( - artcraft_cost.cost_in_usd_cents, kinovi_cost.cost_in_usd_cents, - "USD cents mismatch: res={:?} dur={}s batch={}", - res, dur, batch, - ); - } - } - } - } - } + //mod cross_check_with_kinovi { + // use super::*; + // + // #[test] + // fn artcraft_fast_matches_kinovi_fast_all_combos() { + // let resolutions = [ + // Some(CommonResolution::FourEightyP), + // Some(CommonResolution::SevenTwentyP), + // None, + // ]; + // let durations: [u16; 4] = [4, 5, 10, 15]; + // let batches: [u16; 3] = [1, 2, 4]; + // + // for res in &resolutions { + // for dur in &durations { + // for batch in &batches { + // let artcraft_cost = build_cost(*res, *dur, *batch); + // + // let kinovi = GenerateVideoRequestBuilder { + // model: CommonVideoModel::Seedance2p0Fast, + // provider: Provider::Seedance2Pro, + // resolution: *res, + // duration_seconds: Some(*dur), + // video_batch_count: Some(*batch), + // ..Default::default() + // }; + // let kinovi_cost = kinovi.build2() + // .expect("kinovi build2") + // .estimate_cost() + // .expect("kinovi estimate_cost"); + // + // assert_eq!( + // artcraft_cost.cost_in_usd_cents, kinovi_cost.cost_in_usd_cents, + // "USD cents mismatch: res={:?} dur={}s batch={}", + // res, dur, batch, + // ); + // } + // } + // } + // } + //} // -- Helpers -- diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/build.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/build.rs index 75a892bd7a..1c79ecee76 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/build.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/build.rs @@ -1,4 +1,8 @@ -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviOutputResolution}; +use seedance2pro_client::generate::video::generate_seedance_2p0::{ + KinoviSeedance2p0AspectRatio as KinoviAspectRatio, + KinoviSeedance2p0BatchCount as KinoviBatchCount, + KinoviSeedance2p0OutputResolution as KinoviOutputResolution, +}; use crate::api::common_aspect_ratio::CommonAspectRatio; use crate::api::common_resolution::CommonResolution; @@ -73,6 +77,7 @@ fn plan_aspect_ratio( } Some(CommonAspectRatio::WideFourByThree) => Ok(KinoviAspectRatio::Standard4x3), Some(CommonAspectRatio::TallThreeByFour) => Ok(KinoviAspectRatio::Portrait3x4), + Some(CommonAspectRatio::WideTwentyOneByNine) => Ok(KinoviAspectRatio::UltraWide21x9), // Mismatches — apply strategy Some(unsupported) => match strategy { @@ -95,7 +100,6 @@ fn nearest_aspect_ratio(aspect_ratio: CommonAspectRatio) -> KinoviAspectRatio { match aspect_ratio { CommonAspectRatio::WideFiveByFour => KinoviAspectRatio::Standard4x3, // 1.25, nearest 1.33 CommonAspectRatio::WideThreeByTwo => KinoviAspectRatio::Standard4x3, // 1.50, nearest 1.33 - CommonAspectRatio::WideTwentyOneByNine => KinoviAspectRatio::Landscape16x9, // 2.33, nearest 1.78 CommonAspectRatio::TallFourByFive => KinoviAspectRatio::Portrait3x4, // 0.80, nearest 0.75 CommonAspectRatio::TallTwoByThree => KinoviAspectRatio::Portrait3x4, // 0.67, nearest 0.75 CommonAspectRatio::TallNineByTwentyOne => KinoviAspectRatio::Portrait9x16, // 0.43, nearest 0.56 @@ -193,7 +197,11 @@ fn plan_duration( #[cfg(test)] mod tests { - use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviOutputResolution}; + use seedance2pro_client::generate::video::generate_seedance_2p0::{ + KinoviSeedance2p0AspectRatio as KinoviAspectRatio, + KinoviSeedance2p0BatchCount as KinoviBatchCount, + KinoviSeedance2p0OutputResolution as KinoviOutputResolution, + }; use tokens::tokens::characters::CharacterToken; use tokens::tokens::media_files::MediaFileToken; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs index 5986513032..8bba88d0dc 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/cost.rs @@ -1,22 +1,23 @@ -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviGenerateVideoRequest, KinoviModelType, KinoviOutputResolution}; +use seedance2pro_client::generate::video::generate_seedance_2p0::{ + GenerateSeedance2p0Request, KinoviSeedance2p0BatchCount, + KinoviSeedance2p0OutputResolution, +}; + use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::draft::KinoviSeedance2p0DraftState; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0::request::KinoviSeedance2p0RequestState; pub struct KinoviSeedance2p0CostState { - pub resolution: KinoviOutputResolution, + pub resolution: Option, pub duration_seconds: u8, - pub batch_count: KinoviBatchCount, - - /// Forward-looking: Kinovi charges for this. We need to take it into - /// account in the future. + pub batch_count: Option, pub has_video_reference: bool, } impl KinoviSeedance2p0CostState { pub fn from_request(request: &KinoviSeedance2p0RequestState) -> Self { Self { - resolution: request.request.output_resolution.unwrap_or(KinoviOutputResolution::SevenTwentyP), + resolution: request.request.output_resolution, duration_seconds: request.request.duration_seconds, batch_count: request.request.batch_count, has_video_reference: request.request.reference_video_urls @@ -32,27 +33,22 @@ impl KinoviSeedance2p0CostState { .is_some(); Self { - resolution: draft.resolution.unwrap_or(KinoviOutputResolution::SevenTwentyP), + resolution: draft.resolution, duration_seconds: draft.duration_seconds, - batch_count: draft.batch_count, + batch_count: Some(draft.batch_count), has_video_reference, } } pub fn estimate_cost(&self) -> VideoGenerationCostEstimate { - let request = KinoviGenerateVideoRequest { - // Pricing factors - model_type: KinoviModelType::Seedance2Pro, - output_resolution: Some(self.resolution), + let pricing_request = GenerateSeedance2p0Request { + output_resolution: self.resolution, duration_seconds: self.duration_seconds, batch_count: self.batch_count, - // NB: has_video_reference is tracked but does not affect price yet. - // When Kinovi starts charging for video references, add cost here. - // No impact on price prompt: String::new(), - aspect_ratio: KinoviAspectRatio::Portrait9x16, + aspect_ratio: None, start_frame_url: None, end_frame_url: None, reference_image_urls: None, @@ -62,8 +58,8 @@ impl KinoviSeedance2p0CostState { use_face_blur_hack: None, }; - let cost_in_credits = request.estimate_credits(); - let cost_in_usd_cents = request.estimate_cost_in_usd_cents(); + let cost_in_credits = pricing_request.estimate_credits(); + let cost_in_usd_cents = pricing_request.estimate_cost_in_usd_cents(); VideoGenerationCostEstimate { cost_in_credits: Some(cost_in_credits as u64), @@ -79,6 +75,11 @@ impl KinoviSeedance2p0CostState { #[cfg(test)] mod tests { use super::*; + use seedance2pro_client::generate::video::generate_seedance_2p0::{ + KinoviSeedance2p0OutputResolution as KinoviOutputResolution, + KinoviSeedance2p0BatchCount as KinoviBatchCount, + }; + use crate::api::common_resolution::CommonResolution; use crate::api::provider::Provider; use crate::api::video_list_ref::VideoListRef; @@ -93,26 +94,26 @@ mod tests { #[test] fn cost_720p_batch_1() { - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 64); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 80); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 6, KinoviBatchCount::One), 96); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 7, KinoviBatchCount::One), 112); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 160); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 240); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 83); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 104); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 6, KinoviBatchCount::One), 124); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 7, KinoviBatchCount::One), 145); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 207); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 311); } #[test] fn cost_720p_batch_2() { - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Two), 128); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 160); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Two), 480); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Two), 166); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 207); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Two), 622); } #[test] fn cost_720p_batch_4() { - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Four), 256); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 320); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Four), 960); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::Four), 332); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 415); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::Four), 1244); } } @@ -202,9 +203,9 @@ mod tests { #[test] fn video_reference_does_not_affect_cost() { let base = KinoviSeedance2p0CostState { - resolution: KinoviOutputResolution::SevenTwentyP, + resolution: Some(KinoviOutputResolution::SevenTwentyP), duration_seconds: 5, - batch_count: KinoviBatchCount::One, + batch_count: Some(KinoviBatchCount::One), has_video_reference: false, }; let without = base.estimate_cost(); @@ -222,19 +223,19 @@ mod tests { fn from_request_720p() { let req = make_request_state(Some(KinoviOutputResolution::SevenTwentyP), 5, KinoviBatchCount::One, false); let cost = KinoviSeedance2p0CostState::from_request(&req); - assert!(matches!(cost.resolution, KinoviOutputResolution::SevenTwentyP)); + assert!(matches!(cost.resolution, Some(KinoviOutputResolution::SevenTwentyP))); assert_eq!(cost.duration_seconds, 5); - assert!(matches!(cost.batch_count, KinoviBatchCount::One)); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One))); assert!(!cost.has_video_reference); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(80)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104)); } #[test] fn from_request_none_defaults_to_720p() { let req = make_request_state(None, 5, KinoviBatchCount::One, false); let cost = KinoviSeedance2p0CostState::from_request(&req); - assert!(matches!(cost.resolution, KinoviOutputResolution::SevenTwentyP)); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(80)); + assert!(cost.resolution.is_none()); // None defaults to 720p pricing + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104)); } #[test] @@ -257,7 +258,7 @@ mod tests { let cost = KinoviSeedance2p0CostState::from_request(&req); assert!(cost.has_video_reference); // Video refs don't affect cost yet - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(80)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104)); } #[test] @@ -277,18 +278,18 @@ mod tests { fn from_draft_720p_default() { let draft = make_draft(5, 1, None, false); let cost = KinoviSeedance2p0CostState::from_draft(&draft); - assert!(matches!(cost.resolution, KinoviOutputResolution::SevenTwentyP)); + assert!(cost.resolution.is_none()); // None defaults to 720p pricing assert_eq!(cost.duration_seconds, 5); - assert!(matches!(cost.batch_count, KinoviBatchCount::One)); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One))); assert!(!cost.has_video_reference); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(80)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104)); } #[test] fn from_draft_480p() { let draft = make_draft(5, 1, Some(CommonResolution::FourEightyP), false); let cost = KinoviSeedance2p0CostState::from_draft(&draft); - assert!(matches!(cost.resolution, KinoviOutputResolution::FourEightyP)); + assert!(matches!(cost.resolution, Some(KinoviOutputResolution::FourEightyP))); assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(39)); } @@ -296,8 +297,8 @@ mod tests { fn from_draft_1080p_batch_4() { let draft = make_draft(5, 4, Some(CommonResolution::TenEightyP), false); let cost = KinoviSeedance2p0CostState::from_draft(&draft); - assert!(matches!(cost.resolution, KinoviOutputResolution::TenEightyP)); - assert!(matches!(cost.batch_count, KinoviBatchCount::Four)); + assert!(matches!(cost.resolution, Some(KinoviOutputResolution::TenEightyP))); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::Four))); assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(933)); } @@ -307,7 +308,7 @@ mod tests { let cost = KinoviSeedance2p0CostState::from_draft(&draft); assert!(cost.has_video_reference); // Video refs don't affect cost yet - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(80)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(104)); } #[test] @@ -322,8 +323,8 @@ mod tests { let draft = make_draft(15, 2, Some(CommonResolution::SevenTwentyP), false); let cost = KinoviSeedance2p0CostState::from_draft(&draft); assert_eq!(cost.duration_seconds, 15); - assert!(matches!(cost.batch_count, KinoviBatchCount::Two)); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(480)); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::Two))); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(622)); } } @@ -382,7 +383,10 @@ mod tests { duration_seconds: u8, batch_count: KinoviBatchCount, ) -> u64 { - KinoviSeedance2p0CostState { resolution, duration_seconds, batch_count, has_video_reference: false } + KinoviSeedance2p0CostState { + resolution: Some(resolution), duration_seconds, batch_count: Some(batch_count), + has_video_reference: false, + } .estimate_cost() .cost_in_usd_cents .unwrap() @@ -393,7 +397,10 @@ mod tests { duration_seconds: u8, batch_count: KinoviBatchCount, ) -> u64 { - KinoviSeedance2p0CostState { resolution, duration_seconds, batch_count, has_video_reference: false } + KinoviSeedance2p0CostState { + resolution: Some(resolution), duration_seconds, batch_count: Some(batch_count), + has_video_reference: false, + } .estimate_cost() .cost_in_credits .unwrap() @@ -443,13 +450,12 @@ mod tests { }; KinoviSeedance2p0RequestState { - request: KinoviGenerateVideoRequest { - model_type: KinoviModelType::Seedance2Pro, + request: GenerateSeedance2p0Request { prompt: "test".to_string(), - aspect_ratio: KinoviAspectRatio::Landscape16x9, + aspect_ratio: None, output_resolution: resolution, duration_seconds, - batch_count, + batch_count: Some(batch_count), start_frame_url: None, end_frame_url: None, reference_image_urls: None, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs index c1e43bdd78..8b4e62d544 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/draft.rs @@ -1,4 +1,7 @@ -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviGenerateVideoRequest, KinoviModelType, KinoviOutputResolution}; +use seedance2pro_client::generate::video::generate_seedance_2p0::{ + GenerateSeedance2p0Request, KinoviSeedance2p0AspectRatio, + KinoviSeedance2p0BatchCount, KinoviSeedance2p0OutputResolution, +}; use crate::api::audio_list_ref::AudioListRef; use crate::api::character_list_ref::CharacterListRef; @@ -19,10 +22,10 @@ pub struct KinoviSeedance2p0DraftState { // Materialized / finalized types pub prompt: String, - pub aspect_ratio: KinoviAspectRatio, - pub resolution: Option, + pub aspect_ratio: KinoviSeedance2p0AspectRatio, + pub resolution: Option, pub duration_seconds: u8, - pub batch_count: KinoviBatchCount, + pub batch_count: KinoviSeedance2p0BatchCount, // Pending types that need to be queried. pub unhandled_request_state: Option, @@ -77,13 +80,12 @@ impl KinoviSeedance2p0DraftState { )?; } - let request = KinoviGenerateVideoRequest { - model_type: KinoviModelType::Seedance2Pro, + let request = GenerateSeedance2p0Request { prompt: self.prompt.clone(), - aspect_ratio: self.aspect_ratio, + aspect_ratio: Some(self.aspect_ratio), output_resolution: self.resolution, duration_seconds: self.duration_seconds, - batch_count: self.batch_count, + batch_count: Some(self.batch_count), start_frame_url, end_frame_url, reference_image_urls, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/request.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/request.rs index ee4287663e..3ccfe4f656 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/request.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0/request.rs @@ -1,28 +1,31 @@ +use seedance2pro_client::generate::video::generate_seedance_2p0::{ + generate_seedance_2p0, GenerateSeedance2p0Args, GenerateSeedance2p0Request, +}; + use crate::client::router_seedance2pro_client::RouterSeedance2ProClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; use crate::generate::generate_video::generate_video_response::{GenerateVideoResponse, Seedance2proVideoResponsePayload}; -use seedance2pro_client::requests::generate_video::generate_video::{generate_video, GenerateVideoArgs, KinoviGenerateVideoRequest}; #[derive(Debug, Clone)] pub struct KinoviSeedance2p0RequestState { /// Final materialized request; ready to fire. - pub request: KinoviGenerateVideoRequest, + pub request: GenerateSeedance2p0Request, } impl KinoviSeedance2p0RequestState { pub async fn send(&self, client: &RouterSeedance2ProClient) -> Result { let session = &client.session; - let args = GenerateVideoArgs { + let args = GenerateSeedance2p0Args { session, host_override: None, - request: self.request.clone(), // TODO: Yuck. + request: self.request.clone(), }; - let response = generate_video(args) - .await - .map_err(|err| ArtcraftRouterError::Provider(ProviderError::Seedance2Pro(err)))?; + let response = generate_seedance_2p0(args) + .await + .map_err(|err| ArtcraftRouterError::Provider(ProviderError::Seedance2Pro(err)))?; Ok(GenerateVideoResponse::Seedance2Pro(Seedance2proVideoResponsePayload { order_id: response.order_id, @@ -32,320 +35,3 @@ impl KinoviSeedance2p0RequestState { })) } } - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use tokens::tokens::characters::CharacterToken; - use tokens::tokens::media_files::MediaFileToken; - - use crate::api::character_list_ref::CharacterListRef; - use crate::api::common_aspect_ratio::CommonAspectRatio; - use crate::api::common_resolution::CommonResolution; - use crate::api::image_list_ref::ImageListRef; - use crate::api::image_ref::ImageRef; - use crate::api::provider::Provider; - use crate::api::video_list_ref::VideoListRef; - use crate::client::router_client::RouterClient; - use crate::client::router_seedance2pro_client::RouterSeedance2ProClient; - use crate::generate::generate_video::generate_video_request_builder::GenerateVideoRequestBuilder; - use crate::generate::generate_video::generate_video_response::GenerateVideoResponse; - use crate::generate::generate_video_v2::video_generation_draft_context::VideoGenerationDraftContext; - use crate::generate::generate_video_v2::video_generation_draft_or_request::VideoGenerationDraftOrRequest; - use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession; - use test_data::web::image_urls::{FOREST_BACKDROP_IMAGE_URL, JUNO_AT_LAKE_IMAGE_URL, WHITE_HOUSE_SUNSET_IMAGE_URL}; - - const STEAMPUNK_CLOWN_KINOVI_ID: &str = "char_1775176566518_sik0te"; - const MOCHI_KINOVI_ID: &str = "char_1775177718294_g2pitx"; - - mod aspect_ratio_tests { - use super::*; - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn landscape() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A corgi running through a field of wildflowers at sunset.".to_string()), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn portrait() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A cat sitting on a windowsill watching rain.".to_string()), - aspect_ratio: Some(CommonAspectRatio::TallNineBySixteen), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn square() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A hummingbird hovering near a flower.".to_string()), - aspect_ratio: Some(CommonAspectRatio::Square), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - } - - mod resolution_tests { - use super::*; - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn res_480p() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A shiba inu playing in autumn leaves.".to_string()), - resolution: Some(CommonResolution::FourEightyP), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn res_720p() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A golden retriever catching a frisbee on the beach.".to_string()), - resolution: Some(CommonResolution::SevenTwentyP), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn res_1080p() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A fox walking through a snowy forest.".to_string()), - resolution: Some(CommonResolution::TenEightyP), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - } - - mod modality_tests { - use super::*; - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn text_to_video() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A whale breaching in the open ocean at dawn, cinematic.".to_string()), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn keyframe_start_and_end_frame() { - let start_token = MediaFileToken::new("mf_start".to_string()); - let end_token = MediaFileToken::new("mf_end".to_string()); - - let mut media_map = HashMap::new(); - media_map.insert(start_token.clone(), JUNO_AT_LAKE_IMAGE_URL.to_string()); - media_map.insert(end_token.clone(), FOREST_BACKDROP_IMAGE_URL.to_string()); - - let response = run_pipeline_with_media_map(GenerateVideoRequestBuilder { - prompt: Some("The dog walks from the lake to the forest.".to_string()), - start_frame: Some(ImageRef::MediaFileToken(start_token)), - end_frame: Some(ImageRef::MediaFileToken(end_token)), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_builder() - }, media_map).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn image_references() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("The dog in @2 runs through the scenery in @1 towards the building in @3.".to_string()), - reference_images: Some(ImageListRef::Urls(vec![ - FOREST_BACKDROP_IMAGE_URL.to_string(), - JUNO_AT_LAKE_IMAGE_URL.to_string(), - WHITE_HOUSE_SUNSET_IMAGE_URL.to_string(), - ])), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn video_reference() { - // NB: This URL is a pre-uploaded video on the Seedance2Pro CDN from prior tests. - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("Change @video1 to a nighttime scene with moonlight.".to_string()), - reference_videos: Some(VideoListRef::Urls(vec![ - "https://static.seedance2-pro.com/materials/20260315/1773594284659-3a46d231.mp4".to_string(), - ])), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn character_references() { - let char_clown = CharacterToken::new("char_clown".to_string()); - let char_mochi = CharacterToken::new("char_mochi".to_string()); - - let mut character_map = HashMap::new(); - character_map.insert(char_clown.clone(), STEAMPUNK_CLOWN_KINOVI_ID.to_string()); - character_map.insert(char_mochi.clone(), MOCHI_KINOVI_ID.to_string()); - - let response = run_pipeline_with_maps( - GenerateVideoRequestBuilder { - prompt: Some("@Steampunk Clown and @Mochi are playing fetch in a sunny park.".to_string()), - reference_character_tokens: Some(CharacterListRef::CharacterTokens(vec![ - char_clown, - char_mochi, - ])), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_builder() - }, - HashMap::new(), - character_map, - ).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - // TODO: Add audio reference test once a web-accessible audio URL is available in test_data. - } - - // ── Helpers ── - - fn seedance2pro_builder() -> GenerateVideoRequestBuilder { - GenerateVideoRequestBuilder { - provider: Provider::Seedance2Pro, - duration_seconds: Some(4), - video_batch_count: Some(1), - ..Default::default() - } - } - - fn get_seedance2pro_client() -> RouterClient { - let cookies = std::fs::read_to_string("/Users/bt/Artcraft/credentials/seedance2pro_cookies.txt") - .expect("Failed to read seedance2pro cookies"); - let session = Seedance2ProSession::from_cookies_string(cookies.trim().to_string()); - RouterClient::Seedance2Pro(RouterSeedance2ProClient::new(session)) - } - - /// Run the full pipeline: builder → build2 → finalize → send. - async fn run_pipeline(builder: GenerateVideoRequestBuilder) -> GenerateVideoResponse { - let client = get_seedance2pro_client(); - - let draft_or_request = builder.build2().expect("build2 should succeed"); - let draft = match draft_or_request { - VideoGenerationDraftOrRequest::Draft(d) => d, - _ => panic!("expected Draft variant"), - }; - - let draft_context = VideoGenerationDraftContext { - client: Some(&client), - ..Default::default() - }; - - let request = draft.finalize(draft_context).await.expect("finalize should succeed"); - let response = request.send_request(&client).await.expect("send_request should succeed"); - - match &response { - GenerateVideoResponse::Seedance2Pro(p) => { - println!("task_id={}, order_id={}", p.task_id, p.order_id); - } - other => println!("response: {:?}", other), - } - - response - } - - /// Run the full pipeline with a media file token map for resolving references. - async fn run_pipeline_with_media_map( - builder: GenerateVideoRequestBuilder, - media_map: HashMap, - ) -> GenerateVideoResponse { - let client = get_seedance2pro_client(); - - let draft_or_request = builder.build2().expect("build2 should succeed"); - let draft = match draft_or_request { - VideoGenerationDraftOrRequest::Draft(d) => d, - _ => panic!("expected Draft variant"), - }; - - let draft_context = VideoGenerationDraftContext { - client: Some(&client), - media_file_to_artcraft_url_map: Some(&media_map), - ..Default::default() - }; - - let request = draft.finalize(draft_context).await.expect("finalize should succeed"); - let response = request.send_request(&client).await.expect("send_request should succeed"); - - match &response { - GenerateVideoResponse::Seedance2Pro(p) => { - println!("task_id={}, order_id={}", p.task_id, p.order_id); - } - other => println!("response: {:?}", other), - } - - response - } - - /// Run the full pipeline with both a media map and character map. - async fn run_pipeline_with_maps( - builder: GenerateVideoRequestBuilder, - media_map: HashMap, - character_map: HashMap, - ) -> GenerateVideoResponse { - let client = get_seedance2pro_client(); - - let draft_or_request = builder.build2().expect("build2 should succeed"); - let draft = match draft_or_request { - VideoGenerationDraftOrRequest::Draft(d) => d, - _ => panic!("expected Draft variant"), - }; - - let draft_context = VideoGenerationDraftContext { - client: Some(&client), - media_file_to_artcraft_url_map: Some(&media_map), - character_token_to_kinovi_id_map: Some(&character_map), - }; - - let request = draft.finalize(draft_context).await.expect("finalize should succeed"); - let response = request.send_request(&client).await.expect("send_request should succeed"); - - match &response { - GenerateVideoResponse::Seedance2Pro(p) => { - println!("task_id={}, order_id={}", p.task_id, p.order_id); - } - other => println!("response: {:?}", other), - } - - response - } -} diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/build.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/build.rs index acc1fa6e63..b3be756eab 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/build.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/build.rs @@ -1,4 +1,8 @@ -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviOutputResolution}; +use seedance2pro_client::generate::video::generate_seedance_2p0_fast::{ + KinoviSeedance2p0FastAspectRatio as KinoviAspectRatio, + KinoviSeedance2p0FastBatchCount as KinoviBatchCount, + KinoviSeedance2p0FastOutputResolution as KinoviOutputResolution, +}; use crate::api::common_aspect_ratio::CommonAspectRatio; use crate::api::common_resolution::CommonResolution; @@ -73,6 +77,7 @@ fn plan_aspect_ratio( } Some(CommonAspectRatio::WideFourByThree) => Ok(KinoviAspectRatio::Standard4x3), Some(CommonAspectRatio::TallThreeByFour) => Ok(KinoviAspectRatio::Portrait3x4), + Some(CommonAspectRatio::WideTwentyOneByNine) => Ok(KinoviAspectRatio::UltraWide21x9), // Mismatches — apply strategy Some(unsupported) => match strategy { @@ -95,7 +100,6 @@ fn nearest_aspect_ratio(aspect_ratio: CommonAspectRatio) -> KinoviAspectRatio { match aspect_ratio { CommonAspectRatio::WideFiveByFour => KinoviAspectRatio::Standard4x3, // 1.25, nearest 1.33 CommonAspectRatio::WideThreeByTwo => KinoviAspectRatio::Standard4x3, // 1.50, nearest 1.33 - CommonAspectRatio::WideTwentyOneByNine => KinoviAspectRatio::Landscape16x9, // 2.33, nearest 1.78 CommonAspectRatio::TallFourByFive => KinoviAspectRatio::Portrait3x4, // 0.80, nearest 0.75 CommonAspectRatio::TallTwoByThree => KinoviAspectRatio::Portrait3x4, // 0.67, nearest 0.75 CommonAspectRatio::TallNineByTwentyOne => KinoviAspectRatio::Portrait9x16, // 0.43, nearest 0.56 @@ -208,7 +212,11 @@ fn plan_duration( #[cfg(test)] mod tests { - use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviOutputResolution}; + use seedance2pro_client::generate::video::generate_seedance_2p0_fast::{ + KinoviSeedance2p0FastAspectRatio as KinoviAspectRatio, + KinoviSeedance2p0FastBatchCount as KinoviBatchCount, + KinoviSeedance2p0FastOutputResolution as KinoviOutputResolution, + }; use tokens::tokens::characters::CharacterToken; use tokens::tokens::media_files::MediaFileToken; diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/cost.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/cost.rs index 9860ba82f8..12ff4aca5b 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/cost.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/cost.rs @@ -1,22 +1,23 @@ -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviGenerateVideoRequest, KinoviModelType, KinoviOutputResolution}; +use seedance2pro_client::generate::video::generate_seedance_2p0_fast::{ + GenerateSeedance2p0FastRequest, KinoviSeedance2p0FastBatchCount, + KinoviSeedance2p0FastOutputResolution, +}; + use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0_fast::draft::KinoviSeedance2p0FastDraftState; use crate::generate::generate_video_v2::providers::kinovi::seedance_2p0_fast::request::KinoviSeedance2p0FastRequestState; pub struct KinoviSeedance2p0FastCostState { - pub resolution: KinoviOutputResolution, + pub resolution: Option, pub duration_seconds: u8, - pub batch_count: KinoviBatchCount, - - /// Forward-looking: Kinovi charges for this. We need to take it into - /// account in the future. + pub batch_count: Option, pub has_video_reference: bool, } impl KinoviSeedance2p0FastCostState { pub fn from_request(request: &KinoviSeedance2p0FastRequestState) -> Self { Self { - resolution: request.request.output_resolution.unwrap_or(KinoviOutputResolution::SevenTwentyP), + resolution: request.request.output_resolution, duration_seconds: request.request.duration_seconds, batch_count: request.request.batch_count, has_video_reference: request.request.reference_video_urls @@ -32,27 +33,22 @@ impl KinoviSeedance2p0FastCostState { .is_some(); Self { - resolution: draft.resolution.unwrap_or(KinoviOutputResolution::SevenTwentyP), + resolution: draft.resolution, duration_seconds: draft.duration_seconds, - batch_count: draft.batch_count, + batch_count: Some(draft.batch_count), has_video_reference, } } pub fn estimate_cost(&self) -> VideoGenerationCostEstimate { - let request = KinoviGenerateVideoRequest { - // Pricing factors - model_type: KinoviModelType::Seedance2Fast, - output_resolution: Some(self.resolution), + let pricing_request = GenerateSeedance2p0FastRequest { + output_resolution: self.resolution, duration_seconds: self.duration_seconds, batch_count: self.batch_count, - // NB: has_video_reference is tracked but does not affect price yet. - // When Kinovi starts charging for video references, add cost here. - // No impact on price prompt: String::new(), - aspect_ratio: KinoviAspectRatio::Portrait9x16, + aspect_ratio: None, start_frame_url: None, end_frame_url: None, reference_image_urls: None, @@ -62,8 +58,8 @@ impl KinoviSeedance2p0FastCostState { use_face_blur_hack: None, }; - let cost_in_credits = request.estimate_credits(); - let cost_in_usd_cents = request.estimate_cost_in_usd_cents(); + let cost_in_credits = pricing_request.estimate_credits(); + let cost_in_usd_cents = pricing_request.estimate_cost_in_usd_cents(); VideoGenerationCostEstimate { cost_in_credits: Some(cost_in_credits as u64), @@ -80,6 +76,11 @@ impl KinoviSeedance2p0FastCostState { mod tests { use super::*; use crate::api::common_resolution::CommonResolution; + use seedance2pro_client::generate::video::generate_seedance_2p0_fast::{ + KinoviSeedance2p0FastOutputResolution as KinoviOutputResolution, + KinoviSeedance2p0FastBatchCount as KinoviBatchCount, + }; + use crate::api::common_video_model::CommonVideoModel; use crate::api::provider::Provider; use crate::api::video_list_ref::VideoListRef; @@ -90,51 +91,51 @@ mod tests { // ── Direct estimate_cost() tests ── // These must match the reference implementation values exactly. - // -- 720p (legacy pricing: 220 credits/$1, 28 credits/sec) -- + // -- 720p (28 credits/sec, 193 credits/$1) -- mod pricing_720p { use super::*; #[test] fn cost_720p_batch_1() { - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 51); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 64); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 127); - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 191); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 4, KinoviBatchCount::One), 58); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::One), 73); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 10, KinoviBatchCount::One), 145); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 15, KinoviBatchCount::One), 218); } #[test] fn cost_720p_batch_2() { - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 127); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Two), 145); } #[test] fn cost_720p_batch_4() { - assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 255); + assert_eq!(usd_cents(KinoviOutputResolution::SevenTwentyP, 5, KinoviBatchCount::Four), 290); } } - // -- 480p (new pricing: 193 credits/$1, 10 credits/sec) -- + // -- 480p (14 credits/sec, 193 credits/$1) -- mod pricing_480p { use super::*; #[test] fn cost_480p_batch_1() { - assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 4, KinoviBatchCount::One), 21); - assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 26); - assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 10, KinoviBatchCount::One), 52); - assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 15, KinoviBatchCount::One), 78); + assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 4, KinoviBatchCount::One), 29); + assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 36); + assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 10, KinoviBatchCount::One), 73); + assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 15, KinoviBatchCount::One), 109); } #[test] fn cost_480p_batch_2() { - assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Two), 52); + assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Two), 73); } #[test] fn cost_480p_batch_4() { - assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Four), 104); + assert_eq!(usd_cents(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::Four), 145); } } @@ -174,9 +175,9 @@ mod tests { #[test] fn video_reference_does_not_affect_cost() { let base = KinoviSeedance2p0FastCostState { - resolution: KinoviOutputResolution::SevenTwentyP, + resolution: Some(KinoviOutputResolution::SevenTwentyP), duration_seconds: 5, - batch_count: KinoviBatchCount::One, + batch_count: Some(KinoviBatchCount::One), has_video_reference: false, }; let without = base.estimate_cost(); @@ -194,26 +195,26 @@ mod tests { fn from_request_720p() { let req = make_request_state(Some(KinoviOutputResolution::SevenTwentyP), 5, KinoviBatchCount::One, false); let cost = KinoviSeedance2p0FastCostState::from_request(&req); - assert!(matches!(cost.resolution, KinoviOutputResolution::SevenTwentyP)); + assert!(matches!(cost.resolution, Some(KinoviOutputResolution::SevenTwentyP))); assert_eq!(cost.duration_seconds, 5); - assert!(matches!(cost.batch_count, KinoviBatchCount::One)); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One))); assert!(!cost.has_video_reference); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(64)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(73)); } #[test] fn from_request_none_defaults_to_720p() { let req = make_request_state(None, 5, KinoviBatchCount::One, false); let cost = KinoviSeedance2p0FastCostState::from_request(&req); - assert!(matches!(cost.resolution, KinoviOutputResolution::SevenTwentyP)); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(64)); + assert!(cost.resolution.is_none()); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(73)); } #[test] fn from_request_480p() { let req = make_request_state(Some(KinoviOutputResolution::FourEightyP), 5, KinoviBatchCount::One, false); let cost = KinoviSeedance2p0FastCostState::from_request(&req); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(26)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(36)); } #[test] @@ -222,7 +223,7 @@ mod tests { let cost = KinoviSeedance2p0FastCostState::from_request(&req); assert!(cost.has_video_reference); // Video refs don't affect cost yet - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(64)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(73)); } #[test] @@ -242,19 +243,19 @@ mod tests { fn from_draft_720p_default() { let draft = make_draft(5, 1, None, false); let cost = KinoviSeedance2p0FastCostState::from_draft(&draft); - assert!(matches!(cost.resolution, KinoviOutputResolution::SevenTwentyP)); + assert!(cost.resolution.is_none()); assert_eq!(cost.duration_seconds, 5); - assert!(matches!(cost.batch_count, KinoviBatchCount::One)); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::One))); assert!(!cost.has_video_reference); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(64)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(73)); } #[test] fn from_draft_480p() { let draft = make_draft(5, 1, Some(CommonResolution::FourEightyP), false); let cost = KinoviSeedance2p0FastCostState::from_draft(&draft); - assert!(matches!(cost.resolution, KinoviOutputResolution::FourEightyP)); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(26)); + assert!(matches!(cost.resolution, Some(KinoviOutputResolution::FourEightyP))); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(36)); } #[test] @@ -263,7 +264,7 @@ mod tests { let cost = KinoviSeedance2p0FastCostState::from_draft(&draft); assert!(cost.has_video_reference); // Video refs don't affect cost yet - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(64)); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(73)); } #[test] @@ -278,8 +279,8 @@ mod tests { let draft = make_draft(15, 2, Some(CommonResolution::SevenTwentyP), false); let cost = KinoviSeedance2p0FastCostState::from_draft(&draft); assert_eq!(cost.duration_seconds, 15); - assert!(matches!(cost.batch_count, KinoviBatchCount::Two)); - assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(382)); + assert!(matches!(cost.batch_count, Some(KinoviBatchCount::Two))); + assert_eq!(cost.estimate_cost().cost_in_usd_cents, Some(435)); } } @@ -322,7 +323,7 @@ mod tests { #[test] fn credits_480p() { - assert_eq!(credits(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 50); + assert_eq!(credits(KinoviOutputResolution::FourEightyP, 5, KinoviBatchCount::One), 70); } } @@ -333,7 +334,10 @@ mod tests { duration_seconds: u8, batch_count: KinoviBatchCount, ) -> u64 { - KinoviSeedance2p0FastCostState { resolution, duration_seconds, batch_count, has_video_reference: false } + KinoviSeedance2p0FastCostState { + resolution: Some(resolution), duration_seconds, batch_count: Some(batch_count), + has_video_reference: false, + } .estimate_cost() .cost_in_usd_cents .unwrap() @@ -344,7 +348,10 @@ mod tests { duration_seconds: u8, batch_count: KinoviBatchCount, ) -> u64 { - KinoviSeedance2p0FastCostState { resolution, duration_seconds, batch_count, has_video_reference: false } + KinoviSeedance2p0FastCostState { + resolution: Some(resolution), duration_seconds, batch_count: Some(batch_count), + has_video_reference: false, + } .estimate_cost() .cost_in_credits .unwrap() @@ -395,13 +402,12 @@ mod tests { }; KinoviSeedance2p0FastRequestState { - request: KinoviGenerateVideoRequest { - model_type: KinoviModelType::Seedance2Fast, + request: GenerateSeedance2p0FastRequest { prompt: "test".to_string(), - aspect_ratio: KinoviAspectRatio::Landscape16x9, + aspect_ratio: None, output_resolution: resolution, duration_seconds, - batch_count, + batch_count: Some(batch_count), start_frame_url: None, end_frame_url: None, reference_image_urls: None, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/draft.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/draft.rs index 6f3890ae23..878649eb38 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/draft.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/draft.rs @@ -1,4 +1,7 @@ -use seedance2pro_client::requests::generate_video::generate_video::{KinoviAspectRatio, KinoviBatchCount, KinoviGenerateVideoRequest, KinoviModelType, KinoviOutputResolution}; +use seedance2pro_client::generate::video::generate_seedance_2p0_fast::{ + GenerateSeedance2p0FastRequest, KinoviSeedance2p0FastAspectRatio, + KinoviSeedance2p0FastBatchCount, KinoviSeedance2p0FastOutputResolution, +}; use crate::api::audio_list_ref::AudioListRef; use crate::api::character_list_ref::CharacterListRef; @@ -16,15 +19,12 @@ use crate::generate::generate_video_v2::video_generation_draft_context::VideoGen #[derive(Debug, Clone)] pub struct KinoviSeedance2p0FastDraftState { - // Materialized / finalized types - pub prompt: String, - pub aspect_ratio: KinoviAspectRatio, - pub resolution: Option, + pub aspect_ratio: KinoviSeedance2p0FastAspectRatio, + pub resolution: Option, pub duration_seconds: u8, - pub batch_count: KinoviBatchCount, + pub batch_count: KinoviSeedance2p0FastBatchCount, - // Pending types that need to be queried. pub unhandled_request_state: Option, } @@ -77,13 +77,12 @@ impl KinoviSeedance2p0FastDraftState { )?; } - let request = KinoviGenerateVideoRequest { - model_type: KinoviModelType::Seedance2Fast, + let request = GenerateSeedance2p0FastRequest { prompt: self.prompt.clone(), - aspect_ratio: self.aspect_ratio, + aspect_ratio: Some(self.aspect_ratio), output_resolution: self.resolution, duration_seconds: self.duration_seconds, - batch_count: self.batch_count, + batch_count: Some(self.batch_count), start_frame_url, end_frame_url, reference_image_urls, diff --git a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/request.rs b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/request.rs index 44e96a52c2..fdbf4cd0eb 100644 --- a/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/request.rs +++ b/crates/api_clients/artcraft/artcraft_router/src/generate/generate_video_v2/providers/kinovi/seedance_2p0_fast/request.rs @@ -1,28 +1,31 @@ +use seedance2pro_client::generate::video::generate_seedance_2p0_fast::{ + generate_seedance_2p0_fast, GenerateSeedance2p0FastArgs, GenerateSeedance2p0FastRequest, +}; + use crate::client::router_seedance2pro_client::RouterSeedance2ProClient; use crate::errors::artcraft_router_error::ArtcraftRouterError; use crate::errors::provider_error::ProviderError; use crate::generate::generate_video::generate_video_response::{GenerateVideoResponse, Seedance2proVideoResponsePayload}; -use seedance2pro_client::requests::generate_video::generate_video::{generate_video, GenerateVideoArgs, KinoviGenerateVideoRequest}; #[derive(Debug, Clone)] pub struct KinoviSeedance2p0FastRequestState { /// Final materialized request; ready to fire. - pub request: KinoviGenerateVideoRequest, + pub request: GenerateSeedance2p0FastRequest, } impl KinoviSeedance2p0FastRequestState { pub async fn send(&self, client: &RouterSeedance2ProClient) -> Result { let session = &client.session; - let args = GenerateVideoArgs { + let args = GenerateSeedance2p0FastArgs { session, host_override: None, - request: self.request.clone(), // TODO: Yuck. + request: self.request.clone(), }; - let response = generate_video(args) - .await - .map_err(|err| ArtcraftRouterError::Provider(ProviderError::Seedance2Pro(err)))?; + let response = generate_seedance_2p0_fast(args) + .await + .map_err(|err| ArtcraftRouterError::Provider(ProviderError::Seedance2Pro(err)))?; Ok(GenerateVideoResponse::Seedance2Pro(Seedance2proVideoResponsePayload { order_id: response.order_id, @@ -32,229 +35,3 @@ impl KinoviSeedance2p0FastRequestState { })) } } - -#[cfg(test)] -mod tests { - use std::collections::HashMap; - - use tokens::tokens::characters::CharacterToken; - use tokens::tokens::media_files::MediaFileToken; - - use crate::api::character_list_ref::CharacterListRef; - use crate::api::common_aspect_ratio::CommonAspectRatio; - use crate::api::common_resolution::CommonResolution; - use crate::api::common_video_model::CommonVideoModel; - use crate::api::image_list_ref::ImageListRef; - use crate::api::image_ref::ImageRef; - use crate::api::provider::Provider; - use crate::api::video_list_ref::VideoListRef; - use crate::client::router_client::RouterClient; - use crate::client::router_seedance2pro_client::RouterSeedance2ProClient; - use crate::generate::generate_video::generate_video_request_builder::GenerateVideoRequestBuilder; - use crate::generate::generate_video::generate_video_response::GenerateVideoResponse; - use crate::generate::generate_video_v2::video_generation_draft_context::VideoGenerationDraftContext; - use crate::generate::generate_video_v2::video_generation_draft_or_request::VideoGenerationDraftOrRequest; - use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession; - use test_data::web::image_urls::{FOREST_BACKDROP_IMAGE_URL, JUNO_AT_LAKE_IMAGE_URL, WHITE_HOUSE_SUNSET_IMAGE_URL}; - - mod aspect_ratio_tests { - use super::*; - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn landscape() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A corgi running through a field of wildflowers at sunset.".to_string()), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn portrait() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A cat sitting on a windowsill watching rain.".to_string()), - aspect_ratio: Some(CommonAspectRatio::TallNineBySixteen), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn square() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A hummingbird hovering near a flower.".to_string()), - aspect_ratio: Some(CommonAspectRatio::Square), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - } - - mod resolution_tests { - use super::*; - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn res_480p() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A shiba inu playing in autumn leaves.".to_string()), - resolution: Some(CommonResolution::FourEightyP), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn res_720p() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A golden retriever catching a frisbee on the beach.".to_string()), - resolution: Some(CommonResolution::SevenTwentyP), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - } - - mod modality_tests { - use super::*; - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn text_to_video() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("A whale breaching in the open ocean at dawn, cinematic.".to_string()), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn keyframe_start_and_end_frame() { - let start_token = MediaFileToken::new("mf_start".to_string()); - let end_token = MediaFileToken::new("mf_end".to_string()); - - let mut media_map = HashMap::new(); - media_map.insert(start_token.clone(), JUNO_AT_LAKE_IMAGE_URL.to_string()); - media_map.insert(end_token.clone(), FOREST_BACKDROP_IMAGE_URL.to_string()); - - let response = run_pipeline_with_media_map(GenerateVideoRequestBuilder { - prompt: Some("The dog walks from the lake to the forest.".to_string()), - start_frame: Some(ImageRef::MediaFileToken(start_token)), - end_frame: Some(ImageRef::MediaFileToken(end_token)), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_fast_builder() - }, media_map).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - - #[tokio::test] - #[ignore] // manually run — fires a real API request and incurs cost - async fn image_references() { - let response = run_pipeline(GenerateVideoRequestBuilder { - prompt: Some("The dog in @2 runs through the scenery in @1 towards the building in @3.".to_string()), - reference_images: Some(ImageListRef::Urls(vec![ - FOREST_BACKDROP_IMAGE_URL.to_string(), - JUNO_AT_LAKE_IMAGE_URL.to_string(), - WHITE_HOUSE_SUNSET_IMAGE_URL.to_string(), - ])), - aspect_ratio: Some(CommonAspectRatio::WideSixteenByNine), - ..seedance2pro_fast_builder() - }).await; - assert!(matches!(response, GenerateVideoResponse::Seedance2Pro(_))); - assert_eq!(1, 2, "Inspect output above"); - } - } - - // ── Helpers ── - - fn seedance2pro_fast_builder() -> GenerateVideoRequestBuilder { - GenerateVideoRequestBuilder { - model: CommonVideoModel::Seedance2p0Fast, - provider: Provider::Seedance2Pro, - duration_seconds: Some(4), - video_batch_count: Some(1), - ..Default::default() - } - } - - fn get_seedance2pro_client() -> RouterClient { - let cookies = std::fs::read_to_string("/Users/bt/Artcraft/credentials/seedance2pro_cookies.txt") - .expect("Failed to read seedance2pro cookies"); - let session = Seedance2ProSession::from_cookies_string(cookies.trim().to_string()); - RouterClient::Seedance2Pro(RouterSeedance2ProClient::new(session)) - } - - /// Run the full pipeline: builder -> build2 -> finalize -> send. - async fn run_pipeline(builder: GenerateVideoRequestBuilder) -> GenerateVideoResponse { - let client = get_seedance2pro_client(); - - let draft_or_request = builder.build2().expect("build2 should succeed"); - let draft = match draft_or_request { - VideoGenerationDraftOrRequest::Draft(d) => d, - _ => panic!("expected Draft variant"), - }; - - let draft_context = VideoGenerationDraftContext { - client: Some(&client), - ..Default::default() - }; - - let request = draft.finalize(draft_context).await.expect("finalize should succeed"); - let response = request.send_request(&client).await.expect("send_request should succeed"); - - match &response { - GenerateVideoResponse::Seedance2Pro(p) => { - println!("task_id={}, order_id={}", p.task_id, p.order_id); - } - other => println!("response: {:?}", other), - } - - response - } - - /// Run the full pipeline with a media file token map for resolving references. - async fn run_pipeline_with_media_map( - builder: GenerateVideoRequestBuilder, - media_map: HashMap, - ) -> GenerateVideoResponse { - let client = get_seedance2pro_client(); - - let draft_or_request = builder.build2().expect("build2 should succeed"); - let draft = match draft_or_request { - VideoGenerationDraftOrRequest::Draft(d) => d, - _ => panic!("expected Draft variant"), - }; - - let draft_context = VideoGenerationDraftContext { - client: Some(&client), - media_file_to_artcraft_url_map: Some(&media_map), - ..Default::default() - }; - - let request = draft.finalize(draft_context).await.expect("finalize should succeed"); - let response = request.send_request(&client).await.expect("send_request should succeed"); - - match &response { - GenerateVideoResponse::Seedance2Pro(p) => { - println!("task_id={}, order_id={}", p.task_id, p.order_id); - } - other => println!("response: {:?}", other), - } - - response - } -} diff --git a/frontend/libs/components/settings-modal/tsconfig.json b/frontend/libs/components/settings-modal/tsconfig.json index 454a3117c6..75389c36bd 100644 --- a/frontend/libs/components/settings-modal/tsconfig.json +++ b/frontend/libs/components/settings-modal/tsconfig.json @@ -2,18 +2,15 @@ "files": [], "include": [], "references": [ - { - "path": "../../analytics/google-analytics" - }, - { - "path": "../modal" - }, { "path": "../../tauri-utils" }, { "path": "../../model-list" }, + { + "path": "../promptbox" + }, { "path": "../../state/subscription" }, @@ -33,10 +30,10 @@ "path": "../../soundboard" }, { - "path": "../../tauri-events" + "path": "../input" }, { - "path": "../input" + "path": "../../tauri-events" }, { "path": "../login-modal" @@ -45,7 +42,7 @@ "path": "../../api" }, { - "path": "../button" + "path": "../../analytics/google-analytics" }, { "path": "../label" @@ -53,6 +50,12 @@ { "path": "../../tauri-api" }, + { + "path": "../button" + }, + { + "path": "../modal" + }, { "path": "./tsconfig.lib.json" }, diff --git a/frontend/libs/components/settings-modal/tsconfig.lib.json b/frontend/libs/components/settings-modal/tsconfig.lib.json index 2c7875c47c..f8f198a14c 100644 --- a/frontend/libs/components/settings-modal/tsconfig.lib.json +++ b/frontend/libs/components/settings-modal/tsconfig.lib.json @@ -43,18 +43,15 @@ "src/**/*.tsx" ], "references": [ - { - "path": "../../analytics/google-analytics/tsconfig.lib.json" - }, - { - "path": "../modal/tsconfig.lib.json" - }, { "path": "../../tauri-utils/tsconfig.lib.json" }, { "path": "../../model-list/tsconfig.lib.json" }, + { + "path": "../promptbox/tsconfig.lib.json" + }, { "path": "../../state/subscription/tsconfig.lib.json" }, @@ -74,10 +71,10 @@ "path": "../../soundboard/tsconfig.lib.json" }, { - "path": "../../tauri-events/tsconfig.lib.json" + "path": "../input/tsconfig.lib.json" }, { - "path": "../input/tsconfig.lib.json" + "path": "../../tauri-events/tsconfig.lib.json" }, { "path": "../login-modal/tsconfig.lib.json" @@ -86,13 +83,19 @@ "path": "../../api/tsconfig.lib.json" }, { - "path": "../button/tsconfig.lib.json" + "path": "../../analytics/google-analytics/tsconfig.lib.json" }, { "path": "../label/tsconfig.lib.json" }, { "path": "../../tauri-api/tsconfig.lib.json" + }, + { + "path": "../button/tsconfig.lib.json" + }, + { + "path": "../modal/tsconfig.lib.json" } ] }