mirror of
https://github.com/storytold/artcraft.git
synced 2026-10-22 17:49:30 -04:00
Compare commits
112
Commits
bt-cli-tool
...
bt-rootly
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
398c56d7eb | ||
|
|
ba21368323 | ||
|
|
0750b9fe10 | ||
|
|
05a26b124e | ||
|
|
a394ee5a96 | ||
|
|
c35ea620b3 | ||
|
|
389b1c3d17 | ||
|
|
f9148d3cf6 | ||
|
|
64d66aa9f0 | ||
|
|
82695725cd | ||
|
|
53f9032603 | ||
|
|
69c03045fd | ||
|
|
e82f070d1d | ||
|
|
459960e64f | ||
|
|
d1266b7591 | ||
|
|
4bdb1c89a4 | ||
|
|
4d53d9af18 | ||
|
|
2bc00d7f80 | ||
|
|
f48cb41f21 | ||
|
|
d24508aee9 | ||
|
|
1985d9acd7 | ||
|
|
0f90981f30 | ||
|
|
8d1ca743db | ||
|
|
72403ad4d8 | ||
|
|
8d731f1155 | ||
|
|
516d740e97 | ||
|
|
95eeafd6f0 | ||
|
|
0db5646deb | ||
|
|
ac839e2c39 | ||
|
|
65334e12be | ||
|
|
7e644c3e98 | ||
|
|
bb3fe2df2d | ||
|
|
a92ad2eb3a | ||
|
|
78e7d08f04 | ||
|
|
be18036bf6 | ||
|
|
83a8852cef | ||
|
|
afed8688a5 | ||
|
|
9d380decf9 | ||
|
|
4905cdcd3d | ||
|
|
b709b6e764 | ||
|
|
58d2665f0e | ||
|
|
72bf6738e1 | ||
|
|
1178bb7ebf | ||
|
|
fea20c417c | ||
|
|
5a07903870 | ||
|
|
2063434304 | ||
|
|
b386fd5d88 | ||
|
|
1626dda8b4 | ||
|
|
ebe365703b | ||
|
|
5caa578b86 | ||
|
|
2da5fbcc58 | ||
|
|
588650b1b5 | ||
|
|
761bf832a5 | ||
|
|
df4d46cc9d | ||
|
|
19599e00be | ||
|
|
2f2ac350bc | ||
|
|
bbd0871c04 | ||
|
|
7d20ac3d16 | ||
|
|
f9c1201fc6 | ||
|
|
0ac57a5448 | ||
|
|
b88f5c536b | ||
|
|
7edba0d9d5 | ||
|
|
76ae56a051 | ||
|
|
75a92fe204 | ||
|
|
31c507a404 | ||
|
|
42bb07c110 | ||
|
|
5afa81b57d | ||
|
|
81cadf35b0 | ||
|
|
d4b3579915 | ||
|
|
7cd8c0299b | ||
|
|
87296752a5 | ||
|
|
1416c5cd17 | ||
|
|
de29444626 | ||
|
|
41988a4462 | ||
|
|
4c0c536fb0 | ||
|
|
b15a5d532a | ||
|
|
8ae983ee32 | ||
|
|
279a79e60a | ||
|
|
ebd2a276f9 | ||
|
|
0d2f1cfa2c | ||
|
|
3592111019 | ||
|
|
9d12603d1f | ||
|
|
8902f77a18 | ||
|
|
6d91b5616f | ||
|
|
3783c194e3 | ||
|
|
b7770d5566 | ||
|
|
2fb1eb957b | ||
|
|
9b4ffa7986 | ||
|
|
2dca4884b1 | ||
|
|
1d280ba2e0 | ||
|
|
777758dc16 | ||
|
|
f2cf78514b | ||
|
|
c04586c785 | ||
|
|
fd89d5ab39 | ||
|
|
bbfbc40147 | ||
|
|
76d120916b | ||
|
|
efb33bfe38 | ||
|
|
e7d1d796e1 | ||
|
|
fc81854b99 | ||
|
|
6e9981acc2 | ||
|
|
94637e0d0b | ||
|
|
04b6957dfd | ||
|
|
6a0627a493 | ||
|
|
6e2ed226d8 | ||
|
|
0c20a10a78 | ||
|
|
92bba52502 | ||
|
|
6d3ec8bfee | ||
|
|
c7744ae545 | ||
|
|
65b97a7636 | ||
|
|
dd630c5993 | ||
|
|
b39f208bd3 | ||
|
|
53f34061b6 |
@@ -10,6 +10,20 @@ on:
|
||||
#- $default-branch
|
||||
- main
|
||||
- test
|
||||
# Only build when files that affect the Docker image change.
|
||||
# This avoids expensive 15-25 min builds for docs-only or config-only changes.
|
||||
paths:
|
||||
# Individual files
|
||||
- '.github/workflows/docker-publish-cpu.yml'
|
||||
- 'Cargo.lock'
|
||||
- 'Cargo.toml'
|
||||
- 'build/service_cpu.Dockerfile'
|
||||
# Directories
|
||||
- '.sqlx/**'
|
||||
- '_database/**'
|
||||
- 'crates/**'
|
||||
- 'includes/**'
|
||||
- 'test_data/**'
|
||||
env:
|
||||
IMAGE_NAME: storyteller-rust
|
||||
|
||||
|
||||
+3
-1
@@ -6,6 +6,7 @@
|
||||
.env-elasticsearch-secrets
|
||||
.env-migration-tool-secrets
|
||||
.env-secrets
|
||||
.env-support-tool-secrets
|
||||
_develop/tools/.secrets
|
||||
_develop/tools/db_secrets.toml
|
||||
crates/service/web/storyteller_web/config/storyteller-web.development-secrets.env
|
||||
@@ -35,8 +36,9 @@ script/socat_dev_database_connect.sh
|
||||
# Python virtual envs (named by convention)
|
||||
venv/
|
||||
|
||||
# Testing
|
||||
# LLM Testing
|
||||
/prompts/
|
||||
/reports/
|
||||
/requests/
|
||||
|
||||
# Scratch data
|
||||
|
||||
Generated
+4
@@ -1,5 +1,9 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<codeStyleSettings language="Markdown">
|
||||
<option name="RIGHT_MARGIN" value="100" />
|
||||
<option name="WRAP_ON_TYPING" value="1" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="Rust">
|
||||
<option name="RIGHT_MARGIN" value="180" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
|
||||
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n job_type = ?,\n\n maybe_external_third_party = ?,\n maybe_external_third_party_id = ?,\n\n product_category = ?,\n inference_category = ?,\n\n maybe_model_type = NULL,\n maybe_model_token = NULL,\n\n maybe_input_source_token = NULL,\n maybe_input_source_token_type = NULL,\n\n maybe_download_url = NULL,\n maybe_cover_image_media_file_token = NULL,\n \n maybe_prompt_token = ?,\n\n maybe_raw_inference_text = NULL,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n\n priority_level = 0,\n is_keepalive_required = FALSE,\n max_duration_seconds = 0,\n\n is_debug_request = FALSE,\n maybe_routing_tag = NULL,\n\n status = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 14
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "002cdb3d086f3b4181e2997befa54bd8516cb1d3d3bb6e389862695318d5c299"
|
||||
}
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO prompts\nSET\n token = ?,\n prompt_type = ?,\n\n maybe_creator_user_token = ?,\n \n maybe_model_type = ?,\n maybe_generation_provider = ?,\n\n maybe_positive_prompt = ?,\n maybe_negative_prompt = ?,\n \n maybe_other_args = ?,\n\n creator_ip_address = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 9
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "08f52f15acf6afc7091a525e3dc88f706c71c3579e5e81aa9903807d85f469ef"
|
||||
}
|
||||
+17
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"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 ",
|
||||
"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 on_failure_type,\n on_failure_message,\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": [
|
||||
{
|
||||
@@ -74,18 +74,28 @@
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at: DateTime<Utc>",
|
||||
"name": "on_failure_type",
|
||||
"ordinal": 14,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "on_failure_message",
|
||||
"ordinal": 15,
|
||||
"type_info": "Text"
|
||||
},
|
||||
{
|
||||
"name": "created_at: DateTime<Utc>",
|
||||
"ordinal": 16,
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "updated_at: DateTime<Utc>",
|
||||
"ordinal": 15,
|
||||
"ordinal": 17,
|
||||
"type_info": "Int64"
|
||||
},
|
||||
{
|
||||
"name": "completed_at: DateTime<Utc>",
|
||||
"ordinal": 16,
|
||||
"ordinal": 18,
|
||||
"type_info": "Int64"
|
||||
}
|
||||
],
|
||||
@@ -107,10 +117,12 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "47f94c127abc20683b25c257aed3c2190b9bd29eb829d61392f08e10fd986767"
|
||||
"hash": "2436eb7bf4b0e23a899311a67a77f71d89eb35461e2113e43cd9d221bfa91c9a"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO generic_inference_jobs\nSET\n token = ?,\n uuid_idempotency_token = ?,\n\n job_type = ?,\n\n maybe_external_third_party = ?,\n maybe_external_third_party_id = ?,\n\n product_category = ?,\n inference_category = ?,\n\n maybe_model_type = NULL,\n maybe_model_token = NULL,\n\n maybe_input_source_token = NULL,\n maybe_input_source_token_type = NULL,\n\n maybe_download_url = NULL,\n maybe_cover_image_media_file_token = NULL,\n\n maybe_prompt_token = ?,\n\n maybe_raw_inference_text = NULL,\n\n maybe_inference_args = ?,\n\n maybe_creator_user_token = ?,\n maybe_creator_anonymous_visitor_token = ?,\n creator_ip_address = ?,\n creator_set_visibility = ?,\n\n priority_level = 0,\n is_keepalive_required = FALSE,\n max_duration_seconds = 0,\n\n is_debug_request = FALSE,\n maybe_routing_tag = NULL,\n\n frontend_failure_category = ?,\n failure_reason = ?,\n\n status = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 16
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "29916e73a1784ea0b70ef4f637520b05efccc31e01840f681e9b042f82eb8f7e"
|
||||
}
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n u.id as `id: u64`,\n u.token as `token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name,\n u.username_is_not_customized as `username_is_not_customized: bool`,\n u.email_address,\n u.email_confirmed as `email_confirmed: bool`,\n u.is_without_password as `is_without_password: bool`,\n u.ip_address_creation,\n u.maybe_source as `maybe_source: enums::by_table::users::user_signup_source::UserSignupSource`,\n u.maybe_signup_method as `maybe_signup_method: enums::by_table::users::user_signup_method::UserSignupMethod`,\n u.created_at,\n u.maybe_referral_url,\n u.is_temporary as `is_temporary: bool`\nFROM users AS u\nWHERE\n u.id < ?\n AND u.user_deleted_at IS NULL\n AND u.mod_deleted_at IS NULL\nORDER BY u.id DESC\nLIMIT ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id: u64",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
|
||||
"char_set": 63,
|
||||
"max_size": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "username_is_not_customized: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "email_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "email_confirmed: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "is_without_password: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "ip_address_creation",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "maybe_source: enums::by_table::users::user_signup_source::UserSignupSource",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "maybe_signup_method: enums::by_table::users::user_signup_method::UserSignupMethod",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "maybe_referral_url",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"name": "is_temporary: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "2fe10ae5a2d013e1861f71dcb0afae4048e0d47c5b584c6bbc7df25dde747e87"
|
||||
}
|
||||
+71
-5
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n p.token as `token: tokens::tokens::prompts::PromptToken`,\n\n p.prompt_type as `prompt_type: enums::by_table::prompts::prompt_type::PromptType`,\n\n p.maybe_model_type as `maybe_model_type: enums::common::model_type::ModelType`,\n p.maybe_generation_provider as `maybe_generation_provider: enums::common::generation_provider::GenerationProvider`,\n\n p.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n\n p.maybe_positive_prompt,\n p.maybe_negative_prompt,\n p.maybe_other_args,\n\n p.creator_ip_address,\n p.created_at\n\nFROM prompts as p\nWHERE\n p.token = ?\n ",
|
||||
"query": "\nSELECT\n p.token as `token: tokens::tokens::prompts::PromptToken`,\n\n p.prompt_type as `prompt_type: enums::by_table::prompts::prompt_type::PromptType`,\n\n p.maybe_model_type as `maybe_model_type: enums::common::generation::common_model_type::CommonModelType`,\n p.maybe_generation_provider as `maybe_generation_provider: enums::common::generation_provider::GenerationProvider`,\n\n p.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n\n p.maybe_positive_prompt,\n p.maybe_negative_prompt,\n\n p.maybe_generation_mode as `maybe_generation_mode: enums::common::generation::common_generation_mode::CommonGenerationMode`,\n p.maybe_aspect_ratio as `maybe_aspect_ratio: enums::common::generation::common_aspect_ratio::CommonAspectRatio`,\n p.maybe_resolution as `maybe_resolution: enums::common::generation::common_resolution::CommonResolution`,\n p.maybe_batch_count as `maybe_batch_count: u8`,\n p.maybe_generate_audio as `maybe_generate_audio: bool`,\n p.maybe_duration_seconds as `maybe_duration_seconds: u32`,\n\n p.maybe_other_args,\n\n p.creator_ip_address,\n p.created_at\n\nFROM prompts as p\nWHERE\n p.token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "maybe_model_type: enums::common::model_type::ModelType",
|
||||
"name": "maybe_model_type: enums::common::generation::common_model_type::CommonModelType",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
@@ -75,6 +75,66 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "maybe_generation_mode: enums::common::generation::common_generation_mode::CommonGenerationMode",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 96
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "maybe_aspect_ratio: enums::common::generation::common_aspect_ratio::CommonAspectRatio",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 96
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "maybe_resolution: enums::common::generation::common_resolution::CommonResolution",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 64
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "maybe_batch_count: u8",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "maybe_generate_audio: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "maybe_duration_seconds: u32",
|
||||
"type_info": {
|
||||
"type": "Long",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 10
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"name": "maybe_other_args",
|
||||
"type_info": {
|
||||
"type": "Blob",
|
||||
@@ -84,7 +144,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"ordinal": 14,
|
||||
"name": "creator_ip_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -94,7 +154,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"ordinal": 15,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -116,9 +176,15 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "b46b0d022790f4e10f6e47126df0fdc55172bf8cda77d4e0b2afac9e6ebd1630"
|
||||
"hash": "4a50b7bf06061f05e769a41e547cb927bd2b3a6f67c8ceb37883b744237ba34c"
|
||||
}
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n u.id as `id: u64`,\n u.token as `token: tokens::tokens::users::UserToken`,\n u.username,\n u.display_name,\n u.username_is_not_customized as `username_is_not_customized: bool`,\n u.email_address,\n u.email_confirmed as `email_confirmed: bool`,\n u.is_without_password as `is_without_password: bool`,\n u.ip_address_creation,\n u.maybe_source as `maybe_source: enums::by_table::users::user_signup_source::UserSignupSource`,\n u.maybe_signup_method as `maybe_signup_method: enums::by_table::users::user_signup_method::UserSignupMethod`,\n u.created_at,\n u.maybe_referral_url,\n u.is_temporary as `is_temporary: bool`,\n us.subscription_namespace,\n us.subscription_product_slug,\n us.maybe_stripe_subscription_id,\n us.maybe_stripe_customer_id,\n us.maybe_stripe_product_id,\n us.maybe_stripe_price_id,\n us.maybe_stripe_subscription_status,\n us.maybe_stripe_recurring_interval,\n us.maybe_stripe_invoice_is_paid as `maybe_stripe_invoice_is_paid: bool`,\n us.maybe_cancel_at,\n us.maybe_canceled_at\nFROM users AS u\nINNER JOIN user_subscriptions AS us ON u.token = us.user_token\nWHERE\n u.id < ?\n AND u.user_deleted_at IS NULL\n AND u.mod_deleted_at IS NULL\nORDER BY u.id DESC\nLIMIT ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id: u64",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
|
||||
"char_set": 63,
|
||||
"max_size": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "token: tokens::tokens::users::UserToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "username_is_not_customized: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "email_address",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "email_confirmed: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 7,
|
||||
"name": "is_without_password: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 8,
|
||||
"name": "ip_address_creation",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 160
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 9,
|
||||
"name": "maybe_source: enums::by_table::users::user_signup_source::UserSignupSource",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 10,
|
||||
"name": "maybe_signup_method: enums::by_table::users::user_signup_method::UserSignupMethod",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 11,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 12,
|
||||
"name": "maybe_referral_url",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"name": "is_temporary: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"name": "subscription_namespace",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 15,
|
||||
"name": "subscription_product_slug",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 16,
|
||||
"name": "maybe_stripe_subscription_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "UNIQUE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 17,
|
||||
"name": "maybe_stripe_customer_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 18,
|
||||
"name": "maybe_stripe_product_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 19,
|
||||
"name": "maybe_stripe_price_id",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 1020
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 20,
|
||||
"name": "maybe_stripe_subscription_status",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "MULTIPLE_KEY | BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 21,
|
||||
"name": "maybe_stripe_recurring_interval",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 22,
|
||||
"name": "maybe_stripe_invoice_is_paid: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 23,
|
||||
"name": "maybe_cancel_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 24,
|
||||
"name": "maybe_canceled_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "BINARY",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "83840fa1a0712a326a26ae146a819f67a44fae927f294780d89892270075ebb7"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\n UPDATE media_files\n SET maybe_thumbnail_version = ?\n WHERE token = ?\n LIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 2
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "87d7233bb9a4bcae7c9b7d55bb93fab182343847f0bcf8d8ce849f3a2dcfb704"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "SQLite",
|
||||
"query": "\n UPDATE tasks\n SET task_status = ?,\n on_failure_type = ?,\n on_failure_message = ?\n WHERE id = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "9b99ccd0baf9a4b74d8903f63e3a3dcf4c09b75cad978f0532388cbd743b7516"
|
||||
}
|
||||
+31
-20
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n\n jobs.status as `status: enums::common::job_status_plus::JobStatusPlus`,\n jobs.attempt_count,\n\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n\n jobs.product_category as `product_category: enums::by_table::generic_inference_jobs::inference_job_product_category::InferenceJobProductCategory`,\n jobs.inference_category as `inference_category: enums::by_table::generic_inference_jobs::inference_category::InferenceCategory`,\n jobs.maybe_model_type,\n jobs.maybe_model_token,\n jobs.maybe_raw_inference_text,\n jobs.maybe_inference_args,\n\n jobs.frontend_failure_category as `maybe_frontend_failure_category: enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory`,\n\n jobs.on_success_result_entity_type as maybe_result_entity_type,\n jobs.on_success_result_entity_token as maybe_result_entity_token,\n jobs.on_success_result_batch_token as maybe_result_batch_token,\n\n model_weights.title as maybe_model_weights_title,\n tts_models.title as maybe_tts_model_title,\n voice_conversion_models.title as maybe_voice_conversion_model_title,\n\n tts_results.public_bucket_wav_audio_path as maybe_tts_public_bucket_path,\n voice_conversion_results.public_bucket_hash as maybe_voice_conversion_public_bucket_hash,\n\n media_files.public_bucket_directory_hash as maybe_media_file_public_bucket_directory_hash,\n media_files.maybe_public_bucket_prefix as maybe_media_file_public_bucket_prefix,\n media_files.maybe_public_bucket_extension as maybe_media_file_public_bucket_extension,\n\n jobs.assigned_worker as maybe_assigned_worker,\n jobs.assigned_cluster as maybe_assigned_cluster,\n\n jobs.is_keepalive_required,\n\n jobs.created_at,\n jobs.updated_at,\n\n jobs.first_started_at as maybe_first_started_at,\n jobs.successfully_completed_at as maybe_successfully_completed_at,\n\n NOW() as database_clock\n\nFROM generic_inference_jobs as jobs\n\nLEFT OUTER JOIN model_weights ON jobs.maybe_model_token = model_weights.token\nLEFT OUTER JOIN tts_models ON jobs.maybe_model_token = tts_models.token\nLEFT OUTER JOIN voice_conversion_models ON jobs.maybe_model_token = voice_conversion_models.token\n\nLEFT OUTER JOIN tts_results ON jobs.on_success_result_entity_token = tts_results.token\nLEFT OUTER JOIN voice_conversion_results ON jobs.on_success_result_entity_token = voice_conversion_results.token\nLEFT OUTER JOIN media_files ON jobs.on_success_result_entity_token = media_files.token\n\nWHERE jobs.token = ?\n ",
|
||||
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n\n jobs.status as `status: enums::common::job_status_plus::JobStatusPlus`,\n jobs.attempt_count,\n\n jobs.maybe_creator_user_token as `maybe_creator_user_token: tokens::tokens::users::UserToken`,\n jobs.maybe_creator_anonymous_visitor_token as `maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken`,\n jobs.creator_ip_address,\n\n jobs.product_category as `product_category: enums::by_table::generic_inference_jobs::inference_job_product_category::InferenceJobProductCategory`,\n jobs.inference_category as `inference_category: enums::by_table::generic_inference_jobs::inference_category::InferenceCategory`,\n jobs.maybe_model_type,\n jobs.maybe_model_token,\n jobs.maybe_raw_inference_text,\n jobs.maybe_inference_args,\n\n jobs.frontend_failure_category as `maybe_frontend_failure_category: enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory`,\n jobs.failure_reason,\n\n jobs.on_success_result_entity_type as maybe_result_entity_type,\n jobs.on_success_result_entity_token as maybe_result_entity_token,\n jobs.on_success_result_batch_token as maybe_result_batch_token,\n\n model_weights.title as maybe_model_weights_title,\n tts_models.title as maybe_tts_model_title,\n voice_conversion_models.title as maybe_voice_conversion_model_title,\n\n tts_results.public_bucket_wav_audio_path as maybe_tts_public_bucket_path,\n voice_conversion_results.public_bucket_hash as maybe_voice_conversion_public_bucket_hash,\n\n media_files.public_bucket_directory_hash as maybe_media_file_public_bucket_directory_hash,\n media_files.maybe_public_bucket_prefix as maybe_media_file_public_bucket_prefix,\n media_files.maybe_public_bucket_extension as maybe_media_file_public_bucket_extension,\n\n jobs.assigned_worker as maybe_assigned_worker,\n jobs.assigned_cluster as maybe_assigned_cluster,\n\n jobs.is_keepalive_required,\n\n jobs.created_at,\n jobs.updated_at,\n\n jobs.first_started_at as maybe_first_started_at,\n jobs.successfully_completed_at as maybe_successfully_completed_at,\n\n NOW() as database_clock\n\nFROM generic_inference_jobs as jobs\n\nLEFT OUTER JOIN model_weights ON jobs.maybe_model_token = model_weights.token\nLEFT OUTER JOIN tts_models ON jobs.maybe_model_token = tts_models.token\nLEFT OUTER JOIN voice_conversion_models ON jobs.maybe_model_token = voice_conversion_models.token\n\nLEFT OUTER JOIN tts_results ON jobs.on_success_result_entity_token = tts_results.token\nLEFT OUTER JOIN voice_conversion_results ON jobs.on_success_result_entity_token = voice_conversion_results.token\nLEFT OUTER JOIN media_files ON jobs.on_success_result_entity_token = media_files.token\n\nWHERE jobs.token = ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -135,6 +135,16 @@
|
||||
},
|
||||
{
|
||||
"ordinal": 13,
|
||||
"name": "failure_reason",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 2048
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"name": "maybe_result_entity_type",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -144,7 +154,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 14,
|
||||
"ordinal": 15,
|
||||
"name": "maybe_result_entity_token",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -154,7 +164,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 15,
|
||||
"ordinal": 16,
|
||||
"name": "maybe_result_batch_token",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -164,7 +174,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 16,
|
||||
"ordinal": 17,
|
||||
"name": "maybe_model_weights_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -174,7 +184,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 17,
|
||||
"ordinal": 18,
|
||||
"name": "maybe_tts_model_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -184,7 +194,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 18,
|
||||
"ordinal": 19,
|
||||
"name": "maybe_voice_conversion_model_title",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -194,7 +204,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 19,
|
||||
"ordinal": 20,
|
||||
"name": "maybe_tts_public_bucket_path",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -204,7 +214,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 20,
|
||||
"ordinal": 21,
|
||||
"name": "maybe_voice_conversion_public_bucket_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -214,7 +224,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 21,
|
||||
"ordinal": 22,
|
||||
"name": "maybe_media_file_public_bucket_directory_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -224,7 +234,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 22,
|
||||
"ordinal": 23,
|
||||
"name": "maybe_media_file_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -234,7 +244,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 23,
|
||||
"ordinal": 24,
|
||||
"name": "maybe_media_file_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -244,7 +254,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 24,
|
||||
"ordinal": 25,
|
||||
"name": "maybe_assigned_worker",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -254,7 +264,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 25,
|
||||
"ordinal": 26,
|
||||
"name": "maybe_assigned_cluster",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
@@ -264,7 +274,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 26,
|
||||
"ordinal": 27,
|
||||
"name": "is_keepalive_required",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
@@ -274,7 +284,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 27,
|
||||
"ordinal": 28,
|
||||
"name": "created_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -284,7 +294,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 28,
|
||||
"ordinal": 29,
|
||||
"name": "updated_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -294,7 +304,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 29,
|
||||
"ordinal": 30,
|
||||
"name": "maybe_first_started_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -304,7 +314,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 30,
|
||||
"ordinal": 31,
|
||||
"name": "maybe_successfully_completed_at",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
@@ -314,7 +324,7 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 31,
|
||||
"ordinal": 32,
|
||||
"name": "database_clock",
|
||||
"type_info": {
|
||||
"type": "Datetime",
|
||||
@@ -354,6 +364,7 @@
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
@@ -362,5 +373,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "243afe0bc574f9f233c7797add9faf96440e2bafd52032e07951272fb1ec78b1"
|
||||
"hash": "a2c9e2f61eba666254f8432b3c50a0a7738ee3b3faa77c5281bc8e4af96159b9"
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n username_is_not_customized as `username_is_not_customized: bool`\nFROM users\nWHERE\n token = ?\n AND user_deleted_at IS NULL\n AND mod_deleted_at IS NULL\nLIMIT 1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "username",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "display_name",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 80
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "username_is_generated: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "username_is_not_customized: bool",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "NOT_NULL",
|
||||
"char_set": 63,
|
||||
"max_size": 1
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 1
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "be9867966f24f44e14f96966cf5113055f00c339dda75334e7e88d355b9bfe72"
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO prompts\nSET\n token = ?,\n prompt_type = ?,\n\n maybe_creator_user_token = ?,\n \n maybe_model_type = ?,\n maybe_generation_provider = ?,\n\n maybe_positive_prompt = ?,\n maybe_negative_prompt = ?,\n\n maybe_generation_mode = ?,\n maybe_aspect_ratio = ?,\n maybe_resolution = ?,\n maybe_batch_count = ?,\n maybe_generate_audio = ?,\n maybe_duration_seconds = ?,\n\n maybe_other_args = ?,\n\n creator_ip_address = ?\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
"Right": 15
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "ccf92ebe0328d3019ac6b01be4b442df706a183362fa7e5c331f5a4bf1a74a00"
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nSELECT\n id,\n token as `token: MediaFileToken`,\n created_at as `created_at: DateTime<Utc>`,\n maybe_thumbnail_version as `maybe_thumbnail_version: u8`,\n public_bucket_directory_hash,\n maybe_public_bucket_prefix,\n maybe_public_bucket_extension\nFROM media_files\nWHERE\n id >= (SELECT COALESCE(MIN(id), 0) FROM media_files WHERE created_at >= NOW() - INTERVAL ? HOUR)\n AND id < ?\n AND media_class = ?\n AND maybe_thumbnail_version IS NULL\n AND user_deleted_at IS NULL\n AND mod_deleted_at IS NULL\nORDER BY id DESC\nLIMIT ?\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "id",
|
||||
"type_info": {
|
||||
"type": "LongLong",
|
||||
"flags": "NOT_NULL | PRIMARY_KEY | AUTO_INCREMENT",
|
||||
"char_set": 63,
|
||||
"max_size": 20
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "token: MediaFileToken",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "created_at: DateTime<Utc>",
|
||||
"type_info": {
|
||||
"type": "Timestamp",
|
||||
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | TIMESTAMP",
|
||||
"char_set": 63,
|
||||
"max_size": 19
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "maybe_thumbnail_version: u8",
|
||||
"type_info": {
|
||||
"type": "Tiny",
|
||||
"flags": "UNSIGNED",
|
||||
"char_set": 63,
|
||||
"max_size": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 4,
|
||||
"name": "public_bucket_directory_hash",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "NOT_NULL | BINARY | NO_DEFAULT_VALUE",
|
||||
"char_set": 224,
|
||||
"max_size": 128
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 5,
|
||||
"name": "maybe_public_bucket_prefix",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 64
|
||||
}
|
||||
},
|
||||
{
|
||||
"ordinal": 6,
|
||||
"name": "maybe_public_bucket_extension",
|
||||
"type_info": {
|
||||
"type": "VarString",
|
||||
"flags": "BINARY",
|
||||
"char_set": 224,
|
||||
"max_size": 64
|
||||
}
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Right": 4
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "daed2dcd03b3c9fbdb9057b743df078f43e2af87a2c31f418234f98da5ff979f"
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "MySQL",
|
||||
"query": "\nINSERT INTO wallets\nSET\n token = ?,\n wallet_namespace = ?,\n\n owner_user_token = ?,\n \n banked_credits = 0,\n monthly_credits = 0\n ",
|
||||
"query": "\nINSERT INTO wallets\nSET\n token = ?,\n wallet_namespace = ?,\n\n owner_user_token = ?,\n\n banked_credits = 0,\n monthly_credits = 0\n ",
|
||||
"describe": {
|
||||
"columns": [],
|
||||
"parameters": {
|
||||
@@ -8,5 +8,5 @@
|
||||
},
|
||||
"nullable": []
|
||||
},
|
||||
"hash": "4f5100a2cfb465964e77eaacb1ae394daae94de20c56a0966a8222dc9bea63c6"
|
||||
"hash": "f4fb945b4311bd4458a68d82e417b40f8c36c08d572c07881b89cd157a8a8699"
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance for Claude Code when working with the Artcraft monorepo.
|
||||
|
||||
## Project Overview
|
||||
|
||||
Artcraft is a web and desktop application for generating AI image and video. It is written in
|
||||
Rust and TypeScript and contains desktop, server, and frontend components.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
artcraft/
|
||||
├── _database/ # Schema definitions and migrations (MySQL, SQLite, Elasticsearch, etc.)
|
||||
│ ├── elasticsearch/ # Elasticsearch schema and queries
|
||||
│ └── sql/ # MySQL and SQLite schema definitions and migrations
|
||||
│ ├── artcraft_migrations/ # ArtCraft desktop app SQLite migrations
|
||||
│ ├── migrations/ # Server MySQL migrations
|
||||
│ └── migrations_squashed/ # Fully materialized MySQL schema definitions for most tables
|
||||
├── build/ # Dockerfile build instructions for server components
|
||||
├── crates/ # Rust workspace
|
||||
│ ├── api_clients/ # HTTP clients for calling internal and 3rd party services
|
||||
│ ├── cli/ # Command line tools
|
||||
│ ├── desktop/ # Desktop (Tauri) apps
|
||||
│ │ └── artcraft/ # (Important) ArtCraft, the desktop app. This is one of our main pieces of software
|
||||
│ ├── lib/ # Various utility libraries for servers, CLI tools, desktop, etc.
|
||||
│ ├── schema/ # Data definition layer: MySQL, SQlite, Redis, S3/R2 buckets, etc.
|
||||
│ │ ├── buckets/ # Declares R2 cloud bucket topology
|
||||
│ │ ├── database/ # MySQL, SQLite, Elasticsearch, Redis, etc.
|
||||
│ │ │ ├── elasticsearch_schema/ # Elasticsearch
|
||||
│ │ │ ├── migration/ # (deprecated) Online schema adapters for MySQL
|
||||
│ │ │ ├── mysql_queries/ # Sqlx MySQL queries for our backend monolith `storyteller-web`, jobs, etc.
|
||||
│ │ │ ├── redis_common/ # Redis support
|
||||
│ │ │ ├── redis_schema/ # Redis key and HKEY topology
|
||||
│ │ │ ├── sqlite_queries/ # (deprecated) Sqlite queries
|
||||
│ │ │ └── sqlite_tasks/ # Queries for the ArtCraft desktop app's "tasks" database.
|
||||
│ │ ├── public/ # Token identifier and enum variant definitions
|
||||
│ │ │ ├── composite_identifier/ # MySQL composite key system
|
||||
│ │ │ ├── enums/ # MySQL "enums" stored in VARCHAR fields.
|
||||
│ │ │ └── tokens/ # Primary database identifiers with Stripe-like ID prefixes, eg. "user_{entropy}"
|
||||
│ │ └── service/ # Backend HTTP services and jobs
|
||||
│ │ ├── job/ # Backend jobs.
|
||||
│ │ │ └── video_thumbnail_job/ # Render video thumbnails
|
||||
│ │ ├── plugins/ # Collections of reusable Actix-Web HTTP functions (user and billing systems)
|
||||
│ │ └── web/ # HTTP web servers
|
||||
│ │ └── storyteller_web/ # (Important) Our main HTTP API monolith and backend.
|
||||
│ └── frontend/ # Nx typescript monorepo for our websites and Tauri desktop apps
|
||||
│ ├── apps/ # Websites and Tauri desktop apps
|
||||
│ │ ├── artcraft/ # ArtCraft the Tauri app's frontend. Used in conjunction with `artcraft` the Rust crate.
|
||||
│ │ └── artcraft-website/ # The website for https://getartcraft.com
|
||||
│ └── libs/ # Support libraries, reusable React components, etc.
|
||||
└── Cargo.toml # Rust monorepo workspace
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
- Rust with no minimum supported version
|
||||
- Actix-web for HTTP services
|
||||
- SQLx for MySQL and SQLite
|
||||
- A mix of wreq and reqwest for Rust HTTP clients
|
||||
- TypeScript with Nx, React, Vite, Zustand, and Three.js
|
||||
- Use two spaces for indentation
|
||||
Generated
+589
-886
File diff suppressed because it is too large
Load Diff
+94
-64
@@ -6,26 +6,28 @@ 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/artcraft_api_defs",
|
||||
"crates/api_clients/artcraft/artcraft_client",
|
||||
"crates/api_clients/artcraft/artcraft_router",
|
||||
"crates/api_clients/cloud_storage",
|
||||
"crates/api_clients/fal_client",
|
||||
"crates/api_clients/google_drive_common",
|
||||
"crates/api_clients/google_drive_downloader",
|
||||
"crates/api_clients/google_sign_in",
|
||||
"crates/api_clients/grok_client",
|
||||
"crates/api_clients/midjourney_client",
|
||||
"crates/api_clients/muapi_client",
|
||||
"crates/api_clients/openai_sora_client",
|
||||
"crates/api_clients/openart_client",
|
||||
"crates/api_clients/seedance2pro",
|
||||
"crates/api_clients/rootly_client",
|
||||
"crates/api_clients/runwayml_client",
|
||||
"crates/api_clients/seedance2pro_client",
|
||||
"crates/api_clients/thumbnail_generator",
|
||||
"crates/api_clients/world_labs_api",
|
||||
"crates/api_clients/world_labs_client",
|
||||
"crates/api_clients/worldlabs_api_client",
|
||||
"crates/api_clients/worldlabs_consumer_client",
|
||||
|
||||
# CLI tools for operations, etc.
|
||||
"crates/cli/devenv/dev-database-seed",
|
||||
"crates/cli/devenv/dev-upload-media-file",
|
||||
"crates/cli/devenv/scrape-test",
|
||||
"crates/cli/production/db-backfill",
|
||||
"crates/cli/production/db-backup",
|
||||
"crates/cli/production/db-cleanup",
|
||||
@@ -33,6 +35,7 @@ members = [
|
||||
"crates/cli/production/kubectl-pod-cleanup",
|
||||
"crates/cli/production/lru-delete-models",
|
||||
"crates/cli/production/migration-tool",
|
||||
"crates/cli/production/support-tool",
|
||||
|
||||
# Desktop apps
|
||||
"crates/desktop/artcraft",
|
||||
@@ -42,7 +45,6 @@ members = [
|
||||
"crates/lib/actix_cors_configs",
|
||||
"crates/lib/actix_helpers",
|
||||
"crates/lib/bootstrap",
|
||||
"crates/lib/bucket_paths",
|
||||
"crates/lib/build_metadata",
|
||||
"crates/lib/caching/memory_caching",
|
||||
"crates/lib/caching/memory_store",
|
||||
@@ -51,19 +53,14 @@ members = [
|
||||
"crates/lib/cloudflare_mitigation",
|
||||
"crates/lib/concurrency",
|
||||
"crates/lib/cookie_store",
|
||||
"crates/lib/cookies",
|
||||
"crates/lib/data/collections",
|
||||
"crates/lib/data/crockford",
|
||||
"crates/lib/data/datetimes",
|
||||
"crates/lib/data/primitives",
|
||||
"crates/lib/data/web_base64",
|
||||
"crates/lib/deprecated/config", # TODO(bt, 2023-02-13): Deprecate or repurpose
|
||||
"crates/lib/deprecated/http_server_common", # TODO(bt, 2023-03-20): Move useful pieces to actix_helpers
|
||||
"crates/lib/dimensions",
|
||||
"crates/lib/easyenv", # NB: Vendored version of https://github.com/echelon/easyenv.rs that we'll improve.
|
||||
"crates/lib/email_sender",
|
||||
"crates/lib/errors",
|
||||
"crates/lib/files/archives",
|
||||
"crates/lib/ffmpeg_utils",
|
||||
"crates/lib/files/file_to_base64_url",
|
||||
"crates/lib/files/filesys",
|
||||
"crates/lib/files/hashing",
|
||||
@@ -71,35 +68,41 @@ members = [
|
||||
"crates/lib/files/media",
|
||||
"crates/lib/files/mimetypes",
|
||||
"crates/lib/files/videos",
|
||||
"crates/lib/files/zip_archives",
|
||||
"crates/lib/http_headers",
|
||||
"crates/lib/idempotency",
|
||||
"crates/api_clients/artcraft/artcraft_router",
|
||||
"crates/lib/image_algorithms",
|
||||
"crates/lib/jobs_common",
|
||||
"crates/lib/jwt_light",
|
||||
"crates/lib/jwt_signer",
|
||||
"crates/lib/logging",
|
||||
"crates/lib/machine_learning/ml_weights_registry",
|
||||
"crates/lib/machine_learning/prompt_engineering",
|
||||
"crates/lib/markdown",
|
||||
"crates/lib/migration",
|
||||
"crates/lib/password",
|
||||
"crates/lib/server_environment",
|
||||
"crates/lib/sqlx_mysql_helpers",
|
||||
"crates/lib/storyteller_root",
|
||||
"crates/lib/subprocess_common",
|
||||
"crates/lib/test_data",
|
||||
"crates/lib/testing",
|
||||
"crates/lib/tts_common",
|
||||
"crates/lib/url_config",
|
||||
"crates/lib/url_utils",
|
||||
"crates/lib/user_input_common",
|
||||
"crates/lib/users",
|
||||
"crates/lib/web_scrapers",
|
||||
"crates/lib/uuid_utils",
|
||||
#"crates/lib/api_clients/fakeyou_client",
|
||||
#"crates/lib/machine_learning/ml_models",
|
||||
#"crates/lib/deprecated/machine_learning/ml_models",
|
||||
|
||||
# Shared libraries (Deprecated)
|
||||
"crates/lib/deprecated/config", # TODO(bt, 2023-02-13): Deprecate or repurpose
|
||||
"crates/lib/deprecated/email_sender",
|
||||
"crates/lib/deprecated/http_server_common", # TODO(bt, 2023-03-20): Move useful pieces to actix_helpers
|
||||
"crates/lib/deprecated/image_algorithms",
|
||||
"crates/lib/deprecated/machine_learning/ml_weights_registry",
|
||||
"crates/lib/deprecated/machine_learning/prompt_engineering",
|
||||
"crates/lib/deprecated/subprocess_common",
|
||||
"crates/lib/deprecated/tts_common",
|
||||
|
||||
# Schema (buckets): S3/R2 topology
|
||||
"crates/schema/buckets/bucket_paths",
|
||||
|
||||
# Schema (database): queries, database layouts, Redis keys, etc.
|
||||
"crates/schema/database/elasticsearch_schema",
|
||||
"crates/schema/database/migration",
|
||||
"crates/schema/database/mysql_queries",
|
||||
"crates/schema/database/redis_common",
|
||||
"crates/schema/database/redis_schema",
|
||||
@@ -114,31 +117,34 @@ members = [
|
||||
"crates/schema/public/tokens",
|
||||
|
||||
# Services: API servers, jobs, workers, etc.
|
||||
"crates/service/job/analytics_job",
|
||||
"crates/service/job/download_job",
|
||||
"crates/service/job/email_sender_job",
|
||||
"crates/service/job/es-update-job",
|
||||
"crates/service/job/inference_job",
|
||||
"crates/service/job/seedance2_pro_job",
|
||||
"crates/service/job/video_thumbnail_job",
|
||||
"crates/service/job/worldlabs_job",
|
||||
"crates/service/job/tts_download_job",
|
||||
"crates/service/job/tts_inference_job",
|
||||
"crates/service/job/w2l_download_job",
|
||||
"crates/service/job/w2l_inference_job",
|
||||
"crates/service/web/dummy_service",
|
||||
"crates/service/web/storyteller_web",
|
||||
|
||||
# Services (Deprecated) - may still have some use
|
||||
"crates/service/job/deprecated/analytics_job",
|
||||
"crates/service/job/deprecated/download_job",
|
||||
"crates/service/job/deprecated/email_sender_job",
|
||||
"crates/service/job/deprecated/es-update-job",
|
||||
"crates/service/job/deprecated/inference_job",
|
||||
"crates/service/job/deprecated/tts_download_job",
|
||||
"crates/service/job/deprecated/tts_inference_job",
|
||||
"crates/service/job/deprecated/w2l_download_job",
|
||||
"crates/service/job/deprecated/w2l_inference_job",
|
||||
|
||||
# Service Plugins: complete subsystems that can be plugged into services (users, billing, etc.)
|
||||
"crates/service/plugins/billing",
|
||||
"crates/service/plugins/billing_artcraft",
|
||||
"crates/service/plugins/component_traits",
|
||||
"crates/service/plugins/inference_workloads",
|
||||
"crates/service/plugins/user_traits_component",
|
||||
|
||||
# Testing code
|
||||
"crates/testing/test_data",
|
||||
"crates/testing/test_utils",
|
||||
|
||||
# Vendored code
|
||||
"crates/vendor/fal-rs",
|
||||
"crates/vendor/fal-rs/fal-derive",
|
||||
"crates/vendor/fal-rs/generate",
|
||||
"crates/vendor/limitation",
|
||||
"crates/vendor/tauri-plugin-http",
|
||||
"crates/vendor/Symphonia/symphonia",
|
||||
@@ -210,48 +216,57 @@ workspace-build-acceleration = { path = "crates/workspace-build-acceleration" }
|
||||
# Setting paths here ensures we don't need to do so in every crate's Cargo.toml
|
||||
# It makes refactoring much easier.
|
||||
actix_artcraft = { path = "crates/lib/actix_artcraft" }
|
||||
artcraft_router = { path = "crates/api_clients/artcraft/artcraft_router" }
|
||||
actix_helpers = { path = "crates/lib/actix_helpers" }
|
||||
artcraft_api_defs = { path = "crates/api_clients/artcraft/artcraft_api_defs" }
|
||||
artcraft_client = { path = "crates/api_clients/artcraft/artcraft_client" }
|
||||
artcraft_router = { path = "crates/api_clients/artcraft/artcraft_router" }
|
||||
bootstrap = { path = "crates/lib/bootstrap" }
|
||||
bucket_paths = { path = "crates/schema/buckets/bucket_paths" }
|
||||
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" }
|
||||
collections = { path = "crates/lib/data/collections" }
|
||||
component_traits = { path = "crates/service/plugins/component_traits" }
|
||||
concurrency = { path = "crates/lib/concurrency" }
|
||||
cookie_store = { path = "crates/lib/cookie_store" }
|
||||
cookies = { path = "crates/lib/cookies" }
|
||||
crockford = { path = "crates/lib/data/crockford" }
|
||||
easyenv = { path = "crates/lib/easyenv" }
|
||||
enums = { path = "crates/schema/public/enums" }
|
||||
enums_public = { path = "crates/schema/public/enums_public" }
|
||||
errors = { path = "crates/lib/errors" }
|
||||
fal_client = { path = "crates/api_clients/fal_client" }
|
||||
ffmpeg_utils = { path = "crates/lib/ffmpeg_utils" }
|
||||
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" }
|
||||
rootly_client = { path = "crates/api_clients/rootly_client" }
|
||||
http_headers = { path = "crates/lib/http_headers" }
|
||||
idempotency = { path = "crates/lib/idempotency" }
|
||||
images = { path = "crates/lib/files/images" }
|
||||
jobs_common = { path = "crates/lib/jobs_common" }
|
||||
jwt_light = { path = "crates/lib/jwt_light" }
|
||||
jwt_signer = { path = "crates/lib/jwt_signer" }
|
||||
memory_caching = { path = "crates/lib/caching/memory_caching" }
|
||||
memory_store = { path = "crates/lib/caching/memory_store" }
|
||||
midjourney_client = { path = "crates/api_clients/midjourney_client" }
|
||||
mimetypes = { path = "crates/lib/files/mimetypes" }
|
||||
muapi_client = { path = "crates/api_clients/muapi_client" }
|
||||
mysql_queries = { path = "crates/schema/database/mysql_queries" }
|
||||
openai_sora_client = { path = "crates/api_clients/openai_sora_client" }
|
||||
seedance2pro = { path = "crates/api_clients/seedance2pro" }
|
||||
primitives = { path = "crates/lib/data/primitives" }
|
||||
seedance2pro_client = { path = "crates/api_clients/seedance2pro_client" }
|
||||
shared_service_components = { path = "crates/lib/shared_service_components" }
|
||||
sqlite_tasks = { path = "crates/schema/database/sqlite_tasks" }
|
||||
artcraft_client = { path = "crates/api_clients/artcraft/artcraft_client" }
|
||||
subprocess_common = { path = "crates/lib/subprocess_common" }
|
||||
test_data = { path = "crates/lib/test_data" }
|
||||
testing = { path = "crates/lib/testing" }
|
||||
subprocess_common = { path = "crates/lib/deprecated/subprocess_common" }
|
||||
test_data = { path = "crates/testing/test_data" }
|
||||
test_utils = { path = "crates/testing/test_utils" }
|
||||
tokens = { path = "crates/schema/public/tokens" }
|
||||
url_utils = { path = "crates/lib/url_utils" }
|
||||
users = { path = "crates/lib/users" }
|
||||
uuid_utils = { path = "crates/lib/uuid_utils" }
|
||||
web_base64 = { path = "crates/lib/data/web_base64" }
|
||||
world_labs_api = { path = "crates/api_clients/world_labs_api" }
|
||||
world_labs_client = { path = "crates/api_clients/world_labs_client" }
|
||||
worldlabs_api_client = { path = "crates/api_clients/worldlabs_api_client" }
|
||||
worldlabs_consumer_client = { path = "crates/api_clients/worldlabs_consumer_client" }
|
||||
|
||||
# External libs
|
||||
# Centrally pinned versions so that we can uniformly upgrade/downgrade versions across the workspace
|
||||
@@ -267,31 +282,42 @@ actix-web = "4.7.0" # TODO(bt): We're behind and need to bump versions.
|
||||
actix-web-actors = "4.3.1+deprecated"
|
||||
actix-web-lab = "0.20.2"
|
||||
anyhow = "1.0.102"
|
||||
assertor = "0.0.3"
|
||||
base64 = "0.22.1"
|
||||
bcrypt = "0.15"
|
||||
bstr = "1.12.1"
|
||||
bytes = "1.10.1"
|
||||
chrono = { version = "0.4.41", features = ["serde"] }
|
||||
byteorder = "1.5.0"
|
||||
bytes = "1.11.1"
|
||||
chrono = { version = "0.4.44", features = ["serde"] }
|
||||
clap = { version = "=4.5.60", features = ["derive"] }
|
||||
cookie = "0.18.1"
|
||||
dotenv = "0.15.0"
|
||||
elasticsearch = { version = "8.5.0-alpha.1", default-features = false, features = ["rustls-tls"] }
|
||||
env = "1.0.1"
|
||||
env_logger = "0.11.9"
|
||||
futures = { version = "0.3.31" }
|
||||
hex-literal = "1.0.0"
|
||||
indexmap = "2.9.0"
|
||||
futures = { version = "0.3.32" }
|
||||
hex-literal = "1.1.0"
|
||||
hostname = "0.4.0"
|
||||
indexmap = "2.13.0"
|
||||
log = "0.4.29"
|
||||
md-5 = "0.10.6" # insecure but used for gravatar
|
||||
once_cell = "1.21.3"
|
||||
mockall = "0.12.1"
|
||||
once_cell = "1.21.4"
|
||||
r2d2 = "0.8.10"
|
||||
r2d2_redis = "0.14.0"
|
||||
rand = "0.9.1"
|
||||
redis = { version = "1.0.2", features = ["r2d2", "tokio-rustls-comp", "tokio-comp", "cluster-async", "aio"] }
|
||||
regex = "1.12.3"
|
||||
reqwest = { version = "0.12.23", default-features = false, features = [ "charset", "http2", "system-proxy", "json", "cookies", "rustls-tls", "gzip" ] }
|
||||
reqwest-websocket = { version = "0.5.0" }
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
serde_derive = "1.0.219"
|
||||
serde_json = "1.0.140"
|
||||
rust-s3 = { version = "0.36.0-beta.2", default-features = false, features = ["fail-on-err", "tags", "tokio-rustls-tls"] }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_derive = "1.0.228"
|
||||
serde_json = "1.0.149"
|
||||
serde_yaml = "0.9.34+deprecated"
|
||||
sha2 = "0.11.0-rc.2"
|
||||
sha2 = "0.11.0-rc.5"
|
||||
sha3 = "0.10.8"
|
||||
speculoos = "0.11.0"
|
||||
strum = { version = "0.28.0", features = ["derive"] }
|
||||
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"
|
||||
@@ -299,12 +325,16 @@ tauri-plugin-fs = "2.4.2"
|
||||
tauri-plugin-log = "2.6.0"
|
||||
tauri-plugin-upload = "2.3.1"
|
||||
tempdir = "0.3.7"
|
||||
tempfile = "3.20.0"
|
||||
thiserror = "2.0.12"
|
||||
tokio = { version = "1.45.1", features = ["macros"] }
|
||||
toml = "0.8.23"
|
||||
url = { version = "2.5.4", features = ["serde"] }
|
||||
uuid = "1.18.1"
|
||||
tempfile = "3.27.0"
|
||||
thiserror = "2.0.18"
|
||||
time = "0.3.36"
|
||||
tokio = { version = "1.50.0", features = ["macros"] }
|
||||
tokio-util = "0.7.12"
|
||||
toml = "1.0.7+spec-1.1.0"
|
||||
url = { version = "2.5.8", features = ["serde"] }
|
||||
utoipa = { version = "5.4.0", features = ["chrono", "actix_extras", "url"] }
|
||||
uuid = "1.22.0"
|
||||
walkdir = "2.4.0"
|
||||
|
||||
# NB: wreq gets past fingerprinting, but we have to deal with platform-specific build issues.
|
||||
#
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
-- on_complete_primary_media_file_class,
|
||||
-- on_complete_primary_media_file_cdn_url,
|
||||
-- on_complete_primary_media_file_thumbnail_url_template,
|
||||
--
|
||||
-- tasks_v6.sqlite - added two fields:
|
||||
-- on_failure_type
|
||||
-- on_failure_message
|
||||
|
||||
CREATE TABLE tasks (
|
||||
-- Task auto-incrementing primary key.
|
||||
@@ -84,6 +86,15 @@ CREATE TABLE tasks (
|
||||
-- The URL template for the thumbnail of the primary media file.
|
||||
on_complete_primary_media_file_thumbnail_url_template TEXT,
|
||||
|
||||
-- OPTIONAL.
|
||||
-- An enum-like string describing the failure reason (even for non-terminal failures).
|
||||
-- The enum is `TaskFailureType`, which is a close analogue of the backend API's `FrontendFailureCategory`.
|
||||
on_failure_type TEXT,
|
||||
|
||||
-- OPTIONAL.
|
||||
-- A human-readable message describing the failure reason (even for non-terminal failures).
|
||||
on_failure_message TEXT,
|
||||
|
||||
created_at INTEGER NOT NULL DEFAULT (unixepoch('now')),
|
||||
updated_at INTEGER NOT NULL DEFAULT (unixepoch('now')),
|
||||
completed_at INTEGER DEFAULT NULL
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
DROP COLUMN
|
||||
maybe_thumbnail_version;
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE media_files
|
||||
ADD COLUMN
|
||||
maybe_thumbnail_version TINYINT UNSIGNED DEFAULT NULL;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE prompts
|
||||
DROP COLUMN maybe_generation_mode,
|
||||
DROP COLUMN maybe_aspect_ratio,
|
||||
DROP COLUMN maybe_resolution,
|
||||
DROP COLUMN maybe_duration,
|
||||
DROP COLUMN maybe_batch_count,
|
||||
DROP COLUMN maybe_generate_audio;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE prompts
|
||||
ADD COLUMN maybe_generation_mode VARCHAR(24) DEFAULT NULL,
|
||||
ADD COLUMN maybe_aspect_ratio VARCHAR(24) DEFAULT NULL,
|
||||
ADD COLUMN maybe_resolution VARCHAR(16) DEFAULT NULL,
|
||||
ADD COLUMN maybe_duration VARCHAR(8) DEFAULT NULL,
|
||||
ADD COLUMN maybe_batch_count TINYINT UNSIGNED DEFAULT NULL,
|
||||
ADD COLUMN maybe_generate_audio BOOLEAN DEFAULT NULL;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE prompts
|
||||
DROP COLUMN maybe_duration_seconds,
|
||||
ADD COLUMN maybe_duration VARCHAR(8) DEFAULT NULL;
|
||||
@@ -0,0 +1,7 @@
|
||||
-- noinspection SqlDialectInspectionForFile
|
||||
-- noinspection SqlNoDataSourceInspectionForFile
|
||||
-- noinspection SqlResolveForFile
|
||||
|
||||
ALTER TABLE prompts
|
||||
DROP COLUMN maybe_duration,
|
||||
ADD COLUMN maybe_duration_seconds INT UNSIGNED DEFAULT NULL;
|
||||
@@ -224,6 +224,12 @@ CREATE TABLE media_files (
|
||||
-- If so, we may not need to add a watermark downstream in further processing steps.
|
||||
has_watermark BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
|
||||
-- Tracks the thumbnail algorithm/type used for this media file.
|
||||
-- NULL = no thumbnail generated yet.
|
||||
-- 1 = video thumbnail.
|
||||
-- Other values are reserved for future thumbnail algorithms or media-specific types.
|
||||
maybe_thumbnail_version TINYINT UNSIGNED DEFAULT NULL,
|
||||
|
||||
-- ========== UPLOAD, TRANSCODING, AND TRUNCATION DETAILS ==========
|
||||
|
||||
-- The hash for the bucket directory that contains the original upload
|
||||
|
||||
@@ -27,6 +27,8 @@ CREATE TABLE prompts (
|
||||
-- What type of model was used to generate the result.
|
||||
-- NB: We're conflating prompts with outputs, but in a
|
||||
-- sense the model is inextricably part of the prompt.
|
||||
--
|
||||
-- Represented by the `CommonModelType` enum.
|
||||
maybe_model_type VARCHAR(32) DEFAULT NULL,
|
||||
|
||||
-- What service provided the generation.
|
||||
@@ -52,6 +54,29 @@ CREATE TABLE prompts (
|
||||
-- TEXT = 65,535 bytes (64 KiB), ~= 4 bytes per UTF-8 character, ~ 16383 characters.
|
||||
maybe_other_args TEXT DEFAULT NULL,
|
||||
|
||||
-- ========== GENERATION PARAMETERS ==========
|
||||
|
||||
-- Represented by the enum `CommonGenerationMode`.
|
||||
-- The generation mode (eg. keyframe, reference, inpaint, etc.)
|
||||
maybe_generation_mode VARCHAR(24) DEFAULT NULL,
|
||||
|
||||
-- Represented by the enum `CommonAspectRatio`.
|
||||
-- The aspect ratio for the prompt (eg. square, auto, wide_three_by_two, etc.)
|
||||
maybe_aspect_ratio VARCHAR(24) DEFAULT NULL,
|
||||
|
||||
-- Represented by the enum `CommonResolution`.
|
||||
-- The resolution for the prompt (eg. four_k, 720p, etc.)
|
||||
maybe_resolution VARCHAR(16) DEFAULT NULL,
|
||||
|
||||
-- The duration in seconds
|
||||
maybe_duration_seconds INT UNSIGNED DEFAULT NULL,
|
||||
|
||||
-- The number of outputs to generate (0-255)
|
||||
maybe_batch_count TINYINT UNSIGNED DEFAULT NULL,
|
||||
|
||||
-- Whether to generate audio
|
||||
maybe_generate_audio BOOLEAN DEFAULT NULL,
|
||||
|
||||
-- ========== ABUSE TRACKING ==========
|
||||
|
||||
-- For abuse tracking.
|
||||
|
||||
@@ -66,6 +66,7 @@ CREATE TABLE users (
|
||||
-- - "explore_media"
|
||||
-- - "studio"
|
||||
-- - "video_style_transfer"
|
||||
-- - "sd_wl" (seedance whitelist)
|
||||
maybe_feature_flags VARCHAR(255) DEFAULT NULL,
|
||||
|
||||
-- DEPRECATED
|
||||
|
||||
@@ -130,47 +130,20 @@ RUN echo "Disk usage at current directory (after tests):"
|
||||
RUN pwd
|
||||
RUN du -hsc * | sort -hr
|
||||
|
||||
# Build all the binaries.
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin storyteller-web
|
||||
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin seedance2-pro-job
|
||||
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin worldlabs-job
|
||||
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin dummy-service
|
||||
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin analytics-job
|
||||
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin email-sender-job
|
||||
|
||||
# Build all the binaries in a single cargo invocation.
|
||||
# This lets cargo parallelize shared dependency compilation across all targets,
|
||||
# which is significantly faster than building each binary sequentially.
|
||||
RUN SQLX_OFFLINE=true \
|
||||
LD_LIBRARY_PATH=/usr/lib:${LD_LIBRARY_PATH} \
|
||||
$HOME/.cargo/bin/cargo build \
|
||||
--release \
|
||||
--bin storyteller-web \
|
||||
--bin seedance2-pro-job \
|
||||
--bin worldlabs-job \
|
||||
--bin video-thumbnail-job \
|
||||
--bin dummy-service \
|
||||
--bin analytics-job \
|
||||
--bin email-sender-job \
|
||||
--bin es-update-job
|
||||
|
||||
# Print a report on disk space
|
||||
@@ -210,6 +183,7 @@ RUN echo -n ${GIT_SHA} > GIT_SHA
|
||||
COPY --from=builder /tmp/target/release/storyteller-web /
|
||||
COPY --from=builder /tmp/target/release/seedance2-pro-job /
|
||||
COPY --from=builder /tmp/target/release/worldlabs-job /
|
||||
COPY --from=builder /tmp/target/release/video-thumbnail-job /
|
||||
COPY --from=builder /tmp/target/release/dummy-service /
|
||||
COPY --from=builder /tmp/target/release/analytics-job /
|
||||
COPY --from=builder /tmp/target/release/email-sender-job /
|
||||
|
||||
@@ -178,11 +178,11 @@ RUN touch .env-secrets
|
||||
|
||||
# Some services have default env files that live under their code directories
|
||||
# These should also be readable from the relative current path
|
||||
COPY crates/service/job/download_job/config/download-job.common.env .
|
||||
COPY crates/service/job/download_job/config/download-job.production.env .
|
||||
COPY crates/service/job/deprecated/download_job/config/download-job.common.env .
|
||||
COPY crates/service/job/deprecated/download_job/config/download-job.production.env .
|
||||
|
||||
COPY crates/service/job/inference_job/config/inference-job.common.env .
|
||||
COPY crates/service/job/inference_job/config/inference-job.production.env .
|
||||
COPY crates/service/job/deprecated/inference_job/config/inference-job.common.env .
|
||||
COPY crates/service/job/deprecated/inference_job/config/inference-job.production.env .
|
||||
|
||||
# # Need python to make use of other containers' venv
|
||||
# # TODO(bt,2023-04-26): This is only necessary for download-job and inference-job
|
||||
|
||||
@@ -33,7 +33,7 @@ serde.workspace = true
|
||||
serde_derive.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
utoipa = { version = "4", features = ["chrono", "actix_extras"] }
|
||||
utoipa.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
anyhow.workspace = true
|
||||
+2
-1
@@ -1,11 +1,12 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
// TODO(bt,2025-08-20): Replace the storyteller-web version of this.
|
||||
// All it needs is the impl ported into a builder.
|
||||
|
||||
/// Cover image links can only be jpg, png, etc. No videos.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct CoverImageLinks {
|
||||
/// Primary link to the cover image via the CDN.
|
||||
pub cdn_url: Url,
|
||||
|
||||
+3
-2
@@ -1,5 +1,6 @@
|
||||
use crate::common::responses::cover_image_links::CoverImageLinks;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
// TODO(bt,2025-08-20): Replace the storyteller-web version of this.
|
||||
// We can't drop the old version just yet due to the `impl` (easy)
|
||||
@@ -8,7 +9,7 @@ use serde_derive::{Deserialize, Serialize};
|
||||
/// Everything we need to create a cover image.
|
||||
/// Cover images are small descriptive images that can be set for any media file.
|
||||
/// If a cover image is set, this is the path to the asset.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct MediaFileCoverImageDetails {
|
||||
// /// (DEPRECATED) URL path to the media file
|
||||
// #[deprecated(note="This field doesn't point to the full URL. Use media_links instead to leverage the CDN.")]
|
||||
@@ -36,7 +37,7 @@ pub struct MediaFileCoverImageDetails {
|
||||
|
||||
/// The default cover is composed of an image and color pair that are
|
||||
/// predefined by the frontend.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct MediaFileDefaultCover {
|
||||
pub image_index: u8,
|
||||
pub color_index: u8,
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::users::UserToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
/// Everything we need to refer to a user on the public web interface.
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct UserDetailsLight {
|
||||
/// The token for the user
|
||||
pub user_token: UserToken,
|
||||
@@ -26,7 +27,7 @@ pub struct UserDetailsLight {
|
||||
// In the future, we'll also support user-uploaded avatars that we store on our servers.
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[derive(Serialize, Deserialize, ToSchema, Debug)]
|
||||
pub struct UserDefaultAvatarInfo {
|
||||
pub image_index: u8,
|
||||
pub color_index: u8,
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ use utoipa::ToSchema;
|
||||
|
||||
use enums::common::generation::common_aspect_ratio::CommonAspectRatio;
|
||||
use enums::common::generation::common_image_model::CommonImageModel;
|
||||
use enums::common::generation::common_video_resolution::CommonVideoResolution;
|
||||
use enums::common::generation::common_resolution::CommonResolution;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
|
||||
pub const ESTIMATE_IMAGE_COST_PATH: &str = "/v1/generate/cost_estimate/image";
|
||||
@@ -27,7 +27,7 @@ pub struct EstimateImageCostRequest {
|
||||
pub aspect_ratio: Option<CommonAspectRatio>,
|
||||
|
||||
/// Optional resolution.
|
||||
pub resolution: Option<CommonVideoResolution>,
|
||||
pub resolution: Option<CommonResolution>,
|
||||
|
||||
/// Number of images to generate in parallel.
|
||||
pub image_batch_count: Option<u16>,
|
||||
|
||||
+2
-2
@@ -3,7 +3,7 @@ use utoipa::ToSchema;
|
||||
|
||||
use enums::common::generation::common_aspect_ratio::CommonAspectRatio;
|
||||
use enums::common::generation::common_video_model::CommonVideoModel;
|
||||
use enums::common::generation::common_video_resolution::CommonVideoResolution;
|
||||
use enums::common::generation::common_resolution::CommonResolution;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
|
||||
pub const ESTIMATE_VIDEO_COST_PATH: &str = "/v1/generate/cost_estimate/video";
|
||||
@@ -30,7 +30,7 @@ pub struct EstimateVideoCostRequest {
|
||||
pub aspect_ratio: Option<CommonAspectRatio>,
|
||||
|
||||
/// Optional resolution.
|
||||
pub resolution: Option<CommonVideoResolution>,
|
||||
pub resolution: Option<CommonResolution>,
|
||||
|
||||
/// Duration in seconds.
|
||||
pub duration_seconds: Option<u16>,
|
||||
|
||||
+6
@@ -23,6 +23,12 @@ pub struct Seedance2p0MultiFunctionVideoGenRequest {
|
||||
/// Optional reference images (reference mode). When present, takes priority over start/end frames.
|
||||
pub reference_image_media_tokens: Option<Vec<MediaFileToken>>,
|
||||
|
||||
/// Optional reference videos.
|
||||
pub reference_video_media_tokens: Option<Vec<MediaFileToken>>,
|
||||
|
||||
/// Optional reference audio files.
|
||||
pub reference_audio_media_tokens: Option<Vec<MediaFileToken>>,
|
||||
|
||||
/// Video aspect ratio / resolution.
|
||||
pub aspect_ratio: Option<Seedance2p0AspectRatio>,
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use crate::common::responses::job_details::{JobDetailsLipsyncRequest, JobDetailsLivePortraitRequest};
|
||||
use crate::common::responses::media_links::MediaLinks;
|
||||
use chrono::{DateTime, Utc};
|
||||
use enums::by_table::generic_inference_jobs::frontend_failure_category::FrontendFailureCategory;
|
||||
use enums::by_table::generic_inference_jobs::inference_category::InferenceCategory;
|
||||
use enums::common::job_status_plus::JobStatusPlus;
|
||||
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
|
||||
@@ -9,6 +8,8 @@ use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
use enums::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_api_clients::FrontendFailureCategoryForApiClients;
|
||||
use enums::api_safe::by_table::generic_inference_jobs::frontend_failure_category_for_old_clients::FrontendFailureCategoryForOldClients;
|
||||
use tokens::tokens::batch_generations::BatchGenerationToken;
|
||||
|
||||
pub const LIST_SESSION_JOBS_URL_PATH: &str = "/v1/jobs/session";
|
||||
@@ -98,9 +99,19 @@ pub struct ListSessionStatusDetailsResponse {
|
||||
/// This is typically only for non-premium users.
|
||||
pub requires_keepalive: bool,
|
||||
|
||||
/// NB: DO NOT CHANGE: Old clients can't read the new enum payload values as they are introduced.
|
||||
///
|
||||
/// An enum the frontend can use to display localized/I18N error
|
||||
/// messages. These pertain to both transient and permanent failures.
|
||||
pub maybe_failure_category: Option<FrontendFailureCategory>,
|
||||
#[deprecated(note="use maybe_failure_category_updated")]
|
||||
pub maybe_failure_category: Option<FrontendFailureCategoryForOldClients>,
|
||||
|
||||
/// An enum the frontend can use to display localized/I18N error
|
||||
/// messages. These pertain to both transient and permanent failures.
|
||||
pub maybe_failure_category_updated: Option<FrontendFailureCategoryForApiClients>,
|
||||
|
||||
/// User-facing failure messages
|
||||
pub maybe_failure_message: Option<String>,
|
||||
|
||||
/// This is an integer number between 0 and 100 (both inclusive) that
|
||||
/// reports the completeness.
|
||||
@@ -125,4 +136,3 @@ pub struct ListSessionResultDetailsResponse {
|
||||
|
||||
pub maybe_successfully_completed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use enums::by_table::users::user_signup_method::UserSignupMethod;
|
||||
use enums::by_table::users::user_signup_source::UserSignupSource;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::users::UserToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const MODERATOR_LIST_SUBSCRIBING_USERS_BY_SIGNUP_DATE_PATH: &str = "/v1/moderation/users/list_subscribers_by_signup_date";
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct ModeratorListSubscribingUsersBySignupDateRequest {
|
||||
/// Optional cursor for pagination. Pass the `next_cursor` from a previous response.
|
||||
pub id_cursor: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct ModeratorListSubscribingUsersBySignupDateResponse {
|
||||
pub success: bool,
|
||||
pub users: Vec<ModeratorListSubscribingUsersBySignupDateEntry>,
|
||||
/// The cursor for the next page. `None` if there are no more results.
|
||||
pub next_cursor: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct ModeratorListSubscribingUsersBySignupDateEntry {
|
||||
// -- User fields --
|
||||
pub id: u64,
|
||||
pub token: UserToken,
|
||||
pub username: String,
|
||||
pub display_name: String,
|
||||
pub username_is_not_customized: bool,
|
||||
pub email_address: String,
|
||||
pub email_confirmed: bool,
|
||||
pub is_without_password: bool,
|
||||
pub ip_address_creation: String,
|
||||
pub maybe_source: Option<UserSignupSource>,
|
||||
pub maybe_signup_method: Option<UserSignupMethod>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub maybe_referral_url: Option<String>,
|
||||
pub is_temporary: bool,
|
||||
|
||||
// TODO: Use enum types/strong types -
|
||||
// -- Subscription fields --
|
||||
pub subscription_namespace: String,
|
||||
pub subscription_product_slug: String,
|
||||
pub maybe_stripe_subscription_id: Option<String>,
|
||||
pub maybe_stripe_customer_id: Option<String>,
|
||||
pub maybe_stripe_product_id: Option<String>,
|
||||
pub maybe_stripe_price_id: Option<String>,
|
||||
pub maybe_stripe_subscription_status: Option<String>,
|
||||
pub maybe_stripe_recurring_interval: Option<String>,
|
||||
pub maybe_stripe_invoice_is_paid: Option<bool>,
|
||||
pub maybe_cancel_at: Option<DateTime<Utc>>,
|
||||
pub maybe_canceled_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use enums::by_table::users::user_signup_method::UserSignupMethod;
|
||||
use enums::by_table::users::user_signup_source::UserSignupSource;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::users::UserToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const MODERATOR_LIST_USERS_BY_SIGNUP_DATE_PATH: &str = "/v1/moderation/users/list_all_by_signup_date";
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct ModeratorListUsersBySignupDateRequest {
|
||||
/// Optional cursor for pagination. Pass the `next_cursor` from a previous response.
|
||||
pub id_cursor: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct ModeratorListUsersBySignupDateResponse {
|
||||
pub success: bool,
|
||||
pub users: Vec<ModeratorListUsersBySignupDateEntry>,
|
||||
/// The cursor for the next page. `None` if there are no more results.
|
||||
pub next_cursor: Option<u64>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct ModeratorListUsersBySignupDateEntry {
|
||||
pub id: u64,
|
||||
pub token: UserToken,
|
||||
pub username: String,
|
||||
pub display_name: String,
|
||||
pub username_is_not_customized: bool,
|
||||
pub email_address: String,
|
||||
pub email_confirmed: bool,
|
||||
pub is_without_password: bool,
|
||||
pub ip_address_creation: String,
|
||||
pub maybe_source: Option<UserSignupSource>,
|
||||
pub maybe_signup_method: Option<UserSignupMethod>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub maybe_referral_url: Option<String>,
|
||||
pub is_temporary: bool,
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
pub mod list_subscribing_users_by_signup_date;
|
||||
pub mod list_users_by_signup_date;
|
||||
pub mod user_lookup;
|
||||
pub mod user_lookup_by_stripe_customer_id;
|
||||
pub mod user_lookup_by_stripe_customer_id;
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod list_user_wallets;
|
||||
pub mod moderator_add_banked_balance_to_wallet;
|
||||
pub mod moderator_create_wallet_for_user;
|
||||
pub mod moderator_get_wallet;
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::users::UserToken;
|
||||
use tokens::tokens::wallets::WalletToken;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
pub const MODERATOR_CREATE_WALLET_FOR_USER_PATH: &str = "/v1/moderation/wallet/create_for_user";
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct ModeratorCreateWalletForUserRequest {
|
||||
pub user_token: Option<UserToken>,
|
||||
pub payments_namespace: Option<PaymentsNamespace>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct ModeratorCreateWalletForUserResponse {
|
||||
pub success: bool,
|
||||
pub wallet_token: WalletToken,
|
||||
}
|
||||
@@ -1,8 +1,11 @@
|
||||
use enums::common::generation::common_aspect_ratio::CommonAspectRatio;
|
||||
use enums::common::generation::common_generation_mode::CommonGenerationMode;
|
||||
use enums::common::generation::common_model_type::CommonModelType;
|
||||
use enums::common::generation::common_resolution::CommonResolution;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::prompts::PromptToken;
|
||||
use utoipa::ToSchema;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::common::model_type::ModelType;
|
||||
|
||||
pub const CREATE_PROMPT_PATH: &str = "/v1/prompts/create";
|
||||
|
||||
@@ -14,14 +17,32 @@ pub struct CreatePromptRequest {
|
||||
/// OPTIONAL. The positive prompt.
|
||||
pub positive_prompt: Option<String>,
|
||||
|
||||
/// OPTIONAL. The positive prompt.
|
||||
/// OPTIONAL. The negative prompt.
|
||||
pub negative_prompt: Option<String>,
|
||||
|
||||
|
||||
/// OPTIONAL. The model type.
|
||||
pub model_type: Option<ModelType>,
|
||||
pub model_type: Option<CommonModelType>,
|
||||
|
||||
/// OPTIONAL. The service used.
|
||||
pub generation_provider: Option<GenerationProvider>,
|
||||
|
||||
/// OPTIONAL. The generation mode (eg. keyframe, reference, inpaint, etc.)
|
||||
pub maybe_generation_mode: Option<CommonGenerationMode>,
|
||||
|
||||
/// OPTIONAL. The aspect ratio (eg. square, auto, wide_three_by_two, etc.)
|
||||
pub maybe_aspect_ratio: Option<CommonAspectRatio>,
|
||||
|
||||
/// OPTIONAL. The resolution (eg. one_k, two_k, four_k, etc.)
|
||||
pub maybe_resolution: Option<CommonResolution>,
|
||||
|
||||
/// OPTIONAL. The number of outputs to generate (0-255).
|
||||
pub maybe_batch_count: Option<u8>,
|
||||
|
||||
/// OPTIONAL. Whether to generate audio.
|
||||
pub maybe_generate_audio: Option<bool>,
|
||||
|
||||
/// OPTIONAL. The duration in seconds.
|
||||
pub maybe_duration_seconds: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, ToSchema)]
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
use crate::common::responses::media_links::MediaLinks;
|
||||
use chrono::{DateTime, Utc};
|
||||
use enums::by_table::prompt_context_items::prompt_context_semantic_type::PromptContextSemanticType;
|
||||
use enums::by_table::prompts::prompt_type::PromptType;
|
||||
use enums::common::generation::common_aspect_ratio::CommonAspectRatio;
|
||||
use enums::common::generation::common_generation_mode::CommonGenerationMode;
|
||||
use enums::common::generation::common_model_type::CommonModelType;
|
||||
use enums::common::generation::common_resolution::CommonResolution;
|
||||
use enums::common::generation_provider::GenerationProvider;
|
||||
use enums::no_table::style_transfer::style_transfer_name::StyleTransferName;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::prompts::PromptToken;
|
||||
use utoipa::ToSchema;
|
||||
use enums::common::generation::common_model_class::CommonModelClass;
|
||||
|
||||
pub const GET_PROMPT_PATH: &str = "/v1/prompts/{token}";
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct GetPromptPathInfo {
|
||||
pub token: PromptToken,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct GetPromptSuccessResponse {
|
||||
pub success: bool,
|
||||
pub prompt: PromptInfo,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct GetPromptImageContextItem {
|
||||
pub media_token: MediaFileToken,
|
||||
pub semantic: PromptContextSemanticType,
|
||||
pub media_links: MediaLinks,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct PromptInfo {
|
||||
pub token: PromptToken,
|
||||
|
||||
/// The type of prompt.
|
||||
/// Note: Prompts may or may not be compatible across systems.
|
||||
pub prompt_type: PromptType,
|
||||
|
||||
/// The type of model used
|
||||
pub maybe_model_type: Option<CommonModelType>,
|
||||
|
||||
/// The class of model used
|
||||
pub maybe_model_class: Option<CommonModelClass>,
|
||||
|
||||
/// The service provider used
|
||||
pub maybe_generation_provider: Option<GenerationProvider>,
|
||||
|
||||
/// Positive prompt (technically optional, but usually present)
|
||||
pub maybe_positive_prompt: Option<String>,
|
||||
|
||||
/// Negative prompt (optional)
|
||||
pub maybe_negative_prompt: Option<String>,
|
||||
|
||||
/// OPTIONAL. The generation mode (eg. keyframe, reference, inpaint, etc.)
|
||||
pub maybe_generation_mode: Option<CommonGenerationMode>,
|
||||
|
||||
/// OPTIONAL. The aspect ratio (eg. square, auto, wide_three_by_two, etc.)
|
||||
pub maybe_aspect_ratio: Option<CommonAspectRatio>,
|
||||
|
||||
/// OPTIONAL. The resolution (eg. one_k, two_k, four_k, etc.)
|
||||
pub maybe_resolution: Option<CommonResolution>,
|
||||
|
||||
/// OPTIONAL. The number of outputs to generate (0-255).
|
||||
pub maybe_batch_count: Option<u8>,
|
||||
|
||||
/// OPTIONAL. Whether to generate audio.
|
||||
pub maybe_generate_audio: Option<bool>,
|
||||
|
||||
/// OPTIONAL. The duration in seconds.
|
||||
pub maybe_duration_seconds: Option<u32>,
|
||||
|
||||
/// Context images (optional)
|
||||
pub maybe_context_images: Option<Vec<GetPromptImageContextItem>>,
|
||||
|
||||
/// Scheduled / travel prompt (optional)
|
||||
pub maybe_travel_prompt: Option<String>,
|
||||
|
||||
/// If a "style" was used, this is the name of it.
|
||||
/// This might not be present for all types of inference
|
||||
/// and typically only applies to video style transfer.
|
||||
pub maybe_style_name: Option<StyleTransferName>,
|
||||
|
||||
/// How many milliseconds it took to run generation.
|
||||
pub maybe_inference_duration_millis: Option<u64>,
|
||||
|
||||
/// If a "strength" was used.
|
||||
/// Typically only for video style transfer.
|
||||
pub maybe_strength: Option<f32>,
|
||||
|
||||
/// If a frame skip setting was used.
|
||||
pub maybe_frame_skip: Option<u8>,
|
||||
|
||||
/// If a face detailer was used.
|
||||
/// This might not be present for all types of inference
|
||||
/// and typically only applies to video style transfer.
|
||||
pub used_face_detailer: bool,
|
||||
|
||||
/// If an upscaling pass was used.
|
||||
/// This might not be present for all types of inference
|
||||
/// and typically only applies to video style transfer.
|
||||
pub used_upscaler: bool,
|
||||
|
||||
/// If lipsync was enabled.
|
||||
/// This might not be present for all types of inference
|
||||
/// and typically only applies to video style transfer.
|
||||
pub lipsync_enabled: bool,
|
||||
|
||||
/// If LCM was disabled.
|
||||
/// Only staff can do this for now.
|
||||
pub lcm_disabled: bool,
|
||||
|
||||
/// If the cinematic workflow was used.
|
||||
/// Only staff can do this for now.
|
||||
pub use_cinematic: bool,
|
||||
|
||||
/// If a global IP Adapter Image was used, this is the details.
|
||||
/// NB: We can't easily query for this without another DB round trip,
|
||||
/// so the frontend should query for it instead.
|
||||
pub maybe_global_ipa_image_token: Option<MediaFileToken>,
|
||||
|
||||
/// Fields that only moderators should see.
|
||||
pub maybe_moderator_fields: Option<PromptInfoModeratorFields>,
|
||||
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
pub struct PromptInfoModeratorFields {
|
||||
/// How many milliseconds it took to run generation.
|
||||
pub maybe_inference_duration_millis: Option<u64>,
|
||||
|
||||
/// Version of Yae's workflow
|
||||
/// Used for logging and debugging by the art team.
|
||||
pub main_ipa_workflow: Option<String>,
|
||||
|
||||
/// Version of Yae's face detailer workflow
|
||||
/// Used for logging and debugging by the art team.
|
||||
pub face_detailer_workflow: Option<String>,
|
||||
|
||||
/// Version of Yae's upscaler workflow
|
||||
/// Used for logging and debugging by the art team.
|
||||
pub upscaler_workflow: Option<String>,
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
pub mod create_prompt;
|
||||
pub mod create_prompt;
|
||||
pub mod get_prompt;
|
||||
@@ -28,7 +28,7 @@ cloudflare_errors.workspace = true
|
||||
enums.workspace = true
|
||||
enums_public.workspace = true
|
||||
errors.workspace = true
|
||||
idempotency.workspace = true
|
||||
uuid_utils.workspace = true
|
||||
mimetypes.workspace = true
|
||||
tokens.workspace = true
|
||||
|
||||
|
||||
-1
@@ -5,7 +5,6 @@ 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;
|
||||
|
||||
|
||||
+1
-9
@@ -7,16 +7,9 @@ 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 uuid_utils::uuid::generate_random_uuid;
|
||||
use log::debug;
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use reqwest::Client;
|
||||
@@ -52,7 +45,6 @@ pub struct LegacyUploadMediaFileFromFileArgs<'a, P: AsRef<Path>> {
|
||||
// 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>,
|
||||
|
||||
+1
-8
@@ -7,15 +7,8 @@ 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::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 uuid_utils::uuid::generate_random_uuid;
|
||||
use log::debug;
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use reqwest::Client;
|
||||
|
||||
+1
-9
@@ -7,16 +7,9 @@ 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 uuid_utils::uuid::generate_random_uuid;
|
||||
use log::debug;
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use reqwest::Client;
|
||||
@@ -52,7 +45,6 @@ pub struct UploadImageFromFileArgs<'a, P: AsRef<Path>> {
|
||||
pub maybe_batch_token: Option<&'a BatchGenerationToken>,
|
||||
}
|
||||
|
||||
|
||||
/// Upload an image media file from a file.
|
||||
pub async fn upload_image_media_file_from_file<P: AsRef<Path>>(
|
||||
args: UploadImageFromFileArgs<'_, P>,
|
||||
|
||||
+1
-8
@@ -5,15 +5,8 @@ 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::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 uuid_utils::uuid::generate_random_uuid;
|
||||
use log::debug;
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use reqwest::Client;
|
||||
|
||||
+1
-10
@@ -5,15 +5,8 @@ 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::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 uuid_utils::uuid::generate_random_uuid;
|
||||
use log::debug;
|
||||
use reqwest::multipart::{Form, Part};
|
||||
use reqwest::Client;
|
||||
@@ -49,8 +42,6 @@ pub struct UploadVideoFromFileArgs<'a, P: AsRef<Path>> {
|
||||
// pub maybe_batch_token: Option<&'a BatchGenerationToken>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
// TODO(bt,2025-04-22): Share API definitions between client and server in common crate.
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
|
||||
@@ -19,14 +19,18 @@ workspace-build-acceleration.workspace = true
|
||||
artcraft_api_defs.workspace = true
|
||||
artcraft_client.workspace = true
|
||||
fal_client.workspace = true
|
||||
seedance2pro.workspace = true
|
||||
muapi_client.workspace = true
|
||||
seedance2pro_client.workspace = true
|
||||
tokens.workspace = true
|
||||
world_labs_api.workspace = true
|
||||
url_utils.workspace = true
|
||||
worldlabs_api_client.workspace = true
|
||||
|
||||
# External
|
||||
anyhow.workspace = true
|
||||
log.workspace = true
|
||||
reqwest.workspace = true
|
||||
serde.workspace = true
|
||||
wreq.workspace = true
|
||||
serde_derive.workspace = true
|
||||
tokio.workspace = true
|
||||
uuid.workspace = true
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AudioListRef<'a> {
|
||||
MediaFileTokens(&'a Vec<MediaFileToken>),
|
||||
Urls(&'a Vec<String>),
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod audio_list_ref;
|
||||
pub mod common_aspect_ratio;
|
||||
pub mod common_image_model;
|
||||
pub mod common_resolution;
|
||||
@@ -6,3 +7,4 @@ pub mod common_video_model;
|
||||
pub mod image_list_ref;
|
||||
pub mod image_ref;
|
||||
pub mod provider;
|
||||
pub mod video_list_ref;
|
||||
|
||||
@@ -6,4 +6,6 @@ use serde_derive::{Deserialize, Serialize};
|
||||
pub enum Provider {
|
||||
Artcraft,
|
||||
Fal,
|
||||
Muapi,
|
||||
Seedance2Pro,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum VideoListRef<'a> {
|
||||
MediaFileTokens(&'a Vec<MediaFileToken>),
|
||||
Urls(&'a Vec<String>),
|
||||
}
|
||||
@@ -5,3 +5,5 @@ pub mod request_mismatch_mitigation_strategy;
|
||||
pub mod router_artcraft_client;
|
||||
pub mod router_client;
|
||||
pub mod router_fal_client;
|
||||
pub mod router_muapi_client;
|
||||
pub mod router_seedance2pro_client;
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
use crate::client::router_artcraft_client::RouterArtcraftClient;
|
||||
use crate::client::router_fal_client::RouterFalClient;
|
||||
use crate::client::router_muapi_client::RouterMuapiClient;
|
||||
use crate::client::router_seedance2pro_client::RouterSeedance2ProClient;
|
||||
use crate::errors::client_error::{ClientError, ClientType};
|
||||
|
||||
pub struct MultiRouterClient {
|
||||
pub(crate) artcraft_client: Option<RouterArtcraftClient>,
|
||||
pub(crate) fal_client: Option<RouterFalClient>,
|
||||
pub(crate) muapi_client: Option<RouterMuapiClient>,
|
||||
pub(crate) seedance2pro_client: Option<RouterSeedance2ProClient>,
|
||||
}
|
||||
|
||||
impl MultiRouterClient {
|
||||
@@ -17,4 +21,14 @@ impl MultiRouterClient {
|
||||
self.fal_client.as_ref()
|
||||
.ok_or(ClientError::ClientNotConfigured(ClientType::Fal))
|
||||
}
|
||||
|
||||
pub fn get_muapi_client_ref(&self) -> Result<&RouterMuapiClient, ClientError> {
|
||||
self.muapi_client.as_ref()
|
||||
.ok_or(ClientError::ClientNotConfigured(ClientType::Muapi))
|
||||
}
|
||||
|
||||
pub fn get_seedance2pro_client_ref(&self) -> Result<&RouterSeedance2ProClient, ClientError> {
|
||||
self.seedance2pro_client.as_ref()
|
||||
.ok_or(ClientError::ClientNotConfigured(ClientType::Seedance2Pro))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
use crate::client::multi_router_client::MultiRouterClient;
|
||||
use crate::client::router_artcraft_client::RouterArtcraftClient;
|
||||
use crate::client::router_fal_client::RouterFalClient;
|
||||
use crate::client::router_muapi_client::RouterMuapiClient;
|
||||
use crate::client::router_seedance2pro_client::RouterSeedance2ProClient;
|
||||
|
||||
pub struct MultiRouterClientBuilder {
|
||||
artcraft_client: Option<RouterArtcraftClient>,
|
||||
fal_client: Option<RouterFalClient>,
|
||||
muapi_client: Option<RouterMuapiClient>,
|
||||
seedance2pro_client: Option<RouterSeedance2ProClient>,
|
||||
}
|
||||
|
||||
impl MultiRouterClientBuilder {
|
||||
@@ -12,6 +16,8 @@ impl MultiRouterClientBuilder {
|
||||
Self {
|
||||
artcraft_client: None,
|
||||
fal_client: None,
|
||||
muapi_client: None,
|
||||
seedance2pro_client: None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,10 +31,22 @@ impl MultiRouterClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_muapi_client(mut self, client: RouterMuapiClient) -> Self {
|
||||
self.muapi_client = Some(client);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn set_seedance2pro_client(mut self, client: RouterSeedance2ProClient) -> Self {
|
||||
self.seedance2pro_client = Some(client);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> MultiRouterClient {
|
||||
MultiRouterClient {
|
||||
artcraft_client: self.artcraft_client,
|
||||
fal_client: self.fal_client,
|
||||
muapi_client: self.muapi_client,
|
||||
seedance2pro_client: self.seedance2pro_client,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
use crate::client::multi_router_client::MultiRouterClient;
|
||||
use crate::client::router_artcraft_client::RouterArtcraftClient;
|
||||
use crate::client::router_fal_client::RouterFalClient;
|
||||
use crate::client::router_muapi_client::RouterMuapiClient;
|
||||
use crate::client::router_seedance2pro_client::RouterSeedance2ProClient;
|
||||
use crate::errors::client_error::{ClientError, ClientType};
|
||||
|
||||
pub enum RouterClient {
|
||||
Multi(MultiRouterClient),
|
||||
Artcraft(RouterArtcraftClient),
|
||||
Fal(RouterFalClient),
|
||||
Muapi(RouterMuapiClient),
|
||||
Seedance2Pro(RouterSeedance2ProClient),
|
||||
}
|
||||
|
||||
impl RouterClient {
|
||||
@@ -25,4 +29,20 @@ impl RouterClient {
|
||||
_ => Err(ClientError::ClientNotConfigured(ClientType::Fal)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_muapi_client_ref(&self) -> Result<&RouterMuapiClient, ClientError> {
|
||||
match self {
|
||||
RouterClient::Muapi(client) => Ok(client),
|
||||
RouterClient::Multi(multi) => multi.get_muapi_client_ref(),
|
||||
_ => Err(ClientError::ClientNotConfigured(ClientType::Muapi)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_seedance2pro_client_ref(&self) -> Result<&RouterSeedance2ProClient, ClientError> {
|
||||
match self {
|
||||
RouterClient::Seedance2Pro(client) => Ok(client),
|
||||
RouterClient::Multi(multi) => multi.get_seedance2pro_client_ref(),
|
||||
_ => Err(ClientError::ClientNotConfigured(ClientType::Seedance2Pro)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
use muapi_client::creds::muapi_session::MuapiSession;
|
||||
|
||||
pub struct RouterMuapiClient {
|
||||
pub(crate) session: MuapiSession,
|
||||
}
|
||||
|
||||
impl RouterMuapiClient {
|
||||
pub fn new(session: MuapiSession) -> Self {
|
||||
RouterMuapiClient { session }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession;
|
||||
|
||||
pub struct RouterSeedance2ProClient {
|
||||
pub(crate) session: Seedance2ProSession,
|
||||
}
|
||||
|
||||
impl RouterSeedance2ProClient {
|
||||
pub fn new(session: Seedance2ProSession) -> Self {
|
||||
RouterSeedance2ProClient { session }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::errors::download_error::DownloadError;
|
||||
use crate::errors::provider_error::ProviderError;
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
@@ -8,6 +9,9 @@ pub enum ArtcraftRouterError {
|
||||
/// A client configuration error.
|
||||
Client(ClientError),
|
||||
|
||||
/// Failed to download a file from a URL (e.g. when re-uploading to a provider's CDN).
|
||||
Download(DownloadError),
|
||||
|
||||
/// The requested model is not yet supported by the router.
|
||||
UnsupportedModel(String),
|
||||
|
||||
@@ -24,6 +28,7 @@ impl Display for ArtcraftRouterError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Client(e) => write!(f, "Client error: {}", e),
|
||||
Self::Download(e) => write!(f, "Download error: {}", e),
|
||||
Self::UnsupportedModel(model) => write!(f, "Unsupported model: {}", model),
|
||||
Self::InvalidInput(msg) => write!(f, "Invalid input: {}", msg),
|
||||
Self::Provider(e) => write!(f, "Provider error: {}", e),
|
||||
@@ -37,6 +42,12 @@ impl From<ClientError> for ArtcraftRouterError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DownloadError> for ArtcraftRouterError {
|
||||
fn from(error: DownloadError) -> Self {
|
||||
Self::Download(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ProviderError> for ArtcraftRouterError {
|
||||
fn from(error: ProviderError) -> Self {
|
||||
Self::Provider(error)
|
||||
|
||||
@@ -5,6 +5,8 @@ use std::fmt::{Display, Formatter};
|
||||
pub enum ClientType {
|
||||
Artcraft,
|
||||
Fal,
|
||||
Muapi,
|
||||
Seedance2Pro,
|
||||
}
|
||||
|
||||
impl Display for ClientType {
|
||||
@@ -12,6 +14,8 @@ impl Display for ClientType {
|
||||
match self {
|
||||
Self::Artcraft => write!(f, "Artcraft"),
|
||||
Self::Fal => write!(f, "Fal"),
|
||||
Self::Muapi => write!(f, "Muapi"),
|
||||
Self::Seedance2Pro => write!(f, "Seedance2Pro"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +37,12 @@ pub enum ClientError {
|
||||
|
||||
/// Fal only accepts image URLs for image inputs, not media tokens.
|
||||
FalOnlySupportsUrls,
|
||||
|
||||
/// Muapi only accepts URLs for image inputs, not media tokens.
|
||||
MuapiOnlySupportsUrls,
|
||||
|
||||
/// Seedance2Pro only accepts URLs for media inputs, not media tokens.
|
||||
Seedance2ProOnlySupportsUrls,
|
||||
}
|
||||
|
||||
impl Error for ClientError {}
|
||||
@@ -55,6 +65,12 @@ impl Display for ClientError {
|
||||
Self::FalOnlySupportsUrls => {
|
||||
write!(f, "Fal only supports image URLs for image inputs, not media tokens")
|
||||
}
|
||||
Self::MuapiOnlySupportsUrls => {
|
||||
write!(f, "Muapi only supports URLs for image inputs; resolve media tokens to URLs before calling this provider")
|
||||
}
|
||||
Self::Seedance2ProOnlySupportsUrls => {
|
||||
write!(f, "Seedance2Pro only supports URLs for media inputs; resolve media tokens to URLs before calling this provider")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DownloadError {
|
||||
BadStatus {
|
||||
url: String,
|
||||
status_code: u16,
|
||||
},
|
||||
|
||||
ReqwestDownload {
|
||||
url: String,
|
||||
error: reqwest::Error,
|
||||
maybe_status: Option<reqwest::StatusCode>,
|
||||
},
|
||||
|
||||
WreqDownload {
|
||||
url: String,
|
||||
error: wreq::Error,
|
||||
maybe_status: Option<wreq::StatusCode>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Error for DownloadError {}
|
||||
|
||||
impl Display for DownloadError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::BadStatus { url, status_code } => {
|
||||
write!(f, "Download failed for {} with status {}", url, status_code)
|
||||
}
|
||||
Self::ReqwestDownload { url, error, maybe_status } => {
|
||||
write!(f, "Reqwest download error for {}: {} (status: {:?})", url, error, maybe_status)
|
||||
}
|
||||
Self::WreqDownload { url, error, maybe_status } => {
|
||||
write!(f, "Wreq download error for {}: {} (status: {:?})", url, error, maybe_status)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod artcraft_router_error;
|
||||
pub mod client_error;
|
||||
pub mod download_error;
|
||||
pub mod provider_error;
|
||||
|
||||
@@ -2,11 +2,15 @@ use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use artcraft_client::error::storyteller_error::StorytellerError;
|
||||
use fal_client::error::fal_error_plus::FalErrorPlus;
|
||||
use muapi_client::error::muapi_error::MuapiError;
|
||||
use seedance2pro_client::error::seedance2pro_error::Seedance2ProError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ProviderError {
|
||||
Storyteller(StorytellerError),
|
||||
Fal(FalErrorPlus),
|
||||
Muapi(MuapiError),
|
||||
Seedance2Pro(Seedance2ProError),
|
||||
}
|
||||
|
||||
impl Error for ProviderError {}
|
||||
@@ -16,6 +20,8 @@ impl Display for ProviderError {
|
||||
match self {
|
||||
Self::Storyteller(e) => write!(f, "Storyteller provider error: {}", e),
|
||||
Self::Fal(e) => write!(f, "Fal provider error: {}", e),
|
||||
Self::Muapi(e) => write!(f, "Muapi provider error: {}", e),
|
||||
Self::Seedance2Pro(e) => write!(f, "Seedance2Pro provider error: {}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,3 +37,15 @@ impl From<FalErrorPlus> for ProviderError {
|
||||
Self::Fal(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<MuapiError> for ProviderError {
|
||||
fn from(error: MuapiError) -> Self {
|
||||
Self::Muapi(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Seedance2ProError> for ProviderError {
|
||||
fn from(error: Seedance2ProError) -> Self {
|
||||
Self::Seedance2Pro(error)
|
||||
}
|
||||
}
|
||||
|
||||
+39
-63
@@ -73,72 +73,48 @@ impl<'a> GenerateImageRequest<'a> {
|
||||
/// Read the image generation request, construct a plan, then yield a means to execute it.
|
||||
pub fn build(&self) -> Result<ImageGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
match self.provider {
|
||||
Provider::Artcraft => match self.model {
|
||||
CommonImageModel::Flux1Dev => {
|
||||
plan_generate_image_artcraft_flux_1_dev(self).map(ImageGenerationPlan::ArtcraftFlux1Dev)
|
||||
}
|
||||
CommonImageModel::Flux1Schnell => {
|
||||
plan_generate_image_artcraft_flux_1_schnell(self).map(ImageGenerationPlan::ArtcraftFlux1Schnell)
|
||||
}
|
||||
CommonImageModel::FluxPro11 => {
|
||||
plan_generate_image_artcraft_flux_pro_1p1(self).map(ImageGenerationPlan::ArtcraftFluxPro11)
|
||||
}
|
||||
CommonImageModel::FluxPro11Ultra => {
|
||||
plan_generate_image_artcraft_flux_pro_1p1_ultra(self).map(ImageGenerationPlan::ArtcraftFluxPro11Ultra)
|
||||
}
|
||||
CommonImageModel::GptImage1p5 => {
|
||||
plan_generate_image_artcraft_gpt_image_1p5(self).map(ImageGenerationPlan::ArtcraftGptImage1p5)
|
||||
}
|
||||
CommonImageModel::NanaBanana => {
|
||||
plan_generate_image_artcraft_nano_banana(self).map(ImageGenerationPlan::ArtcraftNanaBanana)
|
||||
}
|
||||
CommonImageModel::NanaBanana2 => {
|
||||
plan_generate_image_artcraft_nano_banana_2(self).map(ImageGenerationPlan::ArtcraftNanaBanana2)
|
||||
}
|
||||
CommonImageModel::NanaBananaPro => {
|
||||
plan_generate_image_artcraft_nano_banana_pro(self).map(ImageGenerationPlan::ArtcraftNanaBananaPro)
|
||||
}
|
||||
CommonImageModel::Seedream4 => {
|
||||
plan_generate_image_artcraft_seedream_4(self).map(ImageGenerationPlan::ArtcraftSeedream4)
|
||||
}
|
||||
CommonImageModel::Seedream4p5 => {
|
||||
plan_generate_image_artcraft_seedream_4p5(self).map(ImageGenerationPlan::ArtcraftSeedream4p5)
|
||||
}
|
||||
CommonImageModel::Seedream5Lite => {
|
||||
plan_generate_image_artcraft_seedream_5_lite(self).map(ImageGenerationPlan::ArtcraftSeedream5Lite)
|
||||
}
|
||||
CommonImageModel::QwenEdit2511Angles => {
|
||||
plan_generate_image_artcraft_qwen_edit_2511_angles(self).map(ImageGenerationPlan::ArtcraftQwenEdit2511Angles)
|
||||
}
|
||||
CommonImageModel::Flux2LoraAngles => {
|
||||
plan_generate_image_artcraft_flux_2_lora_angles(self).map(ImageGenerationPlan::ArtcraftFlux2LoraAngles)
|
||||
}
|
||||
},
|
||||
Provider::Fal => match self.model {
|
||||
CommonImageModel::NanaBananaPro => {
|
||||
plan_generate_image_fal_nano_banana_pro(self).map(ImageGenerationPlan::FalNanaBananaPro)
|
||||
}
|
||||
CommonImageModel::Flux1Dev
|
||||
| CommonImageModel::Flux1Schnell
|
||||
| CommonImageModel::FluxPro11
|
||||
| CommonImageModel::FluxPro11Ultra
|
||||
| CommonImageModel::GptImage1p5
|
||||
| CommonImageModel::NanaBanana
|
||||
| CommonImageModel::NanaBanana2
|
||||
| CommonImageModel::Seedream4
|
||||
| CommonImageModel::Seedream4p5
|
||||
| CommonImageModel::Seedream5Lite
|
||||
| CommonImageModel::QwenEdit2511Angles
|
||||
| CommonImageModel::Flux2LoraAngles => {
|
||||
Err(ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption {
|
||||
field: "provider",
|
||||
value: format!("{:?} is only available on the Artcraft provider", self.model),
|
||||
}))
|
||||
}
|
||||
},
|
||||
Provider::Artcraft => self.build_artcraft(),
|
||||
Provider::Fal => self.build_fal(),
|
||||
_ => self.unsupported_provider(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_artcraft(&self) -> Result<ImageGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
match self.model {
|
||||
CommonImageModel::Flux1Dev => plan_generate_image_artcraft_flux_1_dev(self),
|
||||
CommonImageModel::Flux1Schnell => plan_generate_image_artcraft_flux_1_schnell(self),
|
||||
CommonImageModel::FluxPro11 => plan_generate_image_artcraft_flux_pro_1p1(self),
|
||||
CommonImageModel::FluxPro11Ultra => plan_generate_image_artcraft_flux_pro_1p1_ultra(self),
|
||||
CommonImageModel::GptImage1p5 => plan_generate_image_artcraft_gpt_image_1p5(self),
|
||||
CommonImageModel::NanaBanana => plan_generate_image_artcraft_nano_banana(self),
|
||||
CommonImageModel::NanaBanana2 => plan_generate_image_artcraft_nano_banana_2(self),
|
||||
CommonImageModel::NanaBananaPro => plan_generate_image_artcraft_nano_banana_pro(self),
|
||||
CommonImageModel::Seedream4 => plan_generate_image_artcraft_seedream_4(self),
|
||||
CommonImageModel::Seedream4p5 => plan_generate_image_artcraft_seedream_4p5(self),
|
||||
CommonImageModel::Seedream5Lite => plan_generate_image_artcraft_seedream_5_lite(self),
|
||||
CommonImageModel::QwenEdit2511Angles => plan_generate_image_artcraft_qwen_edit_2511_angles(self),
|
||||
CommonImageModel::Flux2LoraAngles => plan_generate_image_artcraft_flux_2_lora_angles(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_fal(&self) -> Result<ImageGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
match self.model {
|
||||
CommonImageModel::NanaBananaPro => plan_generate_image_fal_nano_banana_pro(self),
|
||||
_ => {
|
||||
Err(ArtcraftRouterError::Client(ClientError::ModelDoesNotSupportOption {
|
||||
field: "provider",
|
||||
value: format!("{:?} is only available on the Artcraft provider", self.model),
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unsupported_provider(&self) -> Result<ImageGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
Err(ArtcraftRouterError::UnsupportedModel(
|
||||
format!("Image generation for model `{:?}` is not supported for provider {:?}", self.model, self.provider)
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_or_generate_idempotency_token(&self) -> String {
|
||||
self.idempotency_token.map(|t| t.to_string())
|
||||
.unwrap_or_else(|| uuid::Uuid::new_v4().to_string())
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_1_dev_text_to_image::{
|
||||
GenerateFlux1DevTextToImageAspectRatio, GenerateFlux1DevTextToImageNumImages,
|
||||
};
|
||||
@@ -18,7 +19,7 @@ pub struct PlanArtcraftFlux1Dev<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_flux_1_dev<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftFlux1Dev<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
// Flux 1 Dev is text-to-image only. Abort if image inputs are provided and
|
||||
// the caller has opted into strict mode.
|
||||
if request.image_inputs.is_some() {
|
||||
@@ -35,12 +36,12 @@ pub fn plan_generate_image_artcraft_flux_1_dev<'a>(
|
||||
let aspect_ratio = plan_aspect_ratio(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftFlux1Dev {
|
||||
Ok(ImageGenerationPlan::ArtcraftFlux1Dev(PlanArtcraftFlux1Dev {
|
||||
prompt: request.prompt,
|
||||
aspect_ratio,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
// Flux 1 Dev supported aspect ratios:
|
||||
@@ -134,7 +135,6 @@ mod tests {
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_flux_1_dev_image_request;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_1_dev_text_to_image::{
|
||||
GenerateFlux1DevTextToImageAspectRatio as FlAr,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_1_schnell_text_to_image::{
|
||||
GenerateFlux1SchnellTextToImageAspectRatio, GenerateFlux1SchnellTextToImageNumImages,
|
||||
};
|
||||
@@ -18,7 +19,7 @@ pub struct PlanArtcraftFlux1Schnell<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_flux_1_schnell<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftFlux1Schnell<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
// Flux 1 Schnell is text-to-image only. Abort if image inputs are provided and
|
||||
// the caller has opted into strict mode.
|
||||
if request.image_inputs.is_some() {
|
||||
@@ -35,12 +36,12 @@ pub fn plan_generate_image_artcraft_flux_1_schnell<'a>(
|
||||
let aspect_ratio = plan_aspect_ratio(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftFlux1Schnell {
|
||||
Ok(ImageGenerationPlan::ArtcraftFlux1Schnell(PlanArtcraftFlux1Schnell {
|
||||
prompt: request.prompt,
|
||||
aspect_ratio,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
// Flux 1 Schnell supported aspect ratios (identical to Flux 1 Dev):
|
||||
@@ -134,7 +135,6 @@ mod tests {
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_flux_1_schnell_image_request;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_1_schnell_text_to_image::{
|
||||
GenerateFlux1SchnellTextToImageAspectRatio as FlAr,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::angle::flux_2_lora_edit_image_angle::{
|
||||
Flux2LoraEditImageAngleImageSize,
|
||||
Flux2LoraEditImageAngleNumImages,
|
||||
@@ -23,7 +24,7 @@ pub struct PlanArtcraftFlux2LoraAngles<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_flux_2_lora_angles<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftFlux2LoraAngles<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
// Angle models require exactly one input image.
|
||||
@@ -31,7 +32,7 @@ pub fn plan_generate_image_artcraft_flux_2_lora_angles<'a>(
|
||||
let image_size = plan_image_size(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftFlux2LoraAngles {
|
||||
Ok(ImageGenerationPlan::ArtcraftFlux2LoraAngles(PlanArtcraftFlux2LoraAngles {
|
||||
image_input,
|
||||
horizontal_angle: request.horizontal_angle,
|
||||
vertical_angle: request.vertical_angle,
|
||||
@@ -39,7 +40,7 @@ pub fn plan_generate_image_artcraft_flux_2_lora_angles<'a>(
|
||||
image_size,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_single_image_input<'a>(
|
||||
@@ -139,7 +140,6 @@ fn plan_num_images(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_flux_2_lora_angles_image_request;
|
||||
use artcraft_api_defs::generate::image::angle::flux_2_lora_edit_image_angle::{
|
||||
Flux2LoraEditImageAngleImageSize as S,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_pro_11_text_to_image::{
|
||||
GenerateFluxPro11TextToImageAspectRatio, GenerateFluxPro11TextToImageNumImages,
|
||||
};
|
||||
@@ -18,7 +19,7 @@ pub struct PlanArtcraftFluxPro11<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_flux_pro_1p1<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftFluxPro11<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
// Flux Pro 1.1 is text-to-image only. Abort if image inputs are provided and
|
||||
// the caller has opted into strict mode.
|
||||
if request.image_inputs.is_some() {
|
||||
@@ -35,12 +36,12 @@ pub fn plan_generate_image_artcraft_flux_pro_1p1<'a>(
|
||||
let aspect_ratio = plan_aspect_ratio(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftFluxPro11 {
|
||||
Ok(ImageGenerationPlan::ArtcraftFluxPro11(PlanArtcraftFluxPro11 {
|
||||
prompt: request.prompt,
|
||||
aspect_ratio,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
// Flux Pro 1.1 supported aspect ratios (no SquareHd):
|
||||
@@ -134,7 +135,6 @@ mod tests {
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_flux_pro_1p1_image_request;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_pro_11_text_to_image::{
|
||||
GenerateFluxPro11TextToImageAspectRatio as FlAr,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_pro_11_ultra_text_to_image::{
|
||||
GenerateFluxPro11UltraTextToImageAspectRatio, GenerateFluxPro11UltraTextToImageNumImages,
|
||||
};
|
||||
@@ -18,7 +19,7 @@ pub struct PlanArtcraftFluxPro11Ultra<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_flux_pro_1p1_ultra<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftFluxPro11Ultra<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
// Flux Pro 1.1 Ultra is text-to-image only. Abort if image inputs are provided and
|
||||
// the caller has opted into strict mode.
|
||||
if request.image_inputs.is_some() {
|
||||
@@ -35,12 +36,12 @@ pub fn plan_generate_image_artcraft_flux_pro_1p1_ultra<'a>(
|
||||
let aspect_ratio = plan_aspect_ratio(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftFluxPro11Ultra {
|
||||
Ok(ImageGenerationPlan::ArtcraftFluxPro11Ultra(PlanArtcraftFluxPro11Ultra {
|
||||
prompt: request.prompt,
|
||||
aspect_ratio,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
// Flux Pro 1.1 Ultra supported aspect ratios:
|
||||
@@ -137,7 +138,6 @@ mod tests {
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_flux_pro_1p1_ultra_image_request;
|
||||
use artcraft_api_defs::generate::image::text::generate_flux_pro_11_ultra_text_to_image::{
|
||||
GenerateFluxPro11UltraTextToImageAspectRatio as FlAr,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::gpt_image_1p5_multi_function_image_gen::{
|
||||
GptImage1p5MultiFunctionImageGenNumImages, GptImage1p5MultiFunctionImageGenQuality,
|
||||
GptImage1p5MultiFunctionImageGenSize,
|
||||
@@ -24,21 +25,21 @@ pub struct PlanArtcraftGptImage1p5<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_gpt_image_1p5<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftGptImage1p5<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let image_inputs = resolve_image_list_ref(request.image_inputs)?;
|
||||
let image_size = plan_image_size(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftGptImage1p5 {
|
||||
Ok(ImageGenerationPlan::ArtcraftGptImage1p5(PlanArtcraftGptImage1p5 {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
image_size,
|
||||
quality: GptImage1p5MultiFunctionImageGenQuality::Medium,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -123,7 +124,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_gpt_image_1p5_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::gpt_image_1p5_multi_function_image_gen::{
|
||||
GptImage1p5MultiFunctionImageGenNumImages as GN,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::nano_banana_multi_function_image_gen::{
|
||||
NanoBananaMultiFunctionImageGenAspectRatio, NanoBananaMultiFunctionImageGenNumImages,
|
||||
};
|
||||
@@ -21,7 +22,7 @@ pub struct PlanArtcraftNanaBanana<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_nano_banana<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftNanaBanana<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
@@ -29,13 +30,13 @@ pub fn plan_generate_image_artcraft_nano_banana<'a>(
|
||||
let aspect_ratio = plan_aspect_ratio(request.aspect_ratio, is_edit_mode, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftNanaBanana {
|
||||
Ok(ImageGenerationPlan::ArtcraftNanaBanana(PlanArtcraftNanaBanana {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
aspect_ratio,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -148,7 +149,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_nano_banana_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::nano_banana_multi_function_image_gen::{
|
||||
NanoBananaMultiFunctionImageGenAspectRatio as NbAr,
|
||||
|
||||
+4
-4
@@ -5,6 +5,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::nano_banana_2_multi_function_image_gen::{
|
||||
NanaBanana2MultiFunctionImageGenAspectRatio, NanaBanana2MultiFunctionImageGenImageResolution,
|
||||
NanaBanana2MultiFunctionImageGenNumImages,
|
||||
@@ -24,7 +25,7 @@ pub struct PlanArtcraftNanaBanana2<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_nano_banana_2<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftNanaBanana2<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
@@ -33,14 +34,14 @@ pub fn plan_generate_image_artcraft_nano_banana_2<'a>(
|
||||
let resolution = plan_resolution(request.resolution, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftNanaBanana2 {
|
||||
Ok(ImageGenerationPlan::ArtcraftNanaBanana2(PlanArtcraftNanaBanana2 {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
aspect_ratio,
|
||||
resolution,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -172,7 +173,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_nano_banana_2_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::nano_banana_2_multi_function_image_gen::{
|
||||
NanaBanana2MultiFunctionImageGenAspectRatio as Nb2Ar,
|
||||
|
||||
+4
-4
@@ -5,6 +5,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::nano_banana_pro_multi_function_image_gen::{
|
||||
NanoBananaProMultiFunctionImageGenAspectRatio, NanoBananaProMultiFunctionImageGenImageResolution,
|
||||
NanoBananaProMultiFunctionImageGenNumImages,
|
||||
@@ -24,7 +25,7 @@ pub struct PlanArtcraftNanaBananaPro<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_nano_banana_pro<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftNanaBananaPro<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
@@ -33,14 +34,14 @@ pub fn plan_generate_image_artcraft_nano_banana_pro<'a>(
|
||||
let resolution = plan_resolution(request.resolution, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftNanaBananaPro {
|
||||
Ok(ImageGenerationPlan::ArtcraftNanaBananaPro(PlanArtcraftNanaBananaPro {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
aspect_ratio,
|
||||
resolution,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -172,7 +173,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::nano_banana_pro_multi_function_image_gen::{
|
||||
NanoBananaProMultiFunctionImageGenAspectRatio as NbpAr,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::angle::qwen_edit_2511_edit_image_angle::{
|
||||
QwenEdit2511EditImageAngleImageSize,
|
||||
QwenEdit2511EditImageAngleNumImages,
|
||||
@@ -24,7 +25,7 @@ pub struct PlanArtcraftQwenEdit2511Angles<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_qwen_edit_2511_angles<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftQwenEdit2511Angles<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
// Angle models require exactly one input image.
|
||||
@@ -32,7 +33,7 @@ pub fn plan_generate_image_artcraft_qwen_edit_2511_angles<'a>(
|
||||
let image_size = plan_image_size(request.aspect_ratio, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftQwenEdit2511Angles {
|
||||
Ok(ImageGenerationPlan::ArtcraftQwenEdit2511Angles(PlanArtcraftQwenEdit2511Angles {
|
||||
prompt: request.prompt,
|
||||
image_input,
|
||||
horizontal_angle: request.horizontal_angle,
|
||||
@@ -41,7 +42,7 @@ pub fn plan_generate_image_artcraft_qwen_edit_2511_angles<'a>(
|
||||
image_size,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_single_image_input<'a>(
|
||||
@@ -141,7 +142,6 @@ fn plan_num_images(
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_qwen_edit_2511_angles_image_request;
|
||||
use artcraft_api_defs::generate::image::angle::qwen_edit_2511_edit_image_angle::{
|
||||
QwenEdit2511EditImageAngleImageSize as S,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_v4_multi_function_image_gen::{
|
||||
BytedanceSeedreamV4MultiFunctionImageGenImageSize,
|
||||
BytedanceSeedreamV4MultiFunctionImageGenNumImages,
|
||||
@@ -22,7 +23,7 @@ pub struct PlanArtcraftSeedream4<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_seedream_4<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftSeedream4<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
@@ -30,13 +31,13 @@ pub fn plan_generate_image_artcraft_seedream_4<'a>(
|
||||
let image_size = plan_image_size(request.aspect_ratio, is_edit_mode, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftSeedream4 {
|
||||
Ok(ImageGenerationPlan::ArtcraftSeedream4(PlanArtcraftSeedream4 {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
image_size,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -147,7 +148,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_seedream_4_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_v4_multi_function_image_gen::{
|
||||
BytedanceSeedreamV4MultiFunctionImageGenImageSize as S,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_v4p5_multi_function_image_gen::{
|
||||
BytedanceSeedreamV4p5MultiFunctionImageGenImageSize,
|
||||
BytedanceSeedreamV4p5MultiFunctionImageGenNumImages,
|
||||
@@ -22,7 +23,7 @@ pub struct PlanArtcraftSeedream4p5<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_seedream_4p5<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftSeedream4p5<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
@@ -30,13 +31,13 @@ pub fn plan_generate_image_artcraft_seedream_4p5<'a>(
|
||||
let image_size = plan_image_size(request.aspect_ratio, is_edit_mode, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftSeedream4p5 {
|
||||
Ok(ImageGenerationPlan::ArtcraftSeedream4p5(PlanArtcraftSeedream4p5 {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
image_size,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -147,7 +148,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_seedream_4p5_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_v4p5_multi_function_image_gen::{
|
||||
BytedanceSeedreamV4p5MultiFunctionImageGenImageSize as S,
|
||||
|
||||
+4
-4
@@ -4,6 +4,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_5_lite_multi_function_image_gen::{
|
||||
BytedanceSeedream5LiteMultiFunctionImageGenImageSize,
|
||||
BytedanceSeedream5LiteMultiFunctionImageGenNumImages,
|
||||
@@ -22,7 +23,7 @@ pub struct PlanArtcraftSeedream5Lite<'a> {
|
||||
|
||||
pub fn plan_generate_image_artcraft_seedream_5_lite<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanArtcraftSeedream5Lite<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
@@ -30,13 +31,13 @@ pub fn plan_generate_image_artcraft_seedream_5_lite<'a>(
|
||||
let image_size = plan_image_size(request.aspect_ratio, is_edit_mode, strategy)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanArtcraftSeedream5Lite {
|
||||
Ok(ImageGenerationPlan::ArtcraftSeedream5Lite(PlanArtcraftSeedream5Lite {
|
||||
prompt: request.prompt,
|
||||
image_inputs,
|
||||
image_size,
|
||||
num_images,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref<'a>(
|
||||
@@ -148,7 +149,6 @@ mod tests {
|
||||
use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use crate::test_helpers::base_seedream_5_lite_image_request;
|
||||
use artcraft_api_defs::generate::image::multi_function::bytedance_seedream_5_lite_multi_function_image_gen::{
|
||||
BytedanceSeedream5LiteMultiFunctionImageGenImageSize as S,
|
||||
|
||||
+8
-4
@@ -5,6 +5,7 @@ use crate::client::request_mismatch_mitigation_strategy::RequestMismatchMitigati
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_image::generate_image_request::GenerateImageRequest;
|
||||
use crate::generate::generate_image::image_generation_plan::ImageGenerationPlan;
|
||||
use fal_client::requests::webhook::image::edit::enqueue_nano_banana_pro_edit_image_webhook::EnqueueNanoBananaProEditImageAspectRatio;
|
||||
use fal_client::requests::webhook::image::text::enqueue_nano_banana_pro_text_to_image_webhook::EnqueueNanoBananaProTextToImageAspectRatio;
|
||||
|
||||
@@ -44,7 +45,7 @@ pub struct PlanFalNanaBananaPro<'a> {
|
||||
|
||||
pub fn plan_generate_image_fal_nano_banana_pro<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> Result<PlanFalNanaBananaPro<'a>, ArtcraftRouterError> {
|
||||
) -> Result<ImageGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let strategy = request.request_mismatch_mitigation_strategy;
|
||||
let is_edit_mode = request.image_inputs.is_some();
|
||||
let image_urls = resolve_image_list_ref(request.image_inputs)?;
|
||||
@@ -53,14 +54,14 @@ pub fn plan_generate_image_fal_nano_banana_pro<'a>(
|
||||
let resolution = plan_resolution(request.resolution)?;
|
||||
let num_images = plan_num_images(request.image_batch_count, strategy)?;
|
||||
|
||||
Ok(PlanFalNanaBananaPro {
|
||||
Ok(ImageGenerationPlan::FalNanaBananaPro(PlanFalNanaBananaPro {
|
||||
prompt: request.prompt,
|
||||
image_urls,
|
||||
t2i_aspect_ratio,
|
||||
edit_aspect_ratio,
|
||||
resolution,
|
||||
num_images,
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_image_list_ref(
|
||||
@@ -263,7 +264,10 @@ mod tests {
|
||||
fn build_plan<'a>(
|
||||
request: &'a GenerateImageRequest<'a>,
|
||||
) -> PlanFalNanaBananaPro<'a> {
|
||||
plan_generate_image_fal_nano_banana_pro(request).expect("plan should succeed")
|
||||
let ImageGenerationPlan::FalNanaBananaPro(plan) = plan_generate_image_fal_nano_banana_pro(request).expect("plan should succeed") else {
|
||||
panic!("expected FalNanaBananaPro variant")
|
||||
};
|
||||
plan
|
||||
}
|
||||
|
||||
// ── Image inputs / mode detection ────────────────────────────────────────────
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
use crate::generate::generate_splat::plan::artcraft::plan_generate_splat_artcraft_marble_0p1_mini::PlanArtcraftMarble0p1Mini;
|
||||
use crate::generate::generate_splat::splat_generation_cost_estimate::SplatGenerationCostEstimate;
|
||||
use world_labs_api::api::api_types::world_labs_model::WorldLabsModel;
|
||||
use world_labs_api::pricing::check_pricing::{calculate_cost, InputType};
|
||||
use worldlabs_api_client::api::api_types::world_labs_model::WorldLabsModel;
|
||||
use worldlabs_api_client::pricing::check_pricing::{calculate_cost, InputType};
|
||||
|
||||
pub(crate) fn estimate_splat_cost_artcraft_marble_0p1_mini(
|
||||
plan: &PlanArtcraftMarble0p1Mini<'_>,
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
use crate::generate::generate_splat::plan::artcraft::plan_generate_splat_artcraft_marble_0p1_plus::PlanArtcraftMarble0p1Plus;
|
||||
use crate::generate::generate_splat::splat_generation_cost_estimate::SplatGenerationCostEstimate;
|
||||
use world_labs_api::api::api_types::world_labs_model::WorldLabsModel;
|
||||
use world_labs_api::pricing::check_pricing::{calculate_cost, InputType};
|
||||
use worldlabs_api_client::api::api_types::world_labs_model::WorldLabsModel;
|
||||
use worldlabs_api_client::pricing::check_pricing::{calculate_cost, InputType};
|
||||
|
||||
pub(crate) fn estimate_splat_cost_artcraft_marble_0p1_plus(
|
||||
plan: &PlanArtcraftMarble0p1Plus<'_>,
|
||||
|
||||
+15
-11
@@ -28,20 +28,24 @@ impl<'a> GenerateSplatRequest<'a> {
|
||||
/// Read the splat generation request, construct a plan, then yield a means to execute it.
|
||||
pub fn build(&self) -> Result<SplatGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
match self.provider {
|
||||
Provider::Artcraft => match self.model {
|
||||
CommonSplatModel::Marble0p1Mini => {
|
||||
plan_generate_splat_artcraft_marble_0p1_mini(self).map(SplatGenerationPlan::ArtcraftMarble0p1Mini)
|
||||
}
|
||||
CommonSplatModel::Marble0p1Plus => {
|
||||
plan_generate_splat_artcraft_marble_0p1_plus(self).map(SplatGenerationPlan::ArtcraftMarble0p1Plus)
|
||||
}
|
||||
},
|
||||
Provider::Fal => Err(ArtcraftRouterError::UnsupportedModel(
|
||||
format!("Splat generation via Fal is not yet supported (model: {:?})", self.model)
|
||||
)),
|
||||
Provider::Artcraft => self.build_artcraft(),
|
||||
_ => self.unsupported_provider(),
|
||||
}
|
||||
}
|
||||
|
||||
fn build_artcraft(&self) -> Result<SplatGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
match self.model {
|
||||
CommonSplatModel::Marble0p1Mini => plan_generate_splat_artcraft_marble_0p1_mini(self),
|
||||
CommonSplatModel::Marble0p1Plus => plan_generate_splat_artcraft_marble_0p1_plus(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn unsupported_provider(&self) -> Result<SplatGenerationPlan<'_>, ArtcraftRouterError> {
|
||||
Err(ArtcraftRouterError::UnsupportedModel(
|
||||
format!("Splat generation for model `{:?}` is not supported for provider {:?}", self.model, self.provider)
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_or_generate_idempotency_token(&self) -> String {
|
||||
self.idempotency_token.map(|t| t.to_string())
|
||||
.unwrap_or_else(|| uuid::Uuid::new_v4().to_string())
|
||||
|
||||
+4
-3
@@ -2,6 +2,7 @@ use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_splat::generate_splat_request::GenerateSplatRequest;
|
||||
use crate::generate::generate_splat::splat_generation_plan::SplatGenerationPlan;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -13,14 +14,14 @@ pub struct PlanArtcraftMarble0p1Mini<'a> {
|
||||
|
||||
pub fn plan_generate_splat_artcraft_marble_0p1_mini<'a>(
|
||||
request: &'a GenerateSplatRequest<'a>,
|
||||
) -> Result<PlanArtcraftMarble0p1Mini<'a>, ArtcraftRouterError> {
|
||||
) -> Result<SplatGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let reference_image = resolve_single_image_ref(request.reference_images)?;
|
||||
|
||||
Ok(PlanArtcraftMarble0p1Mini {
|
||||
Ok(SplatGenerationPlan::ArtcraftMarble0p1Mini(PlanArtcraftMarble0p1Mini {
|
||||
prompt: request.prompt,
|
||||
reference_image,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_single_image_ref<'a>(
|
||||
|
||||
+4
-3
@@ -2,6 +2,7 @@ use crate::api::image_list_ref::ImageListRef;
|
||||
use crate::errors::artcraft_router_error::ArtcraftRouterError;
|
||||
use crate::errors::client_error::ClientError;
|
||||
use crate::generate::generate_splat::generate_splat_request::GenerateSplatRequest;
|
||||
use crate::generate::generate_splat::splat_generation_plan::SplatGenerationPlan;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -13,14 +14,14 @@ pub struct PlanArtcraftMarble0p1Plus<'a> {
|
||||
|
||||
pub fn plan_generate_splat_artcraft_marble_0p1_plus<'a>(
|
||||
request: &'a GenerateSplatRequest<'a>,
|
||||
) -> Result<PlanArtcraftMarble0p1Plus<'a>, ArtcraftRouterError> {
|
||||
) -> Result<SplatGenerationPlan<'a>, ArtcraftRouterError> {
|
||||
let reference_image = resolve_single_image_ref(request.reference_images)?;
|
||||
|
||||
Ok(PlanArtcraftMarble0p1Plus {
|
||||
Ok(SplatGenerationPlan::ArtcraftMarble0p1Plus(PlanArtcraftMarble0p1Plus {
|
||||
prompt: request.prompt,
|
||||
reference_image,
|
||||
idempotency_token: request.get_or_generate_idempotency_token(),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
fn resolve_single_image_ref<'a>(
|
||||
|
||||
+2
@@ -69,6 +69,8 @@ mod tests {
|
||||
start_frame: None,
|
||||
end_frame: None,
|
||||
reference_images: None,
|
||||
reference_videos: None,
|
||||
reference_audio: None,
|
||||
resolution: None,
|
||||
aspect_ratio: None,
|
||||
duration_seconds: Some(duration_seconds),
|
||||
|
||||
+2
@@ -69,6 +69,8 @@ mod tests {
|
||||
start_frame: None,
|
||||
end_frame: None,
|
||||
reference_images: None,
|
||||
reference_videos: None,
|
||||
reference_audio: None,
|
||||
resolution: None,
|
||||
aspect_ratio: None,
|
||||
duration_seconds: Some(duration_seconds),
|
||||
|
||||
+2
@@ -72,6 +72,8 @@ mod tests {
|
||||
start_frame: None,
|
||||
end_frame: None,
|
||||
reference_images: None,
|
||||
reference_videos: None,
|
||||
reference_audio: None,
|
||||
resolution: None,
|
||||
aspect_ratio: None,
|
||||
duration_seconds: Some(duration_seconds),
|
||||
|
||||
+13
-6
@@ -1,6 +1,6 @@
|
||||
use artcraft_api_defs::generate::video::multi_function::seedance_2p0_multi_function_video_gen::Seedance2p0BatchCount;
|
||||
use seedance2pro::creds::seedance2pro_session::Seedance2ProSession;
|
||||
use seedance2pro::requests::generate_video::generate_video::{BatchCount, GenerateVideoArgs, Resolution};
|
||||
use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession;
|
||||
use seedance2pro_client::requests::generate_video::generate_video::{BatchCount, GenerateVideoArgs, ModelType, Resolution};
|
||||
|
||||
use crate::generate::generate_video::plan::artcraft::plan_generate_video_artcraft_seedance2p0::PlanArtcraftSeedance2p0;
|
||||
use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate;
|
||||
@@ -22,6 +22,7 @@ pub (crate) fn estimate_video_cost_artcraft_seedance2p0(
|
||||
|
||||
let args = GenerateVideoArgs {
|
||||
session: &dummy_session,
|
||||
model_type: ModelType::Seedance2Pro,
|
||||
prompt: String::new(),
|
||||
resolution: Resolution::Square1x1,
|
||||
duration_seconds,
|
||||
@@ -31,6 +32,10 @@ pub (crate) fn estimate_video_cost_artcraft_seedance2p0(
|
||||
start_frame_url: None,
|
||||
end_frame_url: None,
|
||||
reference_image_urls: None,
|
||||
reference_video_urls: None,
|
||||
reference_audio_urls: None,
|
||||
use_face_blur_hack: None,
|
||||
host_override: None,
|
||||
};
|
||||
|
||||
let cost_in_usd_cents = args.estimate_cost_in_usd_cents();
|
||||
@@ -61,6 +66,8 @@ mod tests {
|
||||
start_frame: None,
|
||||
end_frame: None,
|
||||
reference_images: None,
|
||||
reference_videos: None,
|
||||
reference_audio: None,
|
||||
resolution: None,
|
||||
aspect_ratio: None,
|
||||
duration_seconds: Some(duration_seconds),
|
||||
@@ -90,9 +97,9 @@ mod tests {
|
||||
assert_eq!(estimate_usd_cents(5, 2), 160);
|
||||
assert_eq!(estimate_usd_cents(15, 2), 480);
|
||||
|
||||
// Batch 4 = 3× (not 4×)
|
||||
assert_eq!(estimate_usd_cents(4, 4), 192);
|
||||
assert_eq!(estimate_usd_cents(5, 4), 240);
|
||||
assert_eq!(estimate_usd_cents(15, 4), 720);
|
||||
// Batch 4 = 4×
|
||||
assert_eq!(estimate_usd_cents(4, 4), 256);
|
||||
assert_eq!(estimate_usd_cents(5, 4), 320);
|
||||
assert_eq!(estimate_usd_cents(15, 4), 960);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
pub (crate) mod artcraft;
|
||||
pub (crate) mod muapi;
|
||||
pub (crate) mod seedance2pro;
|
||||
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
use crate::generate::generate_video::plan::muapi::plan_generate_video_muapi_seedance2p0::{
|
||||
MuapiSeedance2p0Mode, PlanMuapiSeedance2p0,
|
||||
};
|
||||
use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate;
|
||||
use muapi_client::creds::muapi_api_key::MuapiApiKey;
|
||||
use muapi_client::creds::muapi_session::MuapiSession;
|
||||
use muapi_client::requests::seedance_2p0_image_to_video::seedance_2p0_image_to_video::Seedance2p0ImageToVideoArgs;
|
||||
use muapi_client::requests::seedance_2p0_text_to_video::seedance_2p0_text_to_video::Seedance2p0TextToVideoArgs;
|
||||
|
||||
pub(crate) fn estimate_video_cost_muapi_seedance2p0(
|
||||
plan: &PlanMuapiSeedance2p0,
|
||||
) -> VideoGenerationCostEstimate {
|
||||
// A dummy session is sufficient — cost estimation does not make any network calls.
|
||||
let dummy_session = MuapiSession::new(MuapiApiKey::new(String::new()));
|
||||
|
||||
let cost_in_usd_cents;
|
||||
let cost_in_credits;
|
||||
|
||||
match &plan.mode {
|
||||
MuapiSeedance2p0Mode::TextToVideo { aspect_ratio, duration, quality } => {
|
||||
let args = Seedance2p0TextToVideoArgs {
|
||||
session: &dummy_session,
|
||||
prompt: String::new(),
|
||||
aspect_ratio: *aspect_ratio,
|
||||
duration: *duration,
|
||||
quality: *quality,
|
||||
};
|
||||
|
||||
cost_in_usd_cents = args.estimate_cost_in_usd_cents();
|
||||
|
||||
// NB: This is off by a factor of 100 because they use a fractional system.
|
||||
cost_in_credits = (args.estimate_credits() * 100.0f64).round() as u64;
|
||||
}
|
||||
MuapiSeedance2p0Mode::ImageToVideo { aspect_ratio, duration, quality, .. } => {
|
||||
let args = Seedance2p0ImageToVideoArgs {
|
||||
session: &dummy_session,
|
||||
prompt: String::new(),
|
||||
image_urls: vec![],
|
||||
aspect_ratio: *aspect_ratio,
|
||||
duration: *duration,
|
||||
quality: *quality,
|
||||
};
|
||||
|
||||
cost_in_usd_cents = args.estimate_cost_in_usd_cents();
|
||||
|
||||
// NB: This is off by a factor of 100 because they use a fractional system.
|
||||
cost_in_credits = (args.estimate_credits() * 100.0f64).round() as u64;
|
||||
}
|
||||
}
|
||||
|
||||
VideoGenerationCostEstimate {
|
||||
cost_in_credits: Some(cost_in_credits),
|
||||
cost_in_usd_cents: Some(cost_in_usd_cents),
|
||||
is_free: false,
|
||||
is_unlimited: false,
|
||||
is_rate_limited: false,
|
||||
has_watermark: false,
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
pub mod estimate_video_cost_muapi_seedance2p0;
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
use seedance2pro_client::creds::seedance2pro_session::Seedance2ProSession;
|
||||
use seedance2pro_client::requests::generate_video::generate_video::{GenerateVideoArgs, ModelType, Resolution};
|
||||
|
||||
use crate::generate::generate_video::plan::seedance2pro::plan_generate_video_seedance2pro_seedance2p0::PlanSeedance2proSeedance2p0;
|
||||
use crate::generate::generate_video::video_generation_cost_estimate::VideoGenerationCostEstimate;
|
||||
|
||||
pub(crate) fn estimate_video_cost_seedance2pro_seedance2p0(
|
||||
plan: &PlanSeedance2proSeedance2p0,
|
||||
) -> VideoGenerationCostEstimate {
|
||||
// A dummy session is sufficient — cost estimation does not make any network calls.
|
||||
let dummy_session = Seedance2ProSession::from_cookies_string(String::new());
|
||||
|
||||
let args = GenerateVideoArgs {
|
||||
session: &dummy_session,
|
||||
model_type: ModelType::Seedance2Pro,
|
||||
prompt: String::new(),
|
||||
resolution: Resolution::Square1x1, // Resolution does not affect cost
|
||||
duration_seconds: plan.duration_seconds,
|
||||
batch_count: plan.batch_count,
|
||||
start_frame_url: None,
|
||||
end_frame_url: None,
|
||||
reference_image_urls: None,
|
||||
reference_video_urls: None,
|
||||
reference_audio_urls: None,
|
||||
use_face_blur_hack: None,
|
||||
host_override: None,
|
||||
};
|
||||
|
||||
let cost_in_credits = args.estimate_credits();
|
||||
let cost_in_usd_cents = args.estimate_cost_in_usd_cents();
|
||||
|
||||
VideoGenerationCostEstimate {
|
||||
cost_in_credits: Some(cost_in_credits as u64),
|
||||
cost_in_usd_cents: Some(cost_in_usd_cents),
|
||||
is_free: false,
|
||||
is_unlimited: false,
|
||||
is_rate_limited: false,
|
||||
has_watermark: false,
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
pub mod estimate_video_cost_seedance2pro_seedance2p0;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user