Compare commits

...
Author SHA1 Message Date
Brandon Thomas 398c56d7eb page works 2026-03-25 12:29:38 -04:00
Brandon Thomas ba21368323 don't log these 2026-03-25 10:47:31 -04:00
Brandon Thomas 0750b9fe10 that worked! 2026-03-25 10:46:57 -04:00
Brandon Thomas 05a26b124e seems to work 2026-03-25 10:41:58 -04:00
Brandon Thomas a394ee5a96 create alert api 2026-03-25 02:30:11 -04:00
Brandon Thomas c35ea620b3 add rootly stub 2026-03-25 02:18:58 -04:00
Brandon Thomas 389b1c3d17 update website download links 2026-03-25 00:39:01 -04:00
Brandon Thomas f9148d3cf6 seedance 2 fast (#1215) 2026-03-25 00:26:19 -04:00
Brandon Thomas 64d66aa9f0 Batched Seedance 2.0 Job Polling (#1214) 2026-03-24 17:20:31 -04:00
Brandon Thomas 82695725cd seedance whitelist for faster generations (#1213) 2026-03-24 15:54:52 -04:00
Brandon Thomas 53f9032603 simplify seedance 2.0 handler flow 2026-03-24 14:43:29 -04:00
Brandon Thomas 69c03045fd .gitignore 2026-03-24 14:38:09 -04:00
Brandon Thomas e82f070d1d bump artcraft 0.19 -> 0.20 (#1212) 2026-03-24 14:30:32 -04:00
BFlat 459960e64f remove confusing system prompt toggle 2026-03-24 22:23:40 +07:00
BFlat d1266b7591 reprompt/recreate updated to use prompts api (#1208) 2026-03-24 21:59:38 +07:00
BFlat 4bdb1c89a4 password reset fail message 2026-03-24 16:59:22 +07:00
Brandon Thomas 4d53d9af18 mod user signup list (#1207) 2026-03-24 05:53:44 -04:00
Brandon Thomas 2bc00d7f80 richer errors for password reset failures (#1206) 2026-03-24 04:52:25 -04:00
Brandon Thomas f48cb41f21 plumb prompt duration for video models (#1205) 2026-03-24 03:53:05 -04:00
Brandon Thomas d24508aee9 alter prompts table durations (#1204) 2026-03-24 03:04:45 -04:00
Brandon Thomas 1985d9acd7 bump artcraft 0.18 -> 0.19 (#1203) 2026-03-24 02:31:44 -04:00
Brandon Thomas 0f90981f30 fix windows via anstyle-wincon downgrade (#1202) 2026-03-24 02:30:48 -04:00
Brandon Thomas 8d1ca743db bump artcraft 0.17 -> 0.18 (#1201) 2026-03-24 02:15:46 -04:00
Brandon Thomas 72403ad4d8 record prompt info (#1200) 2026-03-24 01:48:46 -04:00
Tanish Manku 8d731f1155 Text2Image - Image batches: Arrow key support (#1198) 2026-03-23 20:57:50 -07:00
Brandon Thomas 516d740e97 include class of model in prompt info 2026-03-23 21:53:00 -04:00
Brandon Thomas 95eeafd6f0 enrich prompts (#1197) 2026-03-23 21:50:18 -04:00
Brandon Thomas 0db5646deb prompts: new database columns (#1196) 2026-03-23 15:59:07 -04:00
Brandon Thomas ac839e2c39 remove enums crates (#1195)
I tried. I'll have to make a better attempt in the future to divorce DB
schema definitions from API definitions (and worse - API clients).
2026-03-23 14:43:57 -04:00
Brandon Thomas 65334e12be More notes on repo 2026-03-23 14:23:50 -04:00
Brandon Thomas 7e644c3e98 Root CLAUDE.md 2026-03-23 14:07:24 -04:00
BFlat bb3fe2df2d reprompt (recreate) button (#1194)
<img width="1219" height="790"
alt="{A15AF77F-C555-4C85-BC15-B4B8D44D2248}"
src="https://github.com/user-attachments/assets/ec4b52a2-68c4-42b0-88fc-00ee3b322321"
/>

A "recreate" button in the media lightbox modal.
On clicked, it will prefill the image or video promptbox with the same
model, prompt and ref images that was used to generate that media the
button was clicked from.

Temporary and doesnt support seedance video/audio ref yet.
2026-03-23 11:14:01 +07:00
Brandon Thomas a92ad2eb3a remove unused enum imports (#1192) 2026-03-22 18:27:00 -04:00
Brandon Thomas 78e7d08f04 all_variants enum methods (#1191) 2026-03-22 18:10:56 -04:00
Brandon Thomas be18036bf6 enums helper methods, cleanup (#1190) 2026-03-22 17:34:32 -04:00
Brandon Thomas 83a8852cef enums split - but just the enums (#1188) 2026-03-22 12:46:29 -04:00
BFlat afed8688a5 resiable image and video prompt boxes 2026-03-20 21:00:10 +07:00
BFlat 9d380decf9 seedance multi generations at a time (#1185) 2026-03-20 20:36:45 +07:00
BFlat 4905cdcd3d angles update 2026-03-20 20:20:50 +07:00
Brandon Thomas b709b6e764 remove fal.rs and move everything into fal_client (#1183) 2026-03-19 20:11:34 -04:00
Brandon Thomas 58d2665f0e seedance2pro -> kinovi domain name migration (#1181) 2026-03-19 13:49:43 -04:00
BFlat 72bf6738e1 website library filter links, added 3d, and video thumbnails to prope… (#1174)
…rly show
2026-03-19 13:21:19 +07:00
Brandon Thomas 1178bb7ebf update utoipa and swagger doc gen (#1171) 2026-03-18 22:49:04 -04:00
Brandon Thomas fea20c417c update builds to trigger only on relevant changes (#1170) 2026-03-18 22:07:20 -04:00
Brandon Thomas 5a07903870 organize root cargo.toml 2026-03-18 21:51:06 -04:00
Brandon Thomas 2063434304 centralized dependency configuration (#1169) 2026-03-18 21:45:42 -04:00
Brandon Thomas b386fd5d88 bump artcraft 0.16.0 -> 0.17.0 (#1168) 2026-03-18 21:19:31 -04:00
Brandon Thomas 1626dda8b4 fix windows builds (#1167) 2026-03-18 21:17:54 -04:00
Brandon Thomas ebe365703b refactor testing crates (#1166) 2026-03-18 21:06:46 -04:00
Brandon Thomas 5caa578b86 Bump ArtCraft 0.15 -> 0.16 (#1165) 2026-03-18 20:34:21 -04:00
Brandon Thomas 2da5fbcc58 cleanup refactor #2 (#1164)
- move a lot of "deprecated" crates so we don't use them
- kill several dead crates
- rename crates to be more semantic/clear
- roll back broken sha3 version bump
2026-03-18 20:32:50 -04:00
Tanish Manku 588650b1b5 2D: Ordered draw instead of Z-Index + Other improvements (#1163)
Paint/Mask cursor now draws properly regardless of canvas scale and drag
offset.
Inpainting now has its own brush with add and subtract actions.
A total node array is used for ordered-rendering of nodes, which fixes
the layer forward/backward operations.
2026-03-18 15:53:32 -07:00
Brandon Thomas 761bf832a5 bump misc dep versions (#1162)
Some deps require manual upgrade - will cycle back
2026-03-18 17:45:58 -04:00
Brandon Thomas df4d46cc9d rename both worldlabs crates (#1161)
- api client crate
- consumer client crate
2026-03-18 16:49:04 -04:00
Brandon Thomas 19599e00be still broken in google ads 2026-03-18 15:44:19 -04:00
Brandon Thomas 2f2ac350bc more redirects 2026-03-18 15:41:54 -04:00
Brandon Thomas bbd0871c04 google ads broken link 2026-03-18 15:40:32 -04:00
Brandon Thomas 7d20ac3d16 grab bag of refactoring, cleanup, etc. (#1160)
- rename seedance2pro crate
- deprecate methods
- remove smtp client
- etc.
2026-03-18 13:36:29 -04:00
Brandon Thomas f9c1201fc6 add thumbnail job sharding and logging (#1158) 2026-03-18 11:42:22 -04:00
Brandon Thomas 0ac57a5448 thumbnail job (#1157) 2026-03-18 02:59:18 -04:00
bflatastic b88f5c536b please upload mp4 file toast - video ref 2026-03-18 08:51:57 +07:00
bflatastic 7edba0d9d5 failed to upload toast for video ref 2026-03-18 08:40:30 +07:00
bflatastic 76ae56a051 updated to duration slider 2026-03-18 07:46:23 +07:00
bflatastic 75a92fe204 popover/dropdown to support scroll on smaller screen height 2026-03-18 07:22:54 +07:00
Tanish Manku 31c507a404 2D: Composite draw layer into ref image for default gen (#1156)
3D nodes and drawings on the canvas were missing from the reference
image sent to the model in the default generation path. The fix mirrors
the Nano Banana Pro approach: render a composite of the base image and
the draw layer, upload it via uploadSceneSnapshot, and pass it as
scene_image_media_token rather than putting editedImageToken in
image_media_tokens.
2026-03-17 14:59:21 -07:00
Brandon Thomas 42bb07c110 hide website image and video gen for now (it's slightly broken) (#1155) 2026-03-17 16:03:02 -04:00
Brandon Thomas 5afa81b57d alter media_files to include thumbnail information (#1154) 2026-03-17 15:42:44 -04:00
Brandon Thomas 81cadf35b0 fix compile error 2026-03-17 09:46:50 -04:00
BFlat d4b3579915 web image and video generations (#1146)
Image and video generation pages on getartcraft website.
2026-03-17 20:36:29 +07:00
Brandon Thomas 7cd8c0299b artcraft router: seedance (#1153)
add multiple providers to artcraft router for seedance
2026-03-16 22:43:50 -04:00
Brandon Thomas 87296752a5 Use muapi as backup (#1152)
Possible problem in our Seedance 2.0 provider means we need a backup.
This is here in case we need it.

Muapi is inferior for several reasons:

- Videos contain watermarks
- Videos cost 2x as much
- Not as many aspect ratio controls
- Not as many duration controls
- No starting frame / ending frame
- No video references
- No audio references

It does seem fast, however.
2026-03-16 17:15:53 -04:00
Brandon Thomas 1416c5cd17 bump 0.14 -> 0.15 2026-03-16 13:27:54 -04:00
BFlat de29444626 allow playing audio ref in seedance prompt input (#1151) 2026-03-16 22:02:39 +07:00
Brandon Thomas 41988a4462 plumb references to seedance (#1150) 2026-03-16 10:49:00 -04:00
BFlat 4c0c536fb0 video and audio references seedance 2.0 (#1121)
<img width="846" height="544" alt="image"
src="https://github.com/user-attachments/assets/1ca92a7e-1faa-47a4-b32c-24d9587aff61"
/>
<img width="374" height="308" alt="image"
src="https://github.com/user-attachments/assets/2331fc09-b576-4556-9a56-225d24eb30e1"
/>

Do not merge: awaiting backend.
2026-03-16 09:26:26 -04:00
bflatastic b15a5d532a angles history stack base thumbnail to use cdn image instead of blob 2026-03-16 19:55:30 +07:00
Brandon Thomas 8ae983ee32 seedance omni video (#1148) 2026-03-16 08:53:47 -04:00
bflatastic 279a79e60a angles local upload thumbnails not showing and get rid of double toast 2026-03-16 19:48:33 +07:00
bflatastic ebd2a276f9 body font updates and fixed title font in app 2026-03-14 15:52:02 +07:00
bflatastic 0d2f1cfa2c website and app font update 2026-03-14 13:13:34 +07:00
Tanish Manku 3592111019 Improve 2D (PageDraw) render stability and performance (#1143)
Generous use of caching used for react elements. Made a pretty
significant difference too.
Minor refactor to move helper functions outside instead of within
component tree.
2026-03-13 16:42:11 -07:00
Tanish Manku 9d12603d1f 2D Editor support for 3D objects (#1142)
3D objects can now be drag-n-dropped from gallery onto 2D canvas, with
support for scale, rotation and FOV changes.
History is tracks so changes support undo/redo as well.
2026-03-13 16:35:46 -07:00
bflatastic 8902f77a18 Show both enum failure reason and dynamic failure message in task queue 2026-03-14 04:18:40 +07:00
Brandon Thomas 6d91b5616f add failure messages to backend + tauri (#1141) 2026-03-13 13:45:54 -04:00
Brandon Thomas 3783c194e3 make job statuses forward- and backwards- compatible (#1140)
this could have possibly been breaking older clients
2026-03-13 10:44:29 -04:00
bflatastic b7770d5566 performance fix - thumbnails to load smaller images not full size 2026-03-13 13:17:05 +07:00
bflatastic 2fb1eb957b removed generation count blocker (image) 2026-03-13 09:30:09 +07:00
Brandon Thomas 9b4ffa7986 long lived url tech debt hurting local dev (#1139)
kill some local dev tech debt on url construction
2026-03-12 21:34:31 -04:00
bflatastic 2dca4884b1 seedance 2.0 temporary alerts 2026-03-12 22:22:23 +07:00
bflatastic 1d280ba2e0 build fix 3 2026-03-12 21:35:29 +07:00
bflatastic 777758dc16 build fix 2 2026-03-12 21:23:43 +07:00
bflatastic f2cf78514b build fix 2026-03-12 21:18:51 +07:00
BFlat c04586c785 genhub start mock to ui (#1138) 2026-03-12 21:12:46 +07:00
BFlat fd89d5ab39 Revert nextjs genhub (#1137) 2026-03-12 15:49:24 +07:00
BFlat bbfbc40147 fix react version mismatch genhub 2026-03-12 15:36:55 +07:00
BFlat 76d120916b downgrade nextjs version for genhub (#1136) 2026-03-12 15:30:16 +07:00
BFlat efb33bfe38 fix: replace bare libs/ import paths with workspace package names 2026-03-12 14:37:59 +07:00
BFlat e7d1d796e1 nx version fixed to before and path (#1135) 2026-03-12 14:29:52 +07:00
BFlat fc81854b99 genhub to use nextjs instead of vite for seo (#1134) 2026-03-12 11:14:41 +07:00
bflatastic 6e9981acc2 genhub netlify redirects 2026-03-12 01:40:12 +07:00
bflatastic 94637e0d0b netlify build file for genhub 2026-03-12 01:31:03 +07:00
bflatastic 04b6957dfd netlify build command for genhub 2026-03-12 01:24:32 +07:00
BFlat 6a0627a493 genhub init (#1133) 2026-03-12 01:21:54 +07:00
Brandon Thomas 6e2ed226d8 api docs 2026-03-11 12:19:06 -04:00
bflatastic 0c20a10a78 add models with missing name mapping 2026-03-11 23:05:30 +07:00
bflatastic 92bba52502 failure reason in task queue 2026-03-11 19:43:43 +07:00
bflatastic 6d3ec8bfee "Make 3D" button to not enqueue directly but go to 3D object page 2026-03-11 14:17:12 +07:00
Brandon Thomas c7744ae545 update oncall script 2026-03-11 00:36:12 -04:00
Brandon Thomas 65b97a7636 moderation: create wallet (#1131) 2026-03-11 00:14:03 -04:00
Brandon Thomas dd630c5993 tauri task failure reasons (#1130) 2026-03-10 23:27:55 -04:00
Brandon Thomas b39f208bd3 add robust job failure reasons to seedance (#1129) 2026-03-10 19:30:31 -04:00
Brandon Thomas 53f34061b6 CLI tool for support issues (#1128) 2026-03-10 17:06:38 -04:00
Brandon Thomas d3acef8467 bump linkst 2026-03-10 15:14:03 -04:00
bflatastic 167a7f996e fixed angles history persistence, non blocking generations 2026-03-10 23:35:03 +07:00
Brandon Thomas 7fca050c56 bump artcraft version 2026-03-10 12:18:47 -04:00
bflatastic e9316bcdb5 bug fixes 2026-03-10 21:04:53 +07:00
bflatastic 40a2e8a514 added angles models name mapping 2026-03-10 20:10:03 +07:00
bflatastic 02ab54bc8c angles fixed and history stack 2026-03-10 20:04:46 +07:00
Brandon Thomas ff268c4e4e WorldLabs download job (#1125) 2026-03-10 08:44:03 -04:00
BFlatandBrandon Thomas f97def83e1 Angles UI (#1090)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-03-09 21:49:17 -04:00
jtoy 9e9156cd32 fix monterey (#1042)
an api for safari that is not supported was used, this fixes it as a
fallback. Tested and works.

Fixes: https://github.com/storytold/artcraft/issues/1008
2026-03-09 20:37:55 -04:00
Brandon Thomas c7b817ac3f angle edit models (fal, handlers, routing) (#1124) 2026-03-09 19:48:09 -04:00
bflatastic 66afce8889 Merge branch 'main' of https://github.com/storytold/storyteller-rust 2026-03-10 02:20:02 +07:00
bflatastic f7e7c132bc cost estimates for splats in frontend ui 2026-03-10 02:19:59 +07:00
Brandon Thomas cfa14769cd fix build error 2026-03-09 15:19:20 -04:00
Brandon Thomas 56d1649a9f splat cost estimate infrastructure (#1123) 2026-03-09 15:01:40 -04:00
Brandon Thomas e070028bf1 bump artcraft to 0.13.0 2026-03-09 14:11:29 -04:00
Brandon Thomas 52fdf237ad Tauri can now generate Marble natively (#1122) 2026-03-09 14:04:28 -04:00
BFlat 15d286135a 3d world splat models selection, multiple image support, optional prompt (#1119) 2026-03-09 12:58:14 -04:00
Brandon Thomas dc1845becb Add native support for WorldLabs Marble (#1120)
- We support users logging into their Marble accounts. This adds it
natively to ArtCraft
2026-03-09 12:50:28 -04:00
Brandon Thomas a654e9ada1 Worldlabs api improvements (#1118) 2026-03-09 10:12:13 -04:00
Brandon Thomas 2843916852 Official WorldLabs API (instead of browser integration) (#1117) 2026-03-09 08:56:57 -04:00
Brandon Thomas 4d89caf6ff generate with sound boolean (+ negative prompts plumbing) (#1116) 2026-03-08 23:22:45 -04:00
Brandon Thomas d68a92e7cf Kling 3.0 Standard and Pro support (#1115) 2026-03-08 19:57:49 -04:00
bflatastic 2b9e168d36 remove arrow icon 2026-03-09 00:44:57 +07:00
bflatastic 12542cb684 enterprise column in pricing page 2026-03-09 00:43:02 +07:00
Brandon Thomas db24eff600 REAMDE update 2026-03-08 11:21:03 -04:00
Brandon Thomas d265cecdce Add Seedance 1.5 to ArtCraft (#1114)
This looks like a thick PR, because it is. 

We're going to do a lot with the middleware.
2026-03-08 10:55:08 -04:00
Brandon Thomas 6be0ce86eb gitignore 2026-03-08 06:47:12 -04:00
Brandon Thomas 573da67788 de-vendor fal sora; fix "auto" bug (#1113)
- Issue with "auto" resolution for text-to-video
- de-vendor (I wrote the code originally anyway) 
- a few extra tests
2026-03-08 06:01:02 -04:00
BFlat 0651afd6fa Scope Get Now button text to SD2 page only via prop (#1111) 2026-03-07 20:02:15 +07:00
BFlat 650cf55421 Add LandingSD2 page at /seedance-2 for Seedance marketing (#1109) 2026-03-07 19:12:42 +07:00
bflatastic 338210a568 stylings fixes 2026-03-07 00:55:26 +07:00
bflatastic 555740dd7e consistent gradients across pages,news page footer fix 2026-03-07 00:52:23 +07:00
bflatastic f688e83ee9 footer update and seedance text 2026-03-07 00:39:43 +07:00
bflatastic 2cfcc04b92 download page update 2026-03-07 00:29:10 +07:00
bflatastic 7cb7ae9e54 remove google login for now 2026-03-06 23:58:42 +07:00
bflatastic 1feb4be5f9 referral to fire only once 2026-03-06 21:20:06 +07:00
bflatastic 9e13c7c307 referrer url on signup 2026-03-06 20:22:51 +07:00
Brandon Thomas 1076ea1b31 widen fields (#1108) 2026-03-05 21:31:25 -05:00
Brandon Thomas 2a101487b0 find out if marketing is effective (#1107)
NB: Ip address is to prevent spam/abuse
2026-03-05 21:22:02 -05:00
2434 changed files with 56690 additions and 121262 deletions
+14
View File
@@ -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
+4 -1
View File
@@ -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,7 +36,9 @@ script/socat_dev_database_connect.sh
# Python virtual envs (named by convention)
venv/
# Testing
# LLM Testing
/prompts/
/reports/
/requests/
# Scratch data
+4
View File
@@ -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" />
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -0,0 +1,12 @@
{
"db_name": "MySQL",
"query": "\n INSERT INTO web_referrals (\n url,\n domain,\n utm_source,\n utm_medium,\n utm_campaign,\n ip_address,\n anonymous_visitor_token\n ) VALUES (?, ?, ?, ?, ?, ?, ?)\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "80f73702374593c141d183d86bd8af73d37fd7118914d0ba12a02f53c1b84c78"
}
@@ -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"
}
@@ -1,12 +1,12 @@
{
"db_name": "MySQL",
"query": "\n INSERT INTO media_files\n SET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n is_user_upload = ?,\n is_intermediate_system_file = ?,\n\n origin_category = ?, \n origin_product_category = ?, \n maybe_origin_model_type = ?, \n maybe_origin_model_token = ?, \n maybe_origin_filename = ?,\n\n is_batch_generated = ?,\n maybe_batch_token = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n maybe_duration_millis = ?,\n maybe_audio_encoding = ?, \n maybe_video_encoding = ?, \n maybe_frame_width = ?, \n maybe_frame_height = ?,\n maybe_prompt_token = ?,\n checksum_sha2 = ?,\n \n maybe_engine_category = ?,\n\n maybe_title = ?,\n maybe_text_transcript = ?,\n\n maybe_scene_source_media_file_token = ?,\n\n public_bucket_directory_hash = ?, \n maybe_public_bucket_prefix = ?, \n maybe_public_bucket_extension = ?, \n\n maybe_creator_user_token = ?, \n maybe_creator_anonymous_visitor_token = ?, \n\n creator_ip_address = ?, \n creator_set_visibility = ?, \n\n maybe_creator_file_synthetic_id = ?, \n maybe_creator_category_synthetic_id = ?,\n\n extra_file_modification_info = ?,\n\n maybe_mod_user_token = ?, \n is_generated_on_prem = ?, \n generated_by_worker = ?, \n generated_by_cluster = ?\n ",
"query": "\n INSERT INTO media_files\n SET\n token = ?,\n\n media_class = ?,\n media_type = ?,\n\n is_user_upload = ?,\n is_intermediate_system_file = ?,\n\n origin_category = ?, \n origin_product_category = ?, \n maybe_origin_model_type = ?, \n maybe_origin_model_token = ?, \n maybe_origin_filename = ?,\n\n is_batch_generated = ?,\n maybe_batch_token = ?,\n\n maybe_mime_type = ?,\n file_size_bytes = ?,\n maybe_duration_millis = ?,\n maybe_audio_encoding = ?, \n maybe_video_encoding = ?, \n maybe_frame_width = ?, \n maybe_frame_height = ?,\n maybe_prompt_token = ?,\n checksum_sha2 = ?,\n \n maybe_engine_category = ?,\n\n maybe_title = ?,\n maybe_text_transcript = ?,\n\n maybe_scene_source_media_file_token = ?,\n\n public_bucket_directory_hash = ?, \n maybe_public_bucket_prefix = ?, \n maybe_public_bucket_extension = ?, \n\n maybe_creator_user_token = ?, \n maybe_creator_anonymous_visitor_token = ?, \n\n creator_ip_address = ?, \n creator_set_visibility = ?, \n\n maybe_creator_file_synthetic_id = ?, \n maybe_creator_category_synthetic_id = ?,\n\n extra_file_modification_info = ?,\n\n maybe_cover_image_media_file_token = ?,\n\n maybe_mod_user_token = ?,\n is_generated_on_prem = ?,\n generated_by_worker = ?,\n generated_by_cluster = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 39
"Right": 40
},
"nullable": []
},
"hash": "b4470e607c005421dd8504b9f1d695080a581936ac6ce00b6f437b2764e741be"
"hash": "87d5511700985daaabfc9f2972f018d56b6672c07be082daa7c1a782400cb18d"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -0,0 +1,102 @@
{
"db_name": "MySQL",
"query": "\nSELECT\n jobs.token as `job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken`,\n jobs.maybe_external_third_party_id as `operation_id`,\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 jobs.creator_set_visibility as `creator_set_visibility: enums::common::visibility::Visibility`,\n jobs.maybe_prompt_token as `maybe_prompt_token: tokens::tokens::prompts::PromptToken`,\n jobs.maybe_wallet_ledger_entry_token as `maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken`\n\nFROM generic_inference_jobs as jobs\n\nWHERE jobs.maybe_external_third_party = ?\n AND jobs.status NOT IN ('complete_success', 'complete_failure')\n AND jobs.maybe_external_third_party_id IS NOT NULL\n\nLIMIT 25000\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "job_token: tokens::tokens::generic_inference_jobs::InferenceJobToken",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | UNIQUE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 1,
"name": "operation_id",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 256
}
},
{
"ordinal": 2,
"name": "maybe_creator_user_token: tokens::tokens::users::UserToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 3,
"name": "maybe_creator_anonymous_visitor_token: tokens::tokens::anonymous_visitor_tracking::AnonymousVisitorTrackingToken",
"type_info": {
"type": "VarString",
"flags": "MULTIPLE_KEY | BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 4,
"name": "creator_ip_address",
"type_info": {
"type": "VarString",
"flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE",
"char_set": 224,
"max_size": 160
}
},
{
"ordinal": 5,
"name": "creator_set_visibility: enums::common::visibility::Visibility",
"type_info": {
"type": "String",
"flags": "NOT_NULL | BINARY | ENUM",
"char_set": 224,
"max_size": 28
}
},
{
"ordinal": 6,
"name": "maybe_prompt_token: tokens::tokens::prompts::PromptToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
},
{
"ordinal": 7,
"name": "maybe_wallet_ledger_entry_token: tokens::tokens::wallet_ledger_entries::WalletLedgerEntryToken",
"type_info": {
"type": "VarString",
"flags": "BINARY",
"char_set": 224,
"max_size": 128
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true,
true,
true,
false,
false,
true,
true
]
},
"hash": "d56a26a7300495fac9741e77e390f16402e2273dbab9a15d7c17eb1f0da7a1b1"
}
@@ -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"
}
@@ -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"
}
+62
View File
@@ -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
+588 -831
View File
File diff suppressed because it is too large Load Diff
+95 -62
View File
@@ -6,25 +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_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",
@@ -32,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",
@@ -41,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",
@@ -50,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",
@@ -70,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",
@@ -113,30 +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/tts_download_job",
"crates/service/job/tts_inference_job",
"crates/service/job/w2l_download_job",
"crates/service/job/w2l_inference_job",
"crates/service/job/video_thumbnail_job",
"crates/service/job/worldlabs_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",
@@ -208,47 +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_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
@@ -264,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"
@@ -296,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.
#
+1 -1
View File
@@ -55,7 +55,7 @@ We haven't abandoned text-to-asset generation for quick prototyping and ideation
| Provider | Features |
|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Artcraft | Nano Banana, Nano Banana Pro, GPT-Image-1 / 1.5, Seedance 2 / Seedream 4 / 4.5, Flux 1.1 / Kontext, Veo 2 / 3 / 3.1, Kling 1.6 / 2.1 / 2.5 / 2.6, Seedance, Sora 2 / Pro, Hunyuan 3d 2 / 3 |
| Artcraft | Nano Banana, Nano Banana Pro, GPT-Image-1 / 1.5, Seedance 1.0 Lite / 1.5 Pro / 2.0, Seedream 4 / 4.5, Flux 1.1 / Kontext, Veo 2 / 3 / 3.1, Kling 1.6 / 2.1 / 2.5 / 2.6, Sora 2 / Pro, Hunyuan 3d 2 / 3 |
| Grok | Grok Imagine, Grok Video |
| Midjourney | Image Gen (all versions) |
| Sora | Sora 1, Sora 2, GPT-Image-1 |
@@ -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
@@ -0,0 +1,8 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE web_referrals
MODIFY COLUMN utm_source VARCHAR(32) DEFAULT NULL,
MODIFY COLUMN utm_medium VARCHAR(32) DEFAULT NULL,
MODIFY COLUMN utm_campaign VARCHAR(255) DEFAULT NULL;
@@ -0,0 +1,8 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE web_referrals
MODIFY COLUMN utm_source VARCHAR(150) DEFAULT NULL,
MODIFY COLUMN utm_medium VARCHAR(150) DEFAULT NULL,
MODIFY COLUMN utm_campaign VARCHAR(150) DEFAULT NULL;
@@ -0,0 +1,7 @@
-- noinspection SqlDialectInspectionForFile
-- noinspection SqlNoDataSourceInspectionForFile
-- noinspection SqlResolveForFile
ALTER TABLE media_files
DROP COLUMN
maybe_thumbnail_version;
@@ -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
@@ -13,11 +13,11 @@ CREATE TABLE web_referrals (
-- The parsed out referral domain
domain VARCHAR(255) DEFAULT NULL,
utm_source VARCHAR(32) DEFAULT NULL,
utm_source VARCHAR(150) DEFAULT NULL,
utm_medium VARCHAR(32) DEFAULT NULL,
utm_medium VARCHAR(150) DEFAULT NULL,
utm_campaign VARCHAR(255) DEFAULT NULL,
utm_campaign VARCHAR(150) DEFAULT NULL,
ip_address VARCHAR(40) NOT NULL,
+12 -31
View File
@@ -130,41 +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 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
@@ -203,6 +182,8 @@ RUN echo -n ${GIT_SHA} > GIT_SHA
# Copy all the binaries (except those that need a GPU):
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 /
+4 -4
View File
@@ -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
@@ -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,
@@ -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,
@@ -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,
@@ -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>,
@@ -0,0 +1,59 @@
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use enums::common::generation::common_splat_model::CommonSplatModel;
use enums::common::generation_provider::GenerationProvider;
pub const ESTIMATE_SPLAT_COST_PATH: &str = "/v1/generate/cost_estimate/splat";
/// Request body for the splat cost estimate endpoint.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct EstimateSplatCostRequest {
/// The splat model to estimate costs for.
pub model: CommonSplatModel,
/// The provider to route the generation through.
pub provider: GenerationProvider,
/// Whether the request includes a reference image.
pub has_reference_image: Option<bool>,
}
/// Response body for the splat cost estimate endpoint.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct EstimateSplatCostResponse {
pub success: bool,
/// Estimated cost in credits.
pub cost_in_credits: Option<u64>,
/// Estimated cost in USD cents.
pub cost_in_usd_cents: Option<u64>,
/// Whether the generation is free for this user/plan.
pub is_free: bool,
/// Whether the user has unlimited generations.
pub is_unlimited: bool,
/// Whether the user is rate limited.
pub is_rate_limited: bool,
/// Whether the output will have a watermark.
pub has_watermark: bool,
}
/// Error response for the splat cost estimate endpoint.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct EstimateSplatCostError {
pub success: bool,
pub error_type: EstimateSplatCostErrorType,
pub error_message: String,
}
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum EstimateSplatCostErrorType {
InvalidProviderForModel,
InvalidInput,
}
@@ -3,13 +3,16 @@ 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";
/// Request body for the video cost estimate endpoint.
#[derive(Serialize, Deserialize, ToSchema)]
///
/// Every model cares about its own set of parameters and not all
/// parameters may be relevant for every model.
#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct EstimateVideoCostRequest {
/// The video model to estimate costs for.
pub model: CommonVideoModel,
@@ -27,17 +30,20 @@ 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>,
/// Number of videos to generate in parallel.
pub video_batch_count: Option<u16>,
/// Whether to generate audio for the video.
pub generate_audio: Option<bool>,
}
/// Describes the type of video generation being requested.
#[derive(Serialize, Deserialize, ToSchema)]
#[derive(Serialize, Deserialize, ToSchema, Debug)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum GenerationMode {
TextToVideo,
@@ -99,6 +105,7 @@ mod tests {
resolution: None,
duration_seconds: None,
video_batch_count: None,
generate_audio: None,
};
let serialized = serde_json::to_string(&request).unwrap();
assert!(serialized.contains("\"generation_mode\":{\"type\":\"text_to_video\"}"));
@@ -115,6 +122,7 @@ mod tests {
resolution: None,
duration_seconds: None,
video_batch_count: None,
generate_audio: None,
};
let serialized = serde_json::to_string(&request).unwrap();
assert!(serialized.contains("\"generation_mode\":{\"type\":\"reference_image_to_video\",\"count\":1}"));
@@ -1,2 +1,3 @@
pub mod estimate_image_cost;
pub mod estimate_splat_cost;
pub mod estimate_video_cost;
@@ -0,0 +1,56 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const FLUX_2_LORA_EDIT_IMAGE_ANGLE_PATH: &str = "/v1/generate/image/angle/flux_2_lora";
#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct Flux2LoraEditImageAngleRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// The image to edit with angle adjustment.
pub image_media_token: MediaFileToken,
/// Horizontal rotation angle in degrees.
pub horizontal_angle: Option<f64>,
/// Vertical rotation angle in degrees.
pub vertical_angle: Option<f64>,
/// Zoom level.
pub zoom: Option<f64>,
/// Number of images to generate. Default is one.
pub num_images: Option<Flux2LoraEditImageAngleNumImages>,
/// Output image size. Default is square_hd.
pub image_size: Option<Flux2LoraEditImageAngleImageSize>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Flux2LoraEditImageAngleNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Flux2LoraEditImageAngleImageSize {
Square,
SquareHd,
PortraitFourThree,
PortraitSixteenNine,
LandscapeFourThree,
LandscapeSixteenNine,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Flux2LoraEditImageAngleResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -0,0 +1,2 @@
pub mod flux_2_lora_edit_image_angle;
pub mod qwen_edit_2511_edit_image_angle;
@@ -0,0 +1,59 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const QWEN_EDIT_2511_EDIT_IMAGE_ANGLE_PATH: &str = "/v1/generate/image/angle/qwen_edit_2511";
#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct QwenEdit2511EditImageAngleRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// The image to edit with angle adjustment.
pub image_media_token: MediaFileToken,
/// Horizontal rotation angle in degrees.
pub horizontal_angle: Option<f64>,
/// Vertical rotation angle in degrees.
pub vertical_angle: Option<f64>,
/// Zoom level.
pub zoom: Option<f64>,
/// Additional text prompt to guide the generation.
pub additional_prompt: Option<String>,
/// Number of images to generate. Default is one.
pub num_images: Option<QwenEdit2511EditImageAngleNumImages>,
/// Output image size. Default is square_hd.
pub image_size: Option<QwenEdit2511EditImageAngleImageSize>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum QwenEdit2511EditImageAngleNumImages {
One,
Two,
Three,
Four,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum QwenEdit2511EditImageAngleImageSize {
Square,
SquareHd,
PortraitFourThree,
PortraitSixteenNine,
LandscapeFourThree,
LandscapeSixteenNine,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct QwenEdit2511EditImageAngleResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,3 +1,4 @@
pub mod angle;
pub mod bg_removal;
pub mod edit;
pub mod inpaint;
@@ -1,4 +1,5 @@
pub mod cost_estimate;
pub mod image;
pub mod object;
pub mod splat;
pub mod video;
@@ -0,0 +1,25 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const GENERATE_WORLDLABS_MARBLE_0P1_MINI_SPLAT_URL_PATH: &str = "/v1/generate/splat/worldlabs_marble_0p1_mini";
/// World Labs Marble 0.1-mini Splat Generation
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GenerateWorldlabsMarble0p1MiniSplatRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Optional image to use as input for world generation.
pub image_media_file_token: Option<MediaFileToken>,
/// Optional text prompt for world generation.
pub prompt: Option<String>,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GenerateWorldlabsMarble0p1MiniSplatResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -0,0 +1,25 @@
use serde_derive::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const GENERATE_WORLDLABS_MARBLE_0P1_PLUS_SPLAT_URL_PATH: &str = "/v1/generate/splat/worldlabs_marble_0p1_plus";
/// World Labs Marble 0.1-plus Splat Generation
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GenerateWorldlabsMarble0p1PlusSplatRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Optional image to use as input for world generation.
pub image_media_file_token: Option<MediaFileToken>,
/// Optional text prompt for world generation.
pub prompt: Option<String>,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct GenerateWorldlabsMarble0p1PlusSplatResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -0,0 +1,2 @@
pub mod generate_worldlabs_marble_0p1_mini_splat;
pub mod generate_worldlabs_marble_0p1_plus_splat;
@@ -0,0 +1,66 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const KLING_3P0_PRO_MULTI_FUNCTION_VIDEO_PATH: &str = "/v1/generate/video/multi_function/kling_3p0_pro";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling3p0ProMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt.
pub prompt: Option<String>,
/// Optional negative prompt.
pub negative_prompt: Option<String>,
/// If present, we're doing image-to-video. If absent, text-to-video.
pub image_media_token: Option<MediaFileToken>,
/// Optional end frame image.
pub end_image_media_token: Option<MediaFileToken>,
/// Duration of the video (3-15 seconds).
pub duration: Option<Kling3p0ProMultiFunctionVideoGenDuration>,
/// Whether to generate audio.
pub generate_audio: Option<bool>,
/// Aspect ratio (only for text-to-video).
pub aspect_ratio: Option<Kling3p0ProMultiFunctionVideoGenAspectRatio>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling3p0ProMultiFunctionVideoGenDuration {
ThreeSeconds,
FourSeconds,
FiveSeconds,
SixSeconds,
SevenSeconds,
EightSeconds,
NineSeconds,
TenSeconds,
ElevenSeconds,
TwelveSeconds,
ThirteenSeconds,
FourteenSeconds,
FifteenSeconds,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling3p0ProMultiFunctionVideoGenAspectRatio {
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling3p0ProMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -0,0 +1,66 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const KLING_3P0_STANDARD_MULTI_FUNCTION_VIDEO_PATH: &str = "/v1/generate/video/multi_function/kling_3p0_standard";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling3p0StandardMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// Text prompt.
pub prompt: Option<String>,
/// Optional negative prompt.
pub negative_prompt: Option<String>,
/// If present, we're doing image-to-video. If absent, text-to-video.
pub image_media_token: Option<MediaFileToken>,
/// Optional end frame image.
pub end_image_media_token: Option<MediaFileToken>,
/// Duration of the video (3-15 seconds).
pub duration: Option<Kling3p0StandardMultiFunctionVideoGenDuration>,
/// Whether to generate audio.
pub generate_audio: Option<bool>,
/// Aspect ratio (only for text-to-video).
pub aspect_ratio: Option<Kling3p0StandardMultiFunctionVideoGenAspectRatio>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling3p0StandardMultiFunctionVideoGenDuration {
ThreeSeconds,
FourSeconds,
FiveSeconds,
SixSeconds,
SevenSeconds,
EightSeconds,
NineSeconds,
TenSeconds,
ElevenSeconds,
TwelveSeconds,
ThirteenSeconds,
FourteenSeconds,
FifteenSeconds,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "snake_case")]
pub enum Kling3p0StandardMultiFunctionVideoGenAspectRatio {
Square,
SixteenByNine,
NineBySixteen,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Kling3p0StandardMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -1,5 +1,8 @@
pub mod kling_2_5_turbo_multi_function_video_gen;
pub mod kling_2_6_multi_function_video_gen;
pub mod kling_3p0_pro_multi_function_video_gen;
pub mod kling_3p0_standard_multi_function_video_gen;
pub mod seedance_1p5_pro_multi_function_video_gen;
pub mod seedance_2p0_multi_function_video_gen;
pub mod sora_2_multi_function_video_gen;
pub mod sora_2_pro_multi_function_video_gen;
@@ -0,0 +1,85 @@
use serde::{Deserialize, Serialize};
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
use tokens::tokens::media_files::MediaFileToken;
use utoipa::ToSchema;
pub const SEEDANCE_1P5_PRO_MULTI_FUNCTION_VIDEO_GEN_PATH: &str = "/v1/generate/video/multi_function/seedance_1p5_pro";
/// Both text-to-video and image-to-video in one request.
#[derive(Serialize, Deserialize, ToSchema, Debug)]
pub struct Seedance1p5ProMultiFunctionVideoGenRequest {
/// Idempotency token to prevent duplicate requests.
pub uuid_idempotency_token: String,
/// "Required".
/// Required downstream, but we'll coerce null to empty string.
/// Text prompt.
pub prompt: Option<String>,
/// Optional.
/// Only for image-to-video.
/// Source of the starting frame.
/// If present, we're doing image-to-video.
/// If absent, we're doing text-to-video.
pub start_frame_image_media_token: Option<MediaFileToken>,
/// Optional.
/// Only for image-to-video.
/// Source of the ending frame.
pub end_frame_image_media_token: Option<MediaFileToken>,
/// Optional.
pub resolution: Option<Seedance1p5ProMultiFunctionVideoGenResolution>,
/// Optional.
/// Duration of the video.
/// (this is uniform against all modes)
pub duration: Option<Seedance1p5ProMultiFunctionVideoGenDuration>,
/// Optional.
pub aspect_ratio: Option<Seedance1p5ProMultiFunctionVideoGenAspectRatio>,
/// Whether to generate audio.
pub generate_audio: Option<bool>,
}
#[derive(Serialize, Deserialize, ToSchema, Copy, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Seedance1p5ProMultiFunctionVideoGenResolution {
FourEightyP,
SevenTwentyP,
TenEightyP,
}
#[derive(Serialize, Deserialize, ToSchema, Copy, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Seedance1p5ProMultiFunctionVideoGenDuration {
FourSeconds,
FiveSeconds,
SixSeconds,
SevenSeconds,
EightSeconds,
NineSeconds,
TenSeconds,
ElevenSeconds,
TwelveSeconds,
}
#[derive(Serialize, Deserialize, ToSchema, Copy, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Seedance1p5ProMultiFunctionVideoGenAspectRatio {
TwentyOneByNine,
SixteenByNine,
FourByThree,
Square,
ThreeByFour,
NineBySixteen,
Auto,
}
#[derive(Serialize, Deserialize, ToSchema)]
pub struct Seedance1p5ProMultiFunctionVideoGenResponse {
pub success: bool,
pub inference_job_token: InferenceJobToken,
}
@@ -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>>,
}
@@ -9,4 +9,5 @@ pub mod prompts;
pub mod stripe_artcraft;
pub mod subscriptions;
pub mod users;
pub mod utils;
pub mod utils;
pub mod web_referrals;
@@ -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>>,
}
@@ -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;
@@ -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;
@@ -0,0 +1,17 @@
use serde_derive::{Deserialize, Serialize};
use utoipa::ToSchema;
pub const LOG_WEB_REFERRAL_URL_PATH: &str = "/v1/web_referrals/record";
#[derive(Deserialize, ToSchema)]
pub struct LogWebReferralRequest {
/// Optional: The referral URL the user arrived from when signing up.
/// The browser can send `document.referrer` to the backend so we know how people are finding us.
/// If the browser doesn't send this parameter, we'll try the `referer` header.
pub maybe_referral_url: Option<String>,
}
#[derive(Serialize, ToSchema)]
pub struct LogWebReferralResponse {
pub success: bool,
}
@@ -0,0 +1 @@
pub mod log_web_referral;
@@ -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,2 +1,3 @@
pub mod image;
pub mod splat;
pub mod video;
@@ -0,0 +1,20 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::cost_estimate::estimate_splat_cost::{
EstimateSplatCostRequest, EstimateSplatCostResponse, ESTIMATE_SPLAT_COST_PATH,
};
pub async fn estimate_splat_cost(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: EstimateSplatCostRequest,
) -> Result<EstimateSplatCostResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
ESTIMATE_SPLAT_COST_PATH,
maybe_creds,
request,
).await?)
}
@@ -0,0 +1 @@
pub mod estimate_splat_cost;
@@ -0,0 +1,21 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::angle::flux_2_lora_edit_image_angle::{
Flux2LoraEditImageAngleRequest, Flux2LoraEditImageAngleResponse,
FLUX_2_LORA_EDIT_IMAGE_ANGLE_PATH,
};
pub async fn flux_2_lora_edit_image_angle(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Flux2LoraEditImageAngleRequest,
) -> Result<Flux2LoraEditImageAngleResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
FLUX_2_LORA_EDIT_IMAGE_ANGLE_PATH,
maybe_creds,
request,
).await?)
}
@@ -0,0 +1,2 @@
pub mod flux_2_lora_edit_image_angle;
pub mod qwen_edit_2511_edit_image_angle;
@@ -0,0 +1,21 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::image::angle::qwen_edit_2511_edit_image_angle::{
QwenEdit2511EditImageAngleRequest, QwenEdit2511EditImageAngleResponse,
QWEN_EDIT_2511_EDIT_IMAGE_ANGLE_PATH,
};
pub async fn qwen_edit_2511_edit_image_angle(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: QwenEdit2511EditImageAngleRequest,
) -> Result<QwenEdit2511EditImageAngleResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
QWEN_EDIT_2511_EDIT_IMAGE_ANGLE_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,3 +1,4 @@
pub mod angle;
pub mod bg_removal;
pub mod edit;
pub mod inpaint;
@@ -1,4 +1,5 @@
pub mod cost_estimate;
pub mod image;
pub mod object;
pub mod splat;
pub mod video;
@@ -0,0 +1,18 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::splat::generate_worldlabs_marble_0p1_mini_splat::{GenerateWorldlabsMarble0p1MiniSplatRequest, GenerateWorldlabsMarble0p1MiniSplatResponse, GENERATE_WORLDLABS_MARBLE_0P1_MINI_SPLAT_URL_PATH};
pub async fn generate_worldlabs_marble_0p1_mini_splat(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: GenerateWorldlabsMarble0p1MiniSplatRequest,
) -> Result<GenerateWorldlabsMarble0p1MiniSplatResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
GENERATE_WORLDLABS_MARBLE_0P1_MINI_SPLAT_URL_PATH,
maybe_creds,
request,
).await?)
}
@@ -0,0 +1,18 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::splat::generate_worldlabs_marble_0p1_plus_splat::{GenerateWorldlabsMarble0p1PlusSplatRequest, GenerateWorldlabsMarble0p1PlusSplatResponse, GENERATE_WORLDLABS_MARBLE_0P1_PLUS_SPLAT_URL_PATH};
pub async fn generate_worldlabs_marble_0p1_plus_splat(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: GenerateWorldlabsMarble0p1PlusSplatRequest,
) -> Result<GenerateWorldlabsMarble0p1PlusSplatResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
GENERATE_WORLDLABS_MARBLE_0P1_PLUS_SPLAT_URL_PATH,
maybe_creds,
request,
).await?)
}
@@ -0,0 +1,2 @@
pub mod generate_worldlabs_marble_0p1_mini_splat;
pub mod generate_worldlabs_marble_0p1_plus_splat;
@@ -0,0 +1,18 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::kling_3p0_pro_multi_function_video_gen::{Kling3p0ProMultiFunctionVideoGenRequest, Kling3p0ProMultiFunctionVideoGenResponse, KLING_3P0_PRO_MULTI_FUNCTION_VIDEO_PATH};
pub async fn kling_3p0_pro_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Kling3p0ProMultiFunctionVideoGenRequest,
) -> Result<Kling3p0ProMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
KLING_3P0_PRO_MULTI_FUNCTION_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -0,0 +1,18 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::kling_3p0_standard_multi_function_video_gen::{Kling3p0StandardMultiFunctionVideoGenRequest, Kling3p0StandardMultiFunctionVideoGenResponse, KLING_3P0_STANDARD_MULTI_FUNCTION_VIDEO_PATH};
pub async fn kling_3p0_standard_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Kling3p0StandardMultiFunctionVideoGenRequest,
) -> Result<Kling3p0StandardMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
KLING_3P0_STANDARD_MULTI_FUNCTION_VIDEO_PATH,
maybe_creds,
request,
).await?)
}
@@ -1,6 +1,9 @@
pub mod kling_2p5_turbo_pro_multi_function_video_gen;
pub mod seedance_1p5_pro_multi_function_video_gen;
pub mod seedance_2p0_multi_function_video_gen;
pub mod kling_2p6_pro_multi_function_video_gen;
pub mod kling_3p0_pro_multi_function_video_gen;
pub mod kling_3p0_standard_multi_function_video_gen;
pub mod sora_2_multi_function_video_gen;
pub mod sora_2_pro_multi_function_video_gen;
pub mod veo_3p1_fast_multi_function_video_gen;
@@ -0,0 +1,18 @@
use crate::credentials::storyteller_credential_set::StorytellerCredentialSet;
use crate::error::storyteller_error::StorytellerError;
use crate::utils::api_host::ApiHost;
use crate::utils::basic_json_post_request::basic_json_post_request;
use artcraft_api_defs::generate::video::multi_function::seedance_1p5_pro_multi_function_video_gen::{Seedance1p5ProMultiFunctionVideoGenRequest, Seedance1p5ProMultiFunctionVideoGenResponse, SEEDANCE_1P5_PRO_MULTI_FUNCTION_VIDEO_GEN_PATH};
pub async fn seedance_1p5_pro_multi_function_video_gen(
api_host: &ApiHost,
maybe_creds: Option<&StorytellerCredentialSet>,
request: Seedance1p5ProMultiFunctionVideoGenRequest,
) -> Result<Seedance1p5ProMultiFunctionVideoGenResponse, StorytellerError> {
Ok(basic_json_post_request(
api_host,
SEEDANCE_1P5_PRO_MULTI_FUNCTION_VIDEO_GEN_PATH,
maybe_creds,
request,
).await?)
}
@@ -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;
@@ -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>,
@@ -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;
@@ -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>,
@@ -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;
@@ -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)]
@@ -17,15 +17,20 @@ workspace-build-acceleration.workspace = true
# Internal
artcraft_api_defs.workspace = true
fal_client.workspace = true
seedance2pro.workspace = true
artcraft_client.workspace = true
fal_client.workspace = true
muapi_client.workspace = true
seedance2pro_client.workspace = true
tokens.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>),
}
@@ -27,4 +27,8 @@ pub enum CommonImageModel {
Seedream4p5,
#[serde(rename = "seedream_5_lite")]
Seedream5Lite,
#[serde(rename = "qwen_edit_2511_angles")]
QwenEdit2511Angles,
#[serde(rename = "flux_2_lora_angles")]
Flux2LoraAngles,
}
@@ -0,0 +1,13 @@
use serde_derive::{Deserialize, Serialize};
/// Common splat models supported by the router.
/// Not all models are available through all providers.
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum CommonSplatModel {
#[serde(rename = "marble_0p1_mini")]
Marble0p1Mini,
#[serde(rename = "marble_0p1_plus")]
Marble0p1Plus,
}
@@ -23,9 +23,18 @@ pub enum CommonVideoModel {
#[serde(rename = "kling_2p6_pro")]
Kling2p6Pro,
#[serde(rename = "kling_3p0_standard")]
Kling3p0Standard,
#[serde(rename = "kling_3p0_pro")]
Kling3p0Pro,
#[serde(rename = "seedance_1p0_lite")]
Seedance10Lite,
#[serde(rename = "seedance_1p5_pro")]
Seedance1p5Pro,
#[serde(rename = "seedance_2p0")]
Seedance2p0,
@@ -1,7 +1,10 @@
pub mod audio_list_ref;
pub mod common_aspect_ratio;
pub mod common_image_model;
pub mod common_resolution;
pub mod common_splat_model;
pub mod common_video_model;
pub mod image_list_ref;
pub mod image_ref;
pub mod provider;
pub mod video_list_ref;

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