mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-21 17:28:24 -04:00
Compare commits
167
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9b6fbcb5e | ||
|
|
d51c16bd9b | ||
|
|
902e2ab9c0 | ||
|
|
98edfa9836 | ||
|
|
345f68132b | ||
|
|
94cfa98250 | ||
|
|
e170bf9d72 | ||
|
|
5474eaed02 | ||
|
|
43d9b96d5e | ||
|
|
e1447de93a | ||
|
|
8598cde149 | ||
|
|
f33aa409c1 | ||
|
|
5f29cd5f79 | ||
|
|
6c0b32aa44 | ||
|
|
6f9b637da0 | ||
|
|
40dda6e5cd | ||
|
|
06fca6b54f | ||
|
|
7a04b131f7 | ||
|
|
427269feec | ||
|
|
2e2c433ffe | ||
|
|
c8228c5073 | ||
|
|
f89ce374cd | ||
|
|
affcbac10f | ||
|
|
cbf91709dc | ||
|
|
eea31d3f94 | ||
|
|
f8f3434d70 | ||
|
|
c6f3fd13b8 | ||
|
|
fd8f9d037f | ||
|
|
9fa4080851 | ||
|
|
73b16274f8 | ||
|
|
835c9ef6b0 | ||
|
|
11bf5949fe | ||
|
|
5415109a35 | ||
|
|
cb8c3b426f | ||
|
|
25ac4213af | ||
|
|
2a316f6cc7 | ||
|
|
2a1ae24917 | ||
|
|
68ff2b484b | ||
|
|
19258c257c | ||
|
|
4cd3bd8095 | ||
|
|
e7dc0abb36 | ||
|
|
a36fe72832 | ||
|
|
4eeb915bef | ||
|
|
19079ab7ec | ||
|
|
9ffcfe83c2 | ||
|
|
3404935720 | ||
|
|
b490b92833 | ||
|
|
f151837c2b | ||
|
|
86a6d16441 | ||
|
|
b9397fb809 | ||
|
|
5688d8cef7 | ||
|
|
6815040cb1 | ||
|
|
754a4da019 | ||
|
|
3a600fcb9f | ||
|
|
510589b758 | ||
|
|
7ee5a6aa9a | ||
|
|
f5cd65be9c | ||
|
|
fba1a65e95 | ||
|
|
a1d08460db | ||
|
|
ba538142e4 | ||
|
|
99fd390bc5 | ||
|
|
cd283bf8de | ||
|
|
0c6021e95c | ||
|
|
859d295014 | ||
|
|
e116df736f | ||
|
|
9bb4a78111 | ||
|
|
edb0330cec | ||
|
|
146f152732 | ||
|
|
32b939a67e | ||
|
|
866a409ff1 | ||
|
|
92731d87ef | ||
|
|
f574d66897 | ||
|
|
21a30bde2d | ||
|
|
6a1eeaffb4 | ||
|
|
00065f120e | ||
|
|
e30dc03466 | ||
|
|
029789ac78 | ||
|
|
7b5550c546 | ||
|
|
0f0bd4c907 | ||
|
|
63f77a4b11 | ||
|
|
5ba6a3e226 | ||
|
|
7683fe34b7 | ||
|
|
1d41fa8174 | ||
|
|
8fe15839b0 | ||
|
|
1eada337f9 | ||
|
|
016f5107e0 | ||
|
|
224ce3f80b | ||
|
|
73a6d0494b | ||
|
|
0a5f220a7d | ||
|
|
d852d24226 | ||
|
|
e7da946e2d | ||
|
|
ea80dab67b | ||
|
|
957bb7ff2f | ||
|
|
2f41f345a2 | ||
|
|
53225932fb | ||
|
|
0c353f2a8c | ||
|
|
6036be1e01 | ||
|
|
197e91d4c6 | ||
|
|
5ddd23a8ff | ||
|
|
31eb00cfa7 | ||
|
|
7d6f262ffe | ||
|
|
33162e4337 | ||
|
|
5afb1db285 | ||
|
|
a511e0e0a4 | ||
|
|
0598aadaa1 | ||
|
|
06c6ff4b36 | ||
|
|
5bc759e511 | ||
|
|
02eafa96cc | ||
|
|
706bdb8d83 | ||
|
|
57534c7a77 | ||
|
|
2228a01466 | ||
|
|
262d931c3d | ||
|
|
a7826f8be3 | ||
|
|
dc0e59b8ce | ||
|
|
e1f3458c54 | ||
|
|
e385b3c6c3 | ||
|
|
dbedb25930 | ||
|
|
952d1e936c | ||
|
|
88799a482d | ||
|
|
851aba7e06 | ||
|
|
8ff9323ae6 | ||
|
|
50b085d450 | ||
|
|
1b70ee7394 | ||
|
|
1c3a176705 | ||
|
|
70c305f78d | ||
|
|
1c3178d073 | ||
|
|
1243e755fe | ||
|
|
d551e48a23 | ||
|
|
5cb608fad6 | ||
|
|
d5ae28ca4c | ||
|
|
8313558795 | ||
|
|
95173e032f | ||
|
|
b0f6551623 | ||
|
|
8f2a03e21e | ||
|
|
5c3760f9ec | ||
|
|
d6c1eaae5d | ||
|
|
d6abe9fb88 | ||
|
|
1e758b1b6c | ||
|
|
cd40edb5f9 | ||
|
|
3838cc3f21 | ||
|
|
0fec772d9a | ||
|
|
1afe2ac26f | ||
|
|
5eef6c0161 | ||
|
|
6c6f7f054d | ||
|
|
ba3d46607b | ||
|
|
12bf504d6f | ||
|
|
026c2bf827 | ||
|
|
d20854f75d | ||
|
|
7c9396aa65 | ||
|
|
90810231da | ||
|
|
e9613c6b4a | ||
|
|
cb2eb39183 | ||
|
|
7a100bd461 | ||
|
|
10c35381fa | ||
|
|
24c8353482 | ||
|
|
eb0db3d67d | ||
|
|
2d44b92bfc | ||
|
|
8c36a7f98a | ||
|
|
a174730bf0 | ||
|
|
96ffeadbe0 | ||
|
|
bd93cd4f1f | ||
|
|
39ad16e856 | ||
|
|
64d589521a | ||
|
|
8c0529be0b | ||
|
|
f198d5e90c | ||
|
|
a7f4a6eda4 | ||
|
|
450c73a29d |
@@ -1,6 +1,7 @@
|
||||
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
|
||||
|
||||
|
||||
@@ -200,10 +200,10 @@ jobs:
|
||||
|
||||
# Use npx to ensure we use the local nx version
|
||||
echo "Building with npx nx..."
|
||||
npx nx run editor3d:build
|
||||
npx nx run artcraft:build
|
||||
|
||||
echo "Checking build output..."
|
||||
ls -la apps/editor3d/dist/ | head -10
|
||||
ls -la apps/artcraft/dist/ | head -10
|
||||
|
||||
# Update Tauri config to skip the build (since we already built)
|
||||
cd ${{ github.workspace }}/crates/desktop/artcraft
|
||||
|
||||
@@ -75,10 +75,10 @@ jobs:
|
||||
|
||||
# Use npx to ensure we use the local nx version
|
||||
echo "Building with npx nx..."
|
||||
npx nx run editor3d:build
|
||||
npx nx run artcraft:build
|
||||
|
||||
echo "Checking build output..."
|
||||
dir apps/editor3d/dist/ | Select-Object -First 10
|
||||
dir apps/artcraft/dist/ | Select-Object -First 10
|
||||
|
||||
# Update Tauri config to skip the build (since we already built)
|
||||
cd ${{ github.workspace }}/crates/desktop/artcraft
|
||||
@@ -104,4 +104,4 @@ jobs:
|
||||
releaseBody: "Windows build - See the assets to download this version and install."
|
||||
releaseDraft: true
|
||||
prerelease: false
|
||||
args: ${{ matrix.args }}
|
||||
args: ${{ matrix.args }}
|
||||
|
||||
@@ -45,6 +45,9 @@ crates/lib/sqlite_queries/target/
|
||||
# Javascript build directories
|
||||
node_modules/
|
||||
|
||||
# Frontend build outputs
|
||||
frontend/apps/artcraft/bundle-report.html
|
||||
|
||||
# Vim noise
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n UPDATE tasks\n SET task_status = \"cancelled_by_user\"\n WHERE task_status NOT IN (\n \"complete_success\",\n \"complete_failure\",\n \"dead\",\n \"cancelled_by_user\",\n \"cancelled_by_provider\",\n \"cancelled_by_us\"\n )\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 0
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "30272128d83543d9fbfca930b7cdd4af30adfb4d90f2de044463a111c6340495"
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n UPDATE tasks\n SET is_dismissed_by_user = 1\n WHERE is_dismissed_by_user != 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 0
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "f83018ec5493982659a56576296914f937bb4e75db3a522eb4bda486d5caa402"
|
||||
}
|
||||
Generated
+965
-419
File diff suppressed because it is too large
Load Diff
+34
-6
@@ -6,17 +6,19 @@ resolver = "2"
|
||||
members = [
|
||||
# API clients for external services
|
||||
# These might be custom implementations or wrappers over other client libraries.
|
||||
"crates/api_clients/artcraft_api_defs", # TODO: api_clients/{artcraft}/{api_defs,client}
|
||||
"crates/api_clients/artcraft/artcraft_api_defs", # TODO: api_clients/{artcraft}/{api_defs,client}
|
||||
"crates/api_clients/artcraft/storyteller_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",
|
||||
@@ -43,6 +45,7 @@ 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",
|
||||
@@ -65,6 +68,7 @@ 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",
|
||||
@@ -84,6 +88,7 @@ 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",
|
||||
@@ -181,10 +186,11 @@ 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_api_defs" }
|
||||
artcraft_api_defs = { path = "crates/api_clients/artcraft/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" }
|
||||
@@ -194,6 +200,8 @@ 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" }
|
||||
@@ -205,12 +213,14 @@ 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/storyteller_client" }
|
||||
storyteller_client = { path = "crates/api_clients/artcraft/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
|
||||
@@ -227,22 +237,26 @@ 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.11.1"
|
||||
reqwest = { version = "0.12.22", features = ["json", "cookies"] }
|
||||
regex = "1.12.2"
|
||||
reqwest = { version = "0.12.23", default-features = false, features = [ "charset", "http2", "system-proxy", "json", "cookies", "rustls-tls" ] }
|
||||
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"
|
||||
@@ -255,3 +269,17 @@ 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"
|
||||
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
ArtCraft License (WIP)
|
||||
======================
|
||||
|
||||
(**Warning**: This isn't a real lawyery license full of legitimate legalese yet, but we'll take care of that ASAP.)
|
||||
|
||||
ArtCraft is a form of "fair source" software. It's like [free beer](https://en.wiktionary.org/wiki/free_as_in_beer)
|
||||
in that we give you the code, but there are a few small limitations on what you can do with it.
|
||||
|
||||
First, what you *can* do with ArtCraft:
|
||||
|
||||
> 1. You do not have to pay us to use ArtCraft. It's free.
|
||||
>
|
||||
> 2. You can back up, copy, modify, compile, and use the code for your own private personal purposes.
|
||||
>
|
||||
> 3. You can do anything you want with the media you create with ArtCraft. Generated assets are yours.
|
||||
|
||||
What you *can't do* with ArtCraft:
|
||||
|
||||
> 1. You cannot sell the ArtCraft software commercially (eg. as your own software).
|
||||
>
|
||||
> 2. You cannot use the ArtCraft code to develop a competing business or product (eg. selling AI image and video tools).
|
||||
>
|
||||
> 3. You cannot fork ArtCraft and remove ArtCraft community, donation links, or paid model services. We intend to
|
||||
> make money to improve ArtCraft for everyone.
|
||||
>
|
||||
> 4. You cannot use the ArtCraft name, logo, or mascot characters to promote your business without permission.
|
||||
|
||||
This license means you can see what we're doing and not be at risk of having the rug pulled out from under
|
||||
you (eg. if our founders die or our business collapses). It also gives you a really great way to customize the
|
||||
software or lend a hand in reporting (or even fixing) bugs.
|
||||
|
||||
Our desire is to support artists, designers, and filmmakers. We want to help you build your own creative studios
|
||||
and businesses. We want to give you creative software you can use forever.
|
||||
|
||||
ArtCraft is free. We do offer models available through us where you can pay us and support our development, but we also
|
||||
offer the ability for you to use other providers - and we'll keep adding more options so you have maximum flexibility.
|
||||
|
||||
## Our Promise
|
||||
|
||||
- All development and business plans will be communicated openly with the community.
|
||||
|
||||
- Except for minor test scripts or a few small places where we might need to use licensed 3rd party code, all of
|
||||
our engineering efforts will live in a single publicly available monorepo. You can see everything we do and even
|
||||
benefit from using it for personal use. We plan on building a lot more than what you see today, and you'll get
|
||||
all of it.
|
||||
|
||||
- We will not "rug pull" our users. If our business shuts down, gets acquired, or otherwise changes, the tools
|
||||
we create will always continue to function in the same way.
|
||||
|
||||
- If the business ends and our founders quit working in this space, we'll make it so the software transitions
|
||||
to an OSI-approved open source license. (We don't intend to quit!)
|
||||
|
||||
## Why not OSI Open Source?
|
||||
|
||||
Philosophical answer: The OSI is an industry body led by hyperscalers. They poach from open source all the time, yet
|
||||
hyperscaler systems and code (AWS, GCP, YouTube, etc.) remain closed source. The tiniest nuggets are open, but the vast
|
||||
machinery surrounding it - systems, user behaviors, funnels, at-scale moneymakers - is totally closed.
|
||||
|
||||
Practical answer: OSI licenses make it exceptionally challenging to grow big things commercially. And many of
|
||||
the licenses leave room for hyperscalers to reach in and cherrypick pieces for themselves that they can better
|
||||
commercialize than the original authors.
|
||||
|
||||
Then there's completely open source software that doesn't even attempt to be a business.
|
||||
|
||||
We love software like Blender, but (1) we want/need jobs, (2) we want to build something at scale, and (3) this will
|
||||
eventually become much more capital intensive than just writing code. We one day want to train novel models that work
|
||||
directly in conjunction with the user interface.
|
||||
|
||||
If and when we do get to scale, we intend to keep every bit of our work in the open. Available for use, inspection,
|
||||
learning, fitting onto consumer GPU hardware, and more.
|
||||
|
||||
Not having a way to make money is unfortunately what killed Stability.ai. Stability.ai walked so that others could
|
||||
eventually run. (Black Forest Labs, et al.) We're not egotistical enough to count ourselves in that party yet, but we
|
||||
believe in the original Stability.ai ethos and that their model can work with a few tweaks.
|
||||
|
||||
We want to build big and incredible tools the world hasn't seen before. We want to keep them free and entirely source
|
||||
available. You don't have to pay us, but if you do, all of your investment goes right back into the engineering
|
||||
and the tools. We're writing code you can clone and keep.
|
||||
|
||||
## Inspiration
|
||||
|
||||
We took inspiration for this from [Fair Source](https://fair.io/), [Fair Code](https://faircode.io/),
|
||||
the [Defold License](https://defold.com/license/), and Hacker News discussions. The folks at Obsidian
|
||||
have some pretty good thoughts on this as well.
|
||||
|
||||
~ Brandon Thomas
|
||||
@@ -1,50 +1,39 @@
|
||||
storyteller-rust
|
||||
================
|
||||
ArtCraft
|
||||
========
|
||||
ArtCraft is the IDE for interactive AI image and video creation.
|
||||
We turn prompting into *crafting*, so your ideas become a form of tangible expression and computing.
|
||||
This is Adobe Photoshop for everyone, and we're giving away the source code!
|
||||
|
||||
Our Artcraft monorepo, which serves our desktop application, backend infrastructure, and more.
|
||||
|
||||
```
|
||||
."-,.__
|
||||
`. `. ,
|
||||
.--' .._,'"-' `.
|
||||
. .' `'
|
||||
`. / ,'
|
||||
` '--. ,-"'
|
||||
`"` | \
|
||||
-. \, |
|
||||
`--Y.' ___.
|
||||
\ L._, \
|
||||
_., `. < <\ _
|
||||
,' ' `, `. | \ ( `
|
||||
../, `. ` | .\`. \ \_
|
||||
,' ,.. . _.,' ||\l ) '".
|
||||
, ,' \ ,'.-.`-._,' | . _._`.
|
||||
,' / \ \ `' ' `--/ | \ / / ..\
|
||||
.' / \ . |\__ - _ ,'` ` / / `.`.
|
||||
| ' .. `-...-" | `-' / / . `.
|
||||
| / |L__ | | / / `. `.
|
||||
, / . . | | / / ` `
|
||||
/ / ,. ,`._ `-_ | | _ ,-' / ` \
|
||||
/ . \"`_/. `-_ \_,. ,' +-' `-' _, ..,-. \`.
|
||||
. ' .-f ,' ` '. \__.---' _ .' ' \ \
|
||||
' / `.' l .' / \.. ,_|/ `. ,'` L`
|
||||
|' _.-""` `. \ _,' ` \ `.___`.'"`-. , | | | \
|
||||
|| ,' `. `. ' _,...._ ` | `/ ' | ' .|
|
||||
|| ,' `. ;.,.---' ,' `. `.. `-' .-' /_ .' ;_ ||
|
||||
|| ' V / / ` | ` ,' ,' '. ! `. ||
|
||||
||/ _,-------7 ' . | `-' l / `||
|
||||
. | ,' .- ,' || | .-. `. .' ||
|
||||
`' ,' `".' | | `. '. -.' `'
|
||||
/ ,' | |,' \-.._,.'/'
|
||||
. / . . \ .''
|
||||
.`. | `. / :_,'.'
|
||||
\ `...\ _ ,'-. .' /_.-' S T O R Y T E L L E R
|
||||
`-.__ `, `' . _.>----''. _ __ / Turning memes into dreams
|
||||
.' /"' | "' '_
|
||||
/_|.-'\ ,". '.'`__'-( \
|
||||
/ ,"'"\,' `/ `-.|"
|
||||
```
|
||||
Test 1
|
||||
|
||||
<p align="center" width="100%">
|
||||
<video src="frontend/apps/artcraft/app/public/resources/videos/artcraft-intro.mp4" width="100%" loop controls></video>
|
||||
</p>
|
||||
|
||||
Test 2
|
||||
|
||||
<p align="center" width="100%">
|
||||
<video src="https://raw.githubusercontent.com/storytold/storyteller-rust/refs/heads/main/frontend/apps/artcraft/app/public/resources/videos/artcraft-intro.mp4" width="100%" loop controls></video>
|
||||
</p>
|
||||
|
||||
Test 3
|
||||
|
||||
|
||||
<video src="https://raw.githubusercontent.com/storytold/github-media/refs/heads/main/artcraft-intro.mp4" />
|
||||
|
||||
Test 4
|
||||
|
||||
<p align="center" width="100%">
|
||||
<video src="https://raw.githubusercontent.com/storytold/github-media/refs/heads/main/artcraft-intro.mp4" width="80%" controls></video>
|
||||
</p>
|
||||
|
||||
|
||||
Gif Test
|
||||
|
||||
[](https://youtu.be/vt5fpE0bzSY)
|
||||
|
||||
- [developer documentation](./_docs)
|
||||
- [server API reference](https://storyteller-docs.netlify.app/)
|
||||
- [tools, scripts, misc](./script)
|
||||
- [license](./LICENSE.md)
|
||||
- [roadmap](./ROADMAP.md)
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
ArtCraft Roadmap
|
||||
================
|
||||
|
||||
## 2026 Goals (non-exhaustive)
|
||||
|
||||
- Make ArtCraft better and more useful than model aggregation websites (our #1 goal).
|
||||
We don't dislike those websites; we just set a high standard for ourselves.
|
||||
|
||||
- Build the best "tangible" computing surfaces where you can mold scenes and videos like
|
||||
clay and direct them with precision and clarity.
|
||||
|
||||
- Add every model and provider into ArtCraft so you can build your own crafting IDE.
|
||||
Nothing will be left out.
|
||||
|
||||
- Build purpose-specific image models, eg. for relighting scenes and reposing characters
|
||||
and props.
|
||||
|
||||
- Build our content studio. Make lots of narrative shorts and at least one
|
||||
feature-length AI film in 2026. Theatrical distribution, but also lots of social
|
||||
media content. (We are creators, and we want to employ more creators!)
|
||||
|
||||
- Architecture: remove dependence on ArtCraft hosted services.
|
||||
|
||||
- Architecture: more Rust, more speed.
|
||||
|
||||
- Community: build a safe community free of "anti-AI" trolls. A community of AI filmmakers
|
||||
and creators
|
||||
|
||||
## Loftier Goals
|
||||
|
||||
- Build an *Open* OpenAI / Google / Anthropic. Open models, open platforms, open hardware.
|
||||
Why? Because the future could be bleak without it. How, you might ask? Get in touch if
|
||||
you're curious.
|
||||
|
||||
- Don't Be Evil (tm)
|
||||
@@ -0,0 +1,20 @@
|
||||
-- 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,6 +9,14 @@
|
||||
-- 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.
|
||||
@@ -50,6 +58,32 @@ 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
|
||||
|
||||
@@ -152,6 +152,7 @@ CREATE TABLE media_files (
|
||||
-- * `vmd`
|
||||
-- * `pmx`
|
||||
-- * `csv`
|
||||
-- * `spz` Gaussian splats
|
||||
media_type VARCHAR(16) NOT NULL,
|
||||
|
||||
-- Broad class of media:
|
||||
|
||||
+1
@@ -3,4 +3,5 @@ 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;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
pub struct SimpleGenericJsonSuccess {
|
||||
pub success: bool,
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod remove_image_background;
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
pub mod flux_pro_kontext_max_edit_image;
|
||||
pub mod gpt_image_1_edit_image;
|
||||
pub mod gemini_25_flash_edit_image;
|
||||
pub mod gpt_image_1_edit_image;
|
||||
pub mod qwen_edit_image;
|
||||
pub mod seededit_3_edit_image;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
pub mod bg_removal;
|
||||
pub mod edit;
|
||||
pub mod inpaint;
|
||||
pub mod multi_function;
|
||||
pub mod text;
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
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,
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
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,
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
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,
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
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;
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
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,
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
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,
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
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
@@ -19,6 +19,7 @@ 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 {
|
||||
+4
@@ -23,10 +23,14 @@ 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
-3
@@ -1,8 +1,6 @@
|
||||
pub mod edit;
|
||||
pub mod gemini_25_flash_text_to_image;
|
||||
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;
|
||||
+18
-2
@@ -21,11 +21,14 @@ pub struct GenerateSeedance10LiteImageToVideoRequest {
|
||||
/// Optional text prompt.
|
||||
pub prompt: Option<String>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
/// Optional: resolution of the generated video.
|
||||
pub resolution: Option<GenerateSeedance10LiteResolution>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
/// Optional: duration of the generated video.
|
||||
pub duration: Option<GenerateSeedance10LiteDuration>,
|
||||
|
||||
/// Optional: aspect ratio of the generated video.
|
||||
pub aspect_ratio: Option<GenerateSeedance10LiteAspectRatio>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
@@ -42,6 +45,19 @@ 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,
|
||||
+2
-1
@@ -5,4 +5,5 @@ 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 generate_veo_3_image_to_video;
|
||||
pub mod multi_function;
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
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,
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
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,
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
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;
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
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,
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
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,
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
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,
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
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,
|
||||
}
|
||||
+2
-1
@@ -6,4 +6,5 @@ pub mod jobs;
|
||||
pub mod media_file;
|
||||
pub mod prompts;
|
||||
pub mod stripe_artcraft;
|
||||
pub mod subscriptions;
|
||||
pub mod subscriptions;
|
||||
pub mod utils;
|
||||
@@ -0,0 +1,19 @@
|
||||
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
@@ -1 +1,2 @@
|
||||
pub mod delete_media_file;
|
||||
pub mod list_batch_generated_media_files;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
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()
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
pub mod media_links_to_thumbnail_template;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user