Compare commits

..
Author SHA1 Message Date
Brandon Thomas f587e19d25 remove gpu loading error 2025-09-27 18:27:33 -04:00
1441 changed files with 15411 additions and 72484 deletions
-1
View File
@@ -1,7 +1,6 @@
SERVER_ENVIRONMENT=development
DATABASE_URL=mysql://storyteller:password@localhost/storyteller
#DATABASE_URL=sqlite:/tmp/tasks.sqlite
#DATABASE_URL=mysql://root:root@localhost/storyteller
#DATABASE_URL=mysql://root@localhost/storyteller
-3
View File
@@ -45,9 +45,6 @@ crates/lib/sqlite_queries/target/
# Javascript build directories
node_modules/
# Frontend build outputs
frontend/apps/editor3d/bundle-report.html
# Vim noise
*.swo
*.swp
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE tasks\n SET is_dismissed_by_user = 1\n WHERE id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "13d435d8f681b73e4080748dcef0579e246e41049af67e1bd79ffc06aa6ba974"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE tasks\n SET\n task_status = ?,\n on_complete_batch_token = ?,\n on_complete_primary_media_file_token = ?,\n on_complete_primary_media_file_class = ?,\n on_complete_primary_media_file_cdn_url = ?,\n on_complete_primary_media_file_thumbnail_url_template = ?\n WHERE\n provider = ?\n AND provider_job_id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 8
},
"nullable": []
},
"hash": "1e3758851fc8451670f86a9432009b73bdb81de4a08dcaa96a86afb5f9be7a68"
}
@@ -1,68 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT\n id,\n task_status,\n task_type,\n model_type,\n provider,\n provider_job_id,\n frontend_caller,\n frontend_subscriber_id,\n frontend_subscriber_payload\n FROM tasks\n WHERE\n provider = ?\n AND provider_job_id = ?\n ",
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "task_status",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "task_type",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "model_type",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "provider",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "provider_job_id",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "frontend_caller",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "frontend_subscriber_id",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "frontend_subscriber_payload",
"ordinal": 8,
"type_info": "Text"
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
true,
true,
true,
true,
true,
true
]
},
"hash": "38ff2df237b16f077865711dd81261de1b5fa05a9787679ce9ccd4ac576b1069"
}
@@ -1,116 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT\n id,\n task_status,\n task_type,\n model_type,\n provider,\n provider_job_id,\n frontend_caller,\n frontend_subscriber_id,\n frontend_subscriber_payload,\n on_complete_primary_media_file_token,\n on_complete_primary_media_file_class,\n on_complete_batch_token,\n on_complete_primary_media_file_cdn_url,\n on_complete_primary_media_file_thumbnail_url_template,\n created_at as \"created_at: DateTime<Utc>\",\n updated_at as \"updated_at: DateTime<Utc>\",\n completed_at as \"completed_at: DateTime<Utc>\"\n FROM tasks\n WHERE is_dismissed_by_user == 0\n ",
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "task_status",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "task_type",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "model_type",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "provider",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "provider_job_id",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "frontend_caller",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "frontend_subscriber_id",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "frontend_subscriber_payload",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "on_complete_primary_media_file_token",
"ordinal": 9,
"type_info": "Text"
},
{
"name": "on_complete_primary_media_file_class",
"ordinal": 10,
"type_info": "Text"
},
{
"name": "on_complete_batch_token",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "on_complete_primary_media_file_cdn_url",
"ordinal": 12,
"type_info": "Text"
},
{
"name": "on_complete_primary_media_file_thumbnail_url_template",
"ordinal": 13,
"type_info": "Text"
},
{
"name": "created_at: DateTime<Utc>",
"ordinal": 14,
"type_info": "Int64"
},
{
"name": "updated_at: DateTime<Utc>",
"ordinal": 15,
"type_info": "Int64"
},
{
"name": "completed_at: DateTime<Utc>",
"ordinal": 16,
"type_info": "Int64"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
true,
false,
false,
true
]
},
"hash": "47f94c127abc20683b25c257aed3c2190b9bd29eb829d61392f08e10fd986767"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "\n UPDATE tasks\n SET\n task_status = ?,\n on_complete_batch_token = ?,\n on_complete_primary_media_file_token = ?,\n on_complete_primary_media_file_class = ?,\n on_complete_primary_media_file_cdn_url = ?,\n on_complete_primary_media_file_thumbnail_url_template = ?\n WHERE id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "50a2449b87abed7df3302a74ecd0e8ab87940077a247636680cb09b2fe488321"
}
Generated
+405 -797
View File
File diff suppressed because it is too large Load Diff
+6 -34
View File
@@ -6,19 +6,17 @@ resolver = "2"
members = [
# API clients for external services
# These might be custom implementations or wrappers over other client libraries.
"crates/api_clients/artcraft/artcraft_api_defs", # TODO: api_clients/{artcraft}/{api_defs,client}
"crates/api_clients/artcraft/storyteller_client",
"crates/api_clients/artcraft_api_defs", # TODO: api_clients/{artcraft}/{api_defs,client}
"crates/api_clients/cloud_storage",
"crates/api_clients/fal_client",
"crates/api_clients/google_drive_common",
"crates/api_clients/google_sign_in",
"crates/api_clients/grok_client",
"crates/api_clients/midjourney_client",
"crates/api_clients/openai_sora_client",
"crates/api_clients/openart_client",
"crates/api_clients/runwayml_client",
"crates/api_clients/storyteller_client",
"crates/api_clients/thumbnail_generator",
"crates/api_clients/world_labs_client",
# CLI tools for operations, etc.
"crates/cli/devenv/dev-database-seed",
@@ -45,7 +43,6 @@ members = [
"crates/lib/caching/memory_store",
"crates/lib/caching/redis_caching",
"crates/lib/cloudflare_errors",
"crates/lib/cloudflare_mitigation",
"crates/lib/concurrency",
"crates/lib/cookie_store",
"crates/lib/cookies",
@@ -68,7 +65,6 @@ members = [
"crates/lib/files/media",
"crates/lib/files/mimetypes",
"crates/lib/files/videos",
"crates/lib/http_headers",
"crates/lib/idempotency",
"crates/lib/image_algorithms",
"crates/lib/jobs_common",
@@ -88,7 +84,6 @@ members = [
"crates/lib/testing",
"crates/lib/tts_common",
"crates/lib/url_config",
"crates/lib/url_utils",
"crates/lib/user_input_common",
"crates/lib/web_scrapers",
#"crates/lib/api_clients/fakeyou_client",
@@ -186,11 +181,10 @@ workspace-build-acceleration = { path = "crates/workspace-build-acceleration" }
# Internal libs
# Setting paths here ensures we don't need to do so in every crate's Cargo.toml
# It makes refactoring much easier.
artcraft_api_defs = { path = "crates/api_clients/artcraft/artcraft_api_defs" }
artcraft_api_defs = { path = "crates/api_clients/artcraft_api_defs" }
build_metadata = { path = "crates/lib/build_metadata" }
cloud_storage = { path = "crates/api_clients/cloud_storage" }
cloudflare_errors = { path = "crates/lib/cloudflare_errors" }
cloudflare_mitigation = { path = "crates/lib/cloudflare_mitigation" }
component_traits = { path = "crates/service/plugins/component_traits" }
cookie_store = { path = "crates/lib/cookie_store" }
crockford = { path = "crates/lib/data/crockford" }
@@ -200,8 +194,6 @@ errors = { path = "crates/lib/errors" }
fal_client = { path = "crates/api_clients/fal_client" }
file_to_base64_url = { path = "crates/lib/files/file_to_base64_url" }
filesys = { path = "crates/lib/files/filesys" }
grok_client = { path = "crates/api_clients/grok_client" }
http_headers = { path = "crates/lib/http_headers" }
idempotency = { path = "crates/lib/idempotency" }
images = { path = "crates/lib/files/images" }
jwt_light = { path = "crates/lib/jwt_light" }
@@ -213,14 +205,12 @@ openai_sora_client = { path = "crates/api_clients/openai_sora_client" }
primitives = { path = "crates/lib/data/primitives" }
shared_service_components = { path = "crates/lib/shared_service_components" }
sqlite_tasks = { path = "crates/schema/database/sqlite_tasks" }
storyteller_client = { path = "crates/api_clients/artcraft/storyteller_client" }
storyteller_client = { path = "crates/api_clients/storyteller_client" }
subprocess_common = { path = "crates/lib/subprocess_common" }
test_data = { path = "crates/lib/test_data" }
testing = { path = "crates/lib/testing" }
tokens = { path = "crates/schema/public/tokens" }
url_utils = { path = "crates/lib/url_utils" }
web_base64 = { path = "crates/lib/data/web_base64" }
world_labs_client = { path = "crates/api_clients/world_labs_client" }
# External libs
# Centrally pinned versions so that we can uniformly upgrade/downgrade versions across the workspace
@@ -237,26 +227,22 @@ actix-web-actors = "4.3.1+deprecated"
actix-web-lab = "0.20.2"
anyhow = "1.0.98"
base64 = "0.22.1"
bstr = "1.12.1"
bytes = "1.10.1"
chrono = { version = "0.4.41", features = ["serde"] }
cookie = "0.18.1"
env = "1.0.1"
env_logger = "0.11.8"
futures = { version = "0.3.31" }
hex-literal = "1.0.0"
indexmap = "2.9.0"
log = "0.4.27"
once_cell = "1.21.3"
rand = "0.9.1"
regex = "1.12.2"
reqwest = { version = "0.12.23", default-features = false, features = [ "charset", "http2", "system-proxy", "json", "cookies", "rustls-tls" ] }
regex = "1.11.1"
reqwest = { version = "0.12.22", features = ["json", "cookies"] }
reqwest-websocket = { version = "0.5.0" }
serde = { version = "1.0.219", features = ["derive"] }
serde_derive = "1.0.219"
serde_json = "1.0.140"
serde_yaml = "0.9.34+deprecated"
sha2 = "0.11.0-rc.2"
sha3 = "0.10.8"
tauri = { version = "2.8.3", features = ["unstable", "devtools"] } # NB: "devtools" prevents App Store distribution; "ubstable" is needed for window access
tauri-plugin-dialog = "2.3.3"
@@ -269,17 +255,3 @@ thiserror = "2.0.12"
tokio = { version = "1.45.1", features = ["macros"] }
toml = "0.8.22"
url = { version = "2.5.4", features = ["serde"] }
uuid = "1.18.1"
# NB: wreq gets past fingerprinting, but we have to deal with platform-specific build issues.
#
# Mac:
# brew install --formula cmake pkg-config llvm
# Windows:
# choco install cmake -y
# choco install strawberryperl -y
# choco install pkgconfiglite -y
# choco install llvm -y
# choco install nasm -y
wreq = { version = "6.0.0-rc.20", features = ["json", "multipart", "cookies", "ws", "stream"] }
wreq-util = "3.0.0-rc.6"
@@ -1,20 +0,0 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
select
u.display_name,
count(*) as sessions,
a.session_duration_seconds / 60 / 60 as hours,
a.measurement_count,
u.email_address,
a.os_platform,
a.os_version,
u.created_at,
u.maybe_source,
a.last_active_at
from analytics_app_sessions as a
left outer join users as u
on a.user_token = u.token
group by a.user_token
order by hours desc;
@@ -9,14 +9,6 @@
-- tasks_v1.sqlite - initial version
-- tasks_v2.sqlite - added model_type (nullable)
-- tasks_v3.sqlite - added frontend_caller, comments
-- tasks_v4.sqlite - added is_dismissed_by_user
-- tasks_v5.sqlite - added five fields:
-- on_complete_batch_token,
-- on_complete_primary_media_file_token,
-- on_complete_primary_media_file_class,
-- on_complete_primary_media_file_cdn_url,
-- on_complete_primary_media_file_thumbnail_url_template,
--
CREATE TABLE tasks (
-- Task auto-incrementing primary key.
@@ -58,32 +50,6 @@ CREATE TABLE tasks (
-- will be re-emitted back to the frontend.
frontend_subscriber_payload TEXT,
-- Whether the user has dismissed the task from view.
is_dismissed_by_user INTEGER NOT NULL DEFAULT 0,
-- OPTIONAL.
-- When the generation completes, the batch token (if any).
-- This will point to a collection of multiple files.
on_complete_batch_token TEXT,
-- OPTIONAL.
-- When the generation completes, the media token of the "primary" media file.
-- We'll probably always generate homogenous types, but just in case this is the first or primary item in a batch.
on_complete_primary_media_file_token TEXT,
-- OPTIONAL.
-- When the generation completes, the file type of the primary media file.
-- We'll probably always generate homogenous types, but just in case this is the first or primary item in a batch.
on_complete_primary_media_file_class TEXT,
-- OPTIONAL.
-- The URL to the media file.
on_complete_primary_media_file_cdn_url TEXT,
-- OPTIONAL.
-- The URL template for the thumbnail of the primary media file.
on_complete_primary_media_file_thumbnail_url_template TEXT,
created_at INTEGER NOT NULL DEFAULT (unixepoch('now')),
updated_at INTEGER NOT NULL DEFAULT (unixepoch('now')),
completed_at INTEGER DEFAULT NULL
-1
View File
@@ -152,7 +152,6 @@ CREATE TABLE media_files (
-- * `vmd`
-- * `pmx`
-- * `csv`
-- * `spz` Gaussian splats
media_type VARCHAR(16) NOT NULL,
-- Broad class of media:
@@ -1,7 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Serialize, Deserialize, ToSchema)]
pub struct SimpleGenericJsonSuccess {
pub success: bool,
}
@@ -1 +0,0 @@
pub mod remove_image_background;
@@ -1,5 +0,0 @@
pub mod bg_removal;
pub mod edit;
pub mod inpaint;
pub mod multi_function;
pub mod text;
@@ -1,69 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const BYTEDANCE_SEEDREAM_V4_MULTI_FUNCTION_IMAGE_GEN_PATH: &str = "/v1/generate/image/multi_function/bytedance_seedream_4";
#[derive(Serialize, Deserialize, ToSchema)]
pub struct BytedanceSeedreamV4MultiFunctionImageGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt to generate the image from.
pub prompt: Option<String>,
/// Image media tokens to include in the editing context.
/// If present, we're doing image editing (image-to-image / image-editing)
/// If absent, we're doing image generation (text-to-image)
pub image_media_tokens: Option<Vec<MediaFileToken>>,
/// Number of images to generate. Default is one.
pub num_images: Option<BytedanceSeedreamV4MultiFunctionImageGenNumImages>,
pub max_images: Option<BytedanceSeedreamV4MultiFunctionImageGenMaxImages>,
pub image_size: Option<BytedanceSeedreamV4MultiFunctionImageGenImageSize>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum BytedanceSeedreamV4MultiFunctionImageGenNumImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum BytedanceSeedreamV4MultiFunctionImageGenMaxImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum BytedanceSeedreamV4MultiFunctionImageGenImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto,
Auto2k,
Auto4k,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct BytedanceSeedreamV4MultiFunctionImageGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,68 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const BYTEDANCE_SEEDREAM_V4P5_MULTI_FUNCTION_IMAGE_GEN_PATH: &str = "/v1/generate/image/multi_function/bytedance_seedream_4p5";
#[derive(Serialize, Deserialize, ToSchema)]
pub struct BytedanceSeedreamV4p5MultiFunctionImageGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt to generate the image from.
pub prompt: Option<String>,
/// Image media tokens to include in the editing context.
/// If present, we're doing image editing (image-to-image / image-editing)
/// If absent, we're doing image generation (text-to-image)
pub image_media_tokens: Option<Vec<MediaFileToken>>,
/// Number of images to generate. Default is one.
pub num_images: Option<BytedanceSeedreamV4p5MultiFunctionImageGenNumImages>,
pub max_images: Option<BytedanceSeedreamV4p5MultiFunctionImageGenMaxImages>,
pub image_size: Option<BytedanceSeedreamV4p5MultiFunctionImageGenImageSize>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum BytedanceSeedreamV4p5MultiFunctionImageGenNumImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum BytedanceSeedreamV4p5MultiFunctionImageGenMaxImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum BytedanceSeedreamV4p5MultiFunctionImageGenImageSize {
// Square
Square,
SquareHd,
// Tall
PortraitFourThree,
PortraitSixteenNine,
// Wide
LandscapeFourThree,
LandscapeSixteenNine,
// Auto
Auto2k,
Auto4k,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct BytedanceSeedreamV4p5MultiFunctionImageGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,95 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const GPT_IMAGE_1P5_MULTI_FUNCTION_IMAGE_GEN_PATH: &str = "/v1/generate/image/multi_function/gpt_image_1p5";
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GptImage1p5MultiFunctionImageGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt to generate the image from.
pub prompt: Option<String>,
/// Image media tokens to include in the editing context (**OR INPAINTING CONTEXT!**).
/// If present, we're doing image editing (image-to-image / image-editing / image-inpainting)
/// If absent, we're doing image generation (text-to-image)
pub image_media_tokens: Option<Vec<MediaFileToken>>,
/// Only for image editing, which turns this into an inpainting task.
/// Text to image should not set this.
pub mask_image_token: Option<MediaFileToken>,
/// Number of images to generate. Default is one.
pub num_images: Option<GptImage1p5MultiFunctionImageGenNumImages>,
pub image_size: Option<GptImage1p5MultiFunctionImageGenSize>,
pub background: Option<GptImage1p5MultiFunctionImageGenBackground>,
pub quality: Option<GptImage1p5MultiFunctionImageGenQuality>,
/// Only for image editing.
pub input_fidelity: Option<GptImage1p5MultiFunctionImageGenInputFidelity>,
pub output_format: Option<GptImage1p5MultiFunctionImageGenOutputFormat>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GptImage1p5MultiFunctionImageGenNumImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GptImage1p5MultiFunctionImageGenSize {
/// 1024x1024
Square,
/// 1536x1024
Wide,
/// 1024x1536
Tall,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GptImage1p5MultiFunctionImageGenBackground {
Auto,
Transparent,
Opaque,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GptImage1p5MultiFunctionImageGenQuality {
Low,
Medium,
High,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GptImage1p5MultiFunctionImageGenInputFidelity {
Low,
High,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GptImage1p5MultiFunctionImageGenOutputFormat {
Jpeg,
Png,
Webp,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GptImage1p5MultiFunctionImageGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,5 +0,0 @@
pub mod bytedance_seedream_v4_multi_function_image_gen;
pub mod bytedance_seedream_v4p5_multi_function_image_gen;
pub mod gpt_image_1p5_multi_function_image_gen;
pub mod nano_banana_multi_function_image_gen;
pub mod nano_banana_pro_multi_function_image_gen;
@@ -1,62 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const NANO_BANANA_MULTI_FUNCTION_IMAGE_GEN_PATH: &str = "/v1/generate/image/multi_function/nano_banana";
#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct NanoBananaMultiFunctionImageGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt to generate the image from.
pub prompt: Option<String>,
/// Image media tokens to include in the editing context.
/// If present, we're doing image editing (image-to-image / image-editing)
/// If absent, we're doing image generation (text-to-image)
pub image_media_tokens: Option<Vec<MediaFileToken>>,
/// Number of images to generate. Default is one.
pub num_images: Option<NanoBananaMultiFunctionImageGenNumImages>,
/// Aspect ratio of the images to generate. Default is "1:1"
pub aspect_ratio: Option<NanoBananaMultiFunctionImageGenAspectRatio>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum NanoBananaMultiFunctionImageGenNumImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum NanoBananaMultiFunctionImageGenAspectRatio {
// Auto (only for image editing)
Auto, // Default for image editing.
// Square
OneByOne, // Default for text-to-image
// Wide
FiveByFour,
FourByThree,
ThreeByTwo,
SixteenByNine,
TwentyOneByNine,
// Tall
FourByFive,
ThreeByFour,
TwoByThree,
NineBySixteen, // NB: No NineByTwentyOne ?
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct NanoBananaMultiFunctionImageGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,73 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const NANO_BANANA_PRO_MULTI_FUNCTION_IMAGE_GEN_PATH: &str = "/v1/generate/image/multi_function/nano_banana_pro";
#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct NanoBananaProMultiFunctionImageGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt to generate the image from.
pub prompt: Option<String>,
/// Image media tokens to include in the editing context.
/// If present, we're doing image editing (image-to-image / image-editing)
/// If absent, we're doing image generation (text-to-image)
pub image_media_tokens: Option<Vec<MediaFileToken>>,
/// Number of images to generate. Default is one.
pub num_images: Option<NanoBananaProMultiFunctionImageGenNumImages>,
/// Resolution of the image to generate. Default is OneK (1K).
pub resolution: Option<NanoBananaProMultiFunctionImageGenImageResolution>,
/// Aspect ratio of the images to generate. Default is "1:1"
pub aspect_ratio: Option<NanoBananaProMultiFunctionImageGenAspectRatio>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum NanoBananaProMultiFunctionImageGenNumImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum NanoBananaProMultiFunctionImageGenImageResolution {
OneK,
TwoK,
FourK,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum NanoBananaProMultiFunctionImageGenAspectRatio {
// Auto (only for image editing)
Auto, // Default for image editing.
// Square
OneByOne, // Default for text-to-image
// Wide
FiveByFour,
FourByThree,
ThreeByTwo,
SixteenByNine,
TwentyOneByNine,
// Tall
FourByFive,
ThreeByFour,
TwoByThree,
NineBySixteen, // NB: No NineByTwentyOne ?
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct NanoBananaProMultiFunctionImageGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,50 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const GEMINI_25_FLASH_EDIT_IMAGE_PATH: &str = "/v1/generate/image/gemini_25_flash";
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Gemini25FlashTextToImageImageRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt to generate the image from.
pub prompt: Option<String>,
// TODO: OneOf for image_urls or image_media_tokens
/// Image media tokens to include in the editing context.
pub image_media_tokens: Option<Vec<MediaFileToken>>,
/// Number of images to generate. Default is one.
pub num_images: Option<Gemini25FlashTextToImageImageNumImages>,
/// Quality of the image to generate. Default is High.
pub image_quality: Option<Gemini25FlashTextToImageImageImageQuality>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Gemini25FlashTextToImageImageNumImages {
One, // Default
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Gemini25FlashTextToImageImageImageQuality {
Auto,
Low,
Medium,
High, // Default
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Gemini25FlashTextToImageImageResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,64 +0,0 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const KLING_2P5_TURBO_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH: &str = "/v1/generate/video/multi_function/kling_2p5_turbo_pro";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling2p5TurboProMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for text-to-video.
pub negative_prompt: Option<String>,
/// Optional.
/// Only for image-to-video
/// Source of the starting frame
/// If present, we're doing image-to-video
/// If absent, we're doing text-to-video
pub start_frame_image_media_token: Option<MediaFileToken>,
/// Optional.
/// Only for image-to-video
/// Source of the ending frame (if desired)
pub end_frame_image_media_token: Option<MediaFileToken>,
/// Optional
/// Duration of the video
pub duration: Option<Kling2p5TurboProMultiFunctionVideoGenDuration>,
/// Optional.
/// Only for text-to-video
pub aspect_ratio: Option<Kling2p5TurboProMultiFunctionVideoGenAspectRatio>,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling2p5TurboProMultiFunctionVideoGenDuration {
FiveSeconds,
TenSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling2p5TurboProMultiFunctionVideoGenAspectRatio {
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling2p5TurboProMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,68 +0,0 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const KLING_2P6_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH: &str = "/v1/generate/video/multi_function/kling_2p6_pro";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling2p6ProMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for text-to-video.
pub negative_prompt: Option<String>,
/// Optional.
/// Only for image-to-video
/// Source of the starting frame
/// If present, we're doing image-to-video
/// If absent, we're doing text-to-video
pub start_frame_image_media_token: Option<MediaFileToken>,
// /// Optional.
// /// Only for image-to-video
// /// Source of the ending frame (if desired)
// pub end_frame_image_media_token: Option<MediaFileToken>,
/// Optional
/// Duration of the video
pub duration: Option<Kling2p6ProMultiFunctionVideoGenDuration>,
/// Optional
/// Whether to generate audio.
pub generate_audio: Option<bool>,
/// Optional.
/// Only for text-to-video
pub aspect_ratio: Option<Kling2p6ProMultiFunctionVideoGenAspectRatio>,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling2p6ProMultiFunctionVideoGenDuration {
FiveSeconds,
TenSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling2p6ProMultiFunctionVideoGenAspectRatio {
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling2p6ProMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,6 +0,0 @@
pub mod kling_2_5_turbo_multi_function_video_gen;
pub mod kling_2_6_multi_function_video_gen;
pub mod sora_2_multi_function_video_gen;
pub mod sora_2_pro_multi_function_video_gen;
pub mod veo_3p1_fast_multi_function_video_gen;
pub mod veo_3p1_multi_function_video_gen;
@@ -1,66 +0,0 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const SORA_2_MULTI_FUNCTION_VIDEO_VIDEO_PATH: &str = "/v1/generate/video/multi_function/sora_2";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Sora2MultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for image-to-video
/// Source of the starting frame
/// If present, we're doing image-to-video
/// If absent, we're doing text-to-video
pub image_media_token: Option<MediaFileToken>,
/// Optional.
pub resolution: Option<Sora2MultiFunctionVideoGenResolution>,
/// Optional
/// Duration of the video
/// (this is uniform against all modes)
pub duration: Option<Sora2MultiFunctionVideoGenDuration>,
/// Optional.
pub aspect_ratio: Option<Sora2MultiFunctionVideoGenAspectRatio>,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Sora2MultiFunctionVideoGenResolution {
Auto,
SevenTwentyP,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Sora2MultiFunctionVideoGenDuration {
FourSeconds,
EightSeconds,
TwelveSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Sora2MultiFunctionVideoGenAspectRatio {
Auto,
NineBySixteen,
SixteenByNine,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Sora2MultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,67 +0,0 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const SORA_2_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH: &str = "/v1/generate/video/multi_function/sora_2_pro";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Sora2ProMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for image-to-video
/// Source of the starting frame
/// If present, we're doing image-to-video
/// If absent, we're doing text-to-video
pub image_media_token: Option<MediaFileToken>,
/// Optional.
pub resolution: Option<Sora2ProMultiFunctionVideoGenResolution>,
/// Optional
/// Duration of the video
/// (this is uniform against all modes)
pub duration: Option<Sora2ProMultiFunctionVideoGenDuration>,
/// Optional.
pub aspect_ratio: Option<Sora2ProMultiFunctionVideoGenAspectRatio>,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Sora2ProMultiFunctionVideoGenResolution {
Auto,
SevenTwentyP,
TenEightyP,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Sora2ProMultiFunctionVideoGenDuration {
FourSeconds,
EightSeconds,
TwelveSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Sora2ProMultiFunctionVideoGenAspectRatio {
Auto,
NineBySixteen,
SixteenByNine,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Sora2ProMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,90 +0,0 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const VEO_3P1_FAST_MULTI_FUNCTION_VIDEO_VIDEO_PATH: &str = "/v1/generate/video/multi_function/veo_3p1_fast";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Veo3p1FastMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for text-to-video.
pub negative_prompt: Option<String>,
/// Optional.
/// Only for image-to-video
/// Source of the starting frame
/// If present, we're doing image-to-video
/// If absent, we're doing text-to-video
pub start_frame_image_media_token: Option<MediaFileToken>,
/// Optional.
/// Only for image-to-video
/// Source of the ending frame (if desired)
pub end_frame_image_media_token: Option<MediaFileToken>,
/// Optional
/// Duration of the video
/// (this is uniform against all modes)
pub duration: Option<Veo3p1FastMultiFunctionVideoGenDuration>,
/// Optional.
pub aspect_ratio: Option<Veo3p1FastMultiFunctionVideoGenAspectRatio>,
/// Optional.
pub resolution: Option<Veo3p1FastMultiFunctionVideoGenResolution>,
/// Optional
/// Whether to generate audio.
pub generate_audio: Option<bool>,
/// Optional
/// Only for text-to-video
pub enhance_prompt: Option<bool>,
/// Optional
/// Only for text-to-video
pub seed: Option<i64>,
/// Optional
/// Only for text-to-video
pub auto_fix: Option<bool>,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Veo3p1FastMultiFunctionVideoGenDuration {
FourSeconds,
SixSeconds,
EightSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Veo3p1FastMultiFunctionVideoGenAspectRatio {
Auto,
SixteenByNine,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Veo3p1FastMultiFunctionVideoGenResolution {
SevenTwentyP,
TenEightyP,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Veo3p1FastMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,90 +0,0 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const VEO_3P1_MULTI_FUNCTION_VIDEO_VIDEO_PATH: &str = "/v1/generate/video/multi_function/veo_3p1";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Veo3p1MultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for text-to-video.
pub negative_prompt: Option<String>,
/// Optional.
/// Only for image-to-video
/// Source of the starting frame
/// If present, we're doing image-to-video
/// If absent, we're doing text-to-video
pub start_frame_image_media_token: Option<MediaFileToken>,
/// Optional.
/// Only for image-to-video
/// Source of the ending frame (if desired)
pub end_frame_image_media_token: Option<MediaFileToken>,
/// Optional
/// Duration of the video
/// (this is uniform against all modes)
pub duration: Option<Veo3p1MultiFunctionVideoGenDuration>,
/// Optional.
pub aspect_ratio: Option<Veo3p1MultiFunctionVideoGenAspectRatio>,
/// Optional.
pub resolution: Option<Veo3p1MultiFunctionVideoGenResolution>,
/// Optional
/// Whether to generate audio.
pub generate_audio: Option<bool>,
/// Optional
/// Only for text-to-video
pub enhance_prompt: Option<bool>,
/// Optional
/// Only for text-to-video
pub seed: Option<i64>,
/// Optional
/// Only for text-to-video
pub auto_fix: Option<bool>,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Veo3p1MultiFunctionVideoGenDuration {
FourSeconds,
SixSeconds,
EightSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Veo3p1MultiFunctionVideoGenAspectRatio {
Auto,
SixteenByNine,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Veo3p1MultiFunctionVideoGenResolution {
SevenTwentyP,
TenEightyP,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Veo3p1MultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,19 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use utoipa::ToSchema;
use tokens::tokens::media_files::MediaFileToken;
#[derive(Serialize, Deserialize, ToSchema)]
pub struct DeleteMediaFileRequest {
pub set_delete: bool,
/// NB: this is only to disambiguate when a user is both a mod and an author.
pub as_mod: Option<bool>,
}
/// For the URL PathInfo
#[derive(Serialize, Deserialize, ToSchema)]
pub struct DeleteMediaFilePathInfo {
pub token: MediaFileToken,
}
@@ -1,12 +0,0 @@
use crate::common::responses::media_links::MediaLinks;
/// Get the thumbnail template for either images or videos.
pub fn media_links_to_thumbnail_template(links: &MediaLinks) -> Option<&str> {
// NB: We only populate video previews for video tasks.
if let Some(video) = links.maybe_video_previews.as_ref() {
return Some(&video.animated_thumbnail_template);
}
// Image case - use the image thumbnail template if it exists.
links.maybe_thumbnail_template.as_deref()
}
@@ -1 +0,0 @@
pub mod media_links_to_thumbnail_template;
@@ -1 +0,0 @@
pub mod remove_image_background;
@@ -1,5 +0,0 @@
pub mod bg_removal;
pub mod edit;
pub mod inpaint;
pub mod multi_function;
pub mod text;
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_v4_multi_function_image_gen::{BytedanceSeedreamV4MultiFunctionImageGenRequest, BytedanceSeedreamV4MultiFunctionImageGenResponse, BYTEDANCE_SEEDREAM_V4_MULTI_FUNCTION_IMAGE_GEN_PATH};
pub async fn bytedance_seedream_v4_multi_function_image_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: BytedanceSeedreamV4MultiFunctionImageGenRequest,
) -> Result<BytedanceSeedreamV4MultiFunctionImageGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
BYTEDANCE_SEEDREAM_V4_MULTI_FUNCTION_IMAGE_GEN_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_v4p5_multi_function_image_gen::{BytedanceSeedreamV4p5MultiFunctionImageGenRequest, BytedanceSeedreamV4p5MultiFunctionImageGenResponse, BYTEDANCE_SEEDREAM_V4P5_MULTI_FUNCTION_IMAGE_GEN_PATH};
pub async fn bytedance_seedream_v4p5_multi_function_image_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: BytedanceSeedreamV4p5MultiFunctionImageGenRequest,
) -> Result<BytedanceSeedreamV4p5MultiFunctionImageGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
BYTEDANCE_SEEDREAM_V4P5_MULTI_FUNCTION_IMAGE_GEN_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::multi_function::gpt_image_1p5_multi_function_image_gen::{GptImage1p5MultiFunctionImageGenRequest, GptImage1p5MultiFunctionImageGenResponse, GPT_IMAGE_1P5_MULTI_FUNCTION_IMAGE_GEN_PATH};
pub async fn gpt_image_1p5_multi_function_image_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: GptImage1p5MultiFunctionImageGenRequest,
) -> Result<GptImage1p5MultiFunctionImageGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
GPT_IMAGE_1P5_MULTI_FUNCTION_IMAGE_GEN_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,5 +0,0 @@
pub mod bytedance_seedream_v4_multi_function_image_gen_image;
pub mod bytedance_seedream_v4p5_multi_function_image_gen_image;
pub mod gpt_image_1p5_multi_function_image_gen_image;
pub mod nano_banana_multi_function_image_gen_image;
pub mod nano_banana_pro_multi_function_image_gen_image;
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::multi_function::nano_banana_multi_function_image_gen::{NanoBananaMultiFunctionImageGenRequest, NanoBananaMultiFunctionImageGenResponse, NANO_BANANA_MULTI_FUNCTION_IMAGE_GEN_PATH};
pub async fn nano_banana_multi_function_image_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: NanoBananaMultiFunctionImageGenRequest,
) -> Result<NanoBananaMultiFunctionImageGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
NANO_BANANA_MULTI_FUNCTION_IMAGE_GEN_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::multi_function::nano_banana_pro_multi_function_image_gen::{NanoBananaProMultiFunctionImageGenRequest, NanoBananaProMultiFunctionImageGenResponse, NANO_BANANA_PRO_MULTI_FUNCTION_IMAGE_GEN_PATH};
pub async fn nano_banana_pro_multi_function_image_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: NanoBananaProMultiFunctionImageGenRequest,
) -> Result<NanoBananaProMultiFunctionImageGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
NANO_BANANA_PRO_MULTI_FUNCTION_IMAGE_GEN_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::kling_2_5_turbo_multi_function_video_gen::{Kling2p5TurboProMultiFunctionVideoGenRequest, Kling2p5TurboProMultiFunctionVideoGenResponse, KLING_2P5_TURBO_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH};
pub async fn kling_2p5_turbo_pro_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Kling2p5TurboProMultiFunctionVideoGenRequest,
) -> Result<Kling2p5TurboProMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
KLING_2P5_TURBO_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::kling_2_6_multi_function_video_gen::{Kling2p6ProMultiFunctionVideoGenRequest, Kling2p6ProMultiFunctionVideoGenResponse, KLING_2P6_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH};
pub async fn kling_2p6_pro_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Kling2p6ProMultiFunctionVideoGenRequest,
) -> Result<Kling2p6ProMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
KLING_2P6_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,6 +0,0 @@
pub mod kling_2p5_turbo_pro_multi_function_video_gen;
pub mod kling_2p6_pro_multi_function_video_gen;
pub mod sora_2_multi_function_video_gen;
pub mod sora_2_pro_multi_function_video_gen;
pub mod veo_3p1_fast_multi_function_video_gen;
pub mod veo_3p1_multi_function_video_gen;
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::sora_2_multi_function_video_gen::{Sora2MultiFunctionVideoGenRequest, Sora2MultiFunctionVideoGenResponse, SORA_2_MULTI_FUNCTION_VIDEO_VIDEO_PATH};
pub async fn sora_2_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Sora2MultiFunctionVideoGenRequest,
) -> Result<Sora2MultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
SORA_2_MULTI_FUNCTION_VIDEO_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::sora_2_pro_multi_function_video_gen::{Sora2ProMultiFunctionVideoGenRequest, Sora2ProMultiFunctionVideoGenResponse, SORA_2_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH};
pub async fn sora_2_pro_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Sora2ProMultiFunctionVideoGenRequest,
) -> Result<Sora2ProMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
SORA_2_PRO_MULTI_FUNCTION_VIDEO_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::veo_3p1_fast_multi_function_video_gen::{Veo3p1FastMultiFunctionVideoGenRequest, Veo3p1FastMultiFunctionVideoGenResponse, VEO_3P1_FAST_MULTI_FUNCTION_VIDEO_VIDEO_PATH};
pub async fn veo_3p1_fast_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Veo3p1FastMultiFunctionVideoGenRequest,
) -> Result<Veo3p1FastMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
VEO_3P1_FAST_MULTI_FUNCTION_VIDEO_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,18 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::veo_3p1_multi_function_video_gen::{Veo3p1MultiFunctionVideoGenRequest, Veo3p1MultiFunctionVideoGenResponse, VEO_3P1_MULTI_FUNCTION_VIDEO_VIDEO_PATH};
pub async fn veo_3p1_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Veo3p1MultiFunctionVideoGenRequest,
) -> Result<Veo3p1MultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
VEO_3P1_MULTI_FUNCTION_VIDEO_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,37 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_delete_request::basic_json_delete_request;
use artcraft_api_defs::common::responses::simple_generic_json_success::SimpleGenericJsonSuccess;
use artcraft_api_defs::media_file::delete_media_file::DeleteMediaFileRequest;
use artcraft_api_defs::subscriptions::get_session_subscription::GetSessionSubscriptionResponse;
use enums::common::payments_namespace::PaymentsNamespace;
use log::debug;
use tokens::tokens::media_files::MediaFileToken;
pub async fn delete_media_file(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
media_file_token: &MediaFileToken,
) -> Result<SimpleGenericJsonSuccess, StorytellerError> {
let url_path = get_url_path(media_file_token);
debug!("Requesting {:?}", &url_path);
// NB: We probably don't need to expose these options from FakeYou anymore.
let request = DeleteMediaFileRequest {
set_delete: true,
as_mod: None,
};
Ok(basic_json_delete_request(
api_host,
&url_path,
maybe_creds,
request,
).await?)
}
fn get_url_path(token: &MediaFileToken) -> String {
format!("/v1/media_files/file/{}", token.as_str())
}
@@ -1,143 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::api_error::ApiError;
use crate::error::client_error::ClientError;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::constants::{APPLICATION_JSON, USER_AGENT};
use crate::utils::filter_bad_response::filter_bad_response;
use crate::utils::http_get_anonymous::http_get_anonymous;
use chrono::{DateTime, Utc};
use enums::by_table::media_files::media_file_animation_type::MediaFileAnimationType;
use enums::by_table::media_files::media_file_class::MediaFileClass;
use enums::by_table::media_files::media_file_engine_category::MediaFileEngineCategory;
use enums::by_table::media_files::media_file_type::MediaFileType;
use enums::by_table::model_weights::weights_category::WeightsCategory;
use enums::common::generation_provider::GenerationProvider;
use enums::common::visibility::Visibility;
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
use enums_public::by_table::model_weights::public_weights_types::PublicWeightsType;
use idempotency::uuid::generate_random_uuid;
use log::debug;
use reqwest::multipart::Form;
use reqwest::Client;
use serde_derive::{Deserialize, Serialize};
use std::fs::File;
use std::io::Read;
use std::path::Path;
use tokens::tokens::batch_generations::BatchGenerationToken;
use tokens::tokens::media_files::MediaFileToken;
use tokens::tokens::model_weights::ModelWeightToken;
use tokens::tokens::prompts::PromptToken;
use uuid::uuid;
pub struct LegacyUploadMediaFileFromFileArgs<'a, P: AsRef<Path>> {
pub api_host: &'a ApiHost,
pub maybe_creds: Option<&'a StorytellerCredentialSet>,
// NB: Path needs to be owned for the request.
pub path: P,
// /// If true, we should hide the image from the user's gallery.
// pub is_intermediate_system_file: bool,
// /// If provided, this is the prompt that this image is associated with.
// /// NOTE: Cannot set `is_intermediate_system_file = true` if this is set.
// pub maybe_prompt_token: Option<&'a PromptToken>,
// /// If provided, this is the service provider that created the image.
// /// NOTE: Cannot set `is_intermediate_system_file = true` if this is set.
// pub maybe_generation_provider: Option<GenerationProvider>,
// /// If provided, this groups the file into a batch
// /// TODO: This shouldn't be set clientside without the backend generating the token
// /// and cryptographically securing it. But we need to go fast here.
// pub maybe_batch_token: Option<&'a BatchGenerationToken>,
}
/// Upload using the legacy endpoint (spz, etc.)
pub async fn legacy_upload_media_file_from_file<P: AsRef<Path>>(
args: LegacyUploadMediaFileFromFileArgs<'_, P>,
) -> Result<UploadImageMediaFileSuccessResponse, StorytellerError> {
validate_args(&args)?;
let url = get_route(args.api_host);
debug!("Requesting {:?}", &url);
//let mut file = File::open(path)?;
let client = Client::builder()
.gzip(true)
.build()
.map_err(|err| StorytellerError::Client(ClientError::from(err)))?;
let mut form = Form::new()
.text("uuid_idempotency_token", generate_random_uuid())
.file("file", args.path)
.await
.map_err(|err| StorytellerError::Client(ClientError::from(err)))?;
//if args.is_intermediate_system_file {
// form = form.text("is_intermediate_system_file", "true");
//}
//if let Some(prompt_token) = &args.maybe_prompt_token {
// form = form.text("maybe_prompt_token", prompt_token.to_string());
//}
//if let Some(batch_token) = &args.maybe_batch_token {
// form = form.text("maybe_batch_token", batch_token.to_string());
//}
let mut request_builder = client.post(url)
.header("User-Agent", USER_AGENT)
.header("Accept", APPLICATION_JSON);
if let Some(creds) = args.maybe_creds {
if let Some(header) = &creds.maybe_as_cookie_header() {
request_builder = request_builder.header("Cookie", header);
}
}
let response = request_builder
.multipart(form)
.send()
.await
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
let response = filter_bad_response(response).await?;
let response_body = &response.text().await
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
let media_file = serde_json::from_str(&response_body)
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
Ok(media_file)
}
fn get_route(api_host: &ApiHost) -> String {
let api_hostname_and_scheme = api_host.to_api_hostname_and_scheme();
format!("{}/v1/media_files/upload", api_hostname_and_scheme)
}
// TODO(bt,2025-04-22): Share API definitions between client and server in common crate.
#[derive(Deserialize, Debug)]
pub struct UploadImageMediaFileSuccessResponse {
pub success: bool,
pub media_file_token: MediaFileToken,
}
fn validate_args<P: AsRef<Path>>(
args: &LegacyUploadMediaFileFromFileArgs<'_, P>,
) -> Result<(), StorytellerError> {
// if args.is_intermediate_system_file && args.maybe_prompt_token.is_some() {
// return Err(StorytellerError::Client(ClientError::InvalidPreflightRequest(
// "Cannot set `is_intermediate_system_file` to true if `maybe_prompt_token` is provided."
// .to_string())));
// }
Ok(())
}
@@ -1,70 +0,0 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::api_error::ApiError;
use crate::error::client_error::ClientError;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::constants::{APPLICATION_JSON, USER_AGENT};
use crate::utils::filter_bad_response::filter_bad_response;
use log::{debug, info};
use reqwest::Client;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
pub async fn basic_json_delete_request<Req: Serialize, Res: DeserializeOwned>(
api_host: &ApiHost,
route_path: &str,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Req,
) -> Result<Res, StorytellerError> {
let url = get_route(api_host, route_path);
info!("DELETE {:?}", &url);
let client = Client::builder()
.gzip(true)
.build()
.map_err(|err| StorytellerError::Client(ClientError::from(err)))?;
let mut request_builder = client.delete(url)
.header("User-Agent", USER_AGENT)
.header("Accept", APPLICATION_JSON)
.header("Content-Type", APPLICATION_JSON);
if let Some(creds) = maybe_creds {
if let Some(header) = &creds.maybe_as_cookie_header() {
request_builder = request_builder.header("Cookie", header);
}
}
let request_body = serde_json::to_string(&request)
.map_err(|err| StorytellerError::Client(ClientError::from(err)))?;
debug!("Request body: {:?}", request_body);
let response = request_builder
.body(request_body)
.send()
.await
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
let response = filter_bad_response(response)
.await
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
let response_body = &response.text()
.await
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
debug!("Response body: {:?}", response_body);
let response = serde_json::from_str(&response_body)
.map_err(|err| StorytellerError::Api(ApiError::from(err)))?;
Ok(response)
}
fn get_route(api_host: &ApiHost, route_path: &str) -> String {
let api_hostname = api_host.to_api_hostname_and_scheme();
format!("{}{}", api_hostname, route_path)
}
@@ -1,9 +0,0 @@
pub (crate) mod basic_json_delete_request;
pub (crate) mod basic_json_get_request;
pub (crate) mod basic_json_post_request;
pub (crate) mod basic_query_string_post_request;
pub (crate) mod filter_bad_response;
pub (crate) mod http_get_anonymous;
pub mod api_host;
pub mod constants;
pub mod status_codes;
@@ -3,5 +3,4 @@ pub mod job_details;
pub mod media_file_cover_image_details;
pub mod media_links;
pub mod simple_entity_stats;
pub mod simple_generic_json_success;
pub mod user_details_light;
@@ -1,6 +1,6 @@
pub mod flux_pro_kontext_max_edit_image;
pub mod gemini_25_flash_edit_image;
pub mod gpt_image_1_edit_image;
pub mod gemini_25_flash_edit_image;
pub mod qwen_edit_image;
pub mod seededit_3_edit_image;
@@ -19,7 +19,6 @@ pub struct GenerateFluxPro11TextToImageRequest {
pub num_images: Option<GenerateFluxPro11TextToImageNumImages>,
}
// TODO(btw,2026-01-01): Fal.ai and Fal.rs client libraries seem to disagree about the options.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GenerateFluxPro11TextToImageAspectRatio {
@@ -23,14 +23,10 @@ pub struct GenerateFluxPro11UltraTextToImageRequest {
#[serde(rename_all = "snake_case")]
pub enum GenerateFluxPro11UltraTextToImageAspectRatio {
Square, // 1:1
LandscapeThreeByTwo, // 3:2
LandscapeFourByThree, // 4:3
LandscapeSixteenByNine, // 16:9
LandscapeTwentyOneByNine, // 21:9
PortraitTwoByThree, // 2:3
PortraitThreeByFour, // 3:4
PortraitNineBySixteen, // 9:16
PortraitNineByTwentyOne, // 9:21
//Custom { width: u32, height: u32 }, // TODO
}
@@ -1,6 +1,8 @@
pub mod gemini_25_flash_text_to_image;
pub mod edit;
pub mod generate_flux_1_dev_text_to_image;
pub mod generate_flux_1_schnell_text_to_image;
pub mod generate_flux_pro_11_text_to_image;
pub mod generate_flux_pro_11_ultra_text_to_image;
pub mod generate_gpt_image_1_text_to_image;
pub mod inpaint;
pub mod remove_image_background;
@@ -21,14 +21,11 @@ pub struct GenerateSeedance10LiteImageToVideoRequest {
/// Optional text prompt.
pub prompt: Option<String>,
/// Optional: resolution of the generated video.
/// Optional: aspect ratio of the generated video.
pub resolution: Option<GenerateSeedance10LiteResolution>,
/// Optional: duration of the generated video.
pub duration: Option<GenerateSeedance10LiteDuration>,
/// Optional: aspect ratio of the generated video.
pub aspect_ratio: Option<GenerateSeedance10LiteAspectRatio>,
pub duration: Option<GenerateSeedance10LiteDuration>,
}
#[derive(Serialize, Deserialize, ToSchema)]
@@ -45,19 +42,6 @@ pub enum GenerateSeedance10LiteDuration {
TenSeconds,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum GenerateSeedance10LiteAspectRatio {
Auto,
TwentyOneByNine,
SixteenByNine,
FourByThree,
Square,
ThreeByFour,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GenerateSeedance10LiteImageToVideoResponse {
pub success: bool,
@@ -5,5 +5,4 @@ pub mod generate_seedance_1_0_lite_image_to_video;
pub mod generate_seedance_1_0_pro_image_to_video;
pub mod generate_veo_2_image_to_video;
pub mod generate_veo_3_fast_image_to_video;
pub mod generate_veo_3_image_to_video;
pub mod multi_function;
pub mod generate_veo_3_image_to_video;
@@ -6,5 +6,4 @@ pub mod jobs;
pub mod media_file;
pub mod prompts;
pub mod stripe_artcraft;
pub mod subscriptions;
pub mod utils;
pub mod subscriptions;
@@ -1,2 +1 @@
pub mod delete_media_file;
pub mod list_batch_generated_media_files;

Some files were not shown because too many files have changed in this diff Show More