@weirdfingers/baseboards 0.9.6 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. package/dist/index.js +560 -469
  2. package/dist/index.js.map +1 -1
  3. package/package.json +2 -5
  4. package/templates/README.md +0 -122
  5. package/templates/api/.env.example +0 -65
  6. package/templates/api/ARTIFACT_RESOLUTION_GUIDE.md +0 -148
  7. package/templates/api/Dockerfile +0 -32
  8. package/templates/api/README.md +0 -264
  9. package/templates/api/alembic/env.py +0 -114
  10. package/templates/api/alembic/script.py.mako +0 -28
  11. package/templates/api/alembic/versions/20250101_000000_initial_schema.py +0 -506
  12. package/templates/api/alembic/versions/20251022_174729_remove_provider_name_from_generations.py +0 -75
  13. package/templates/api/alembic/versions/20251023_165852_switch_to_declarative_base_and_mapping.py +0 -467
  14. package/templates/api/alembic/versions/20251202_000000_add_artifact_lineage.py +0 -134
  15. package/templates/api/alembic/versions/2025925_62735_add_seed_data_for_default_tenant.py +0 -88
  16. package/templates/api/alembic.ini +0 -36
  17. package/templates/api/config/generators.yaml +0 -237
  18. package/templates/api/config/storage_config.yaml +0 -26
  19. package/templates/api/docs/ADDING_GENERATORS.md +0 -409
  20. package/templates/api/docs/GENERATORS_API.md +0 -502
  21. package/templates/api/docs/MIGRATIONS.md +0 -472
  22. package/templates/api/docs/TESTING_LIVE_APIS.md +0 -417
  23. package/templates/api/docs/storage_providers.md +0 -337
  24. package/templates/api/pyproject.toml +0 -205
  25. package/templates/api/src/boards/__init__.py +0 -10
  26. package/templates/api/src/boards/api/app.py +0 -172
  27. package/templates/api/src/boards/api/auth.py +0 -75
  28. package/templates/api/src/boards/api/endpoints/__init__.py +0 -3
  29. package/templates/api/src/boards/api/endpoints/jobs.py +0 -76
  30. package/templates/api/src/boards/api/endpoints/setup.py +0 -505
  31. package/templates/api/src/boards/api/endpoints/sse.py +0 -129
  32. package/templates/api/src/boards/api/endpoints/storage.py +0 -155
  33. package/templates/api/src/boards/api/endpoints/tenant_registration.py +0 -296
  34. package/templates/api/src/boards/api/endpoints/uploads.py +0 -149
  35. package/templates/api/src/boards/api/endpoints/webhooks.py +0 -13
  36. package/templates/api/src/boards/auth/__init__.py +0 -15
  37. package/templates/api/src/boards/auth/adapters/__init__.py +0 -27
  38. package/templates/api/src/boards/auth/adapters/auth0.py +0 -220
  39. package/templates/api/src/boards/auth/adapters/base.py +0 -73
  40. package/templates/api/src/boards/auth/adapters/clerk.py +0 -172
  41. package/templates/api/src/boards/auth/adapters/jwt.py +0 -122
  42. package/templates/api/src/boards/auth/adapters/none.py +0 -102
  43. package/templates/api/src/boards/auth/adapters/oidc.py +0 -284
  44. package/templates/api/src/boards/auth/adapters/supabase.py +0 -110
  45. package/templates/api/src/boards/auth/context.py +0 -35
  46. package/templates/api/src/boards/auth/factory.py +0 -129
  47. package/templates/api/src/boards/auth/middleware.py +0 -221
  48. package/templates/api/src/boards/auth/provisioning.py +0 -129
  49. package/templates/api/src/boards/auth/tenant_extraction.py +0 -278
  50. package/templates/api/src/boards/cli.py +0 -354
  51. package/templates/api/src/boards/config.py +0 -131
  52. package/templates/api/src/boards/database/__init__.py +0 -7
  53. package/templates/api/src/boards/database/cli.py +0 -110
  54. package/templates/api/src/boards/database/connection.py +0 -292
  55. package/templates/api/src/boards/database/models.py +0 -19
  56. package/templates/api/src/boards/database/seed_data.py +0 -182
  57. package/templates/api/src/boards/dbmodels/__init__.py +0 -441
  58. package/templates/api/src/boards/generators/__init__.py +0 -57
  59. package/templates/api/src/boards/generators/artifact_resolution.py +0 -405
  60. package/templates/api/src/boards/generators/artifacts.py +0 -53
  61. package/templates/api/src/boards/generators/base.py +0 -144
  62. package/templates/api/src/boards/generators/implementations/__init__.py +0 -14
  63. package/templates/api/src/boards/generators/implementations/fal/__init__.py +0 -25
  64. package/templates/api/src/boards/generators/implementations/fal/audio/__init__.py +0 -23
  65. package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_music_generation.py +0 -171
  66. package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_sound_effect_generation.py +0 -167
  67. package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_text_to_speech.py +0 -176
  68. package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_tts_turbo.py +0 -195
  69. package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_sound_effects_v2.py +0 -194
  70. package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_tts_eleven_v3.py +0 -209
  71. package/templates/api/src/boards/generators/implementations/fal/audio/fal_elevenlabs_tts_turbo_v2_5.py +0 -206
  72. package/templates/api/src/boards/generators/implementations/fal/audio/fal_minimax_speech_26_hd.py +0 -237
  73. package/templates/api/src/boards/generators/implementations/fal/audio/minimax_music_v2.py +0 -173
  74. package/templates/api/src/boards/generators/implementations/fal/audio/minimax_speech_2_6_turbo.py +0 -221
  75. package/templates/api/src/boards/generators/implementations/fal/image/__init__.py +0 -63
  76. package/templates/api/src/boards/generators/implementations/fal/image/bytedance_seedream_v45_edit.py +0 -219
  77. package/templates/api/src/boards/generators/implementations/fal/image/clarity_upscaler.py +0 -220
  78. package/templates/api/src/boards/generators/implementations/fal/image/crystal_upscaler.py +0 -173
  79. package/templates/api/src/boards/generators/implementations/fal/image/fal_ideogram_character.py +0 -227
  80. package/templates/api/src/boards/generators/implementations/fal/image/flux_2.py +0 -203
  81. package/templates/api/src/boards/generators/implementations/fal/image/flux_2_edit.py +0 -230
  82. package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro.py +0 -204
  83. package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro_edit.py +0 -221
  84. package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_kontext.py +0 -216
  85. package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_ultra.py +0 -197
  86. package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image.py +0 -177
  87. package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image_edit.py +0 -208
  88. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_15_edit.py +0 -216
  89. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_5.py +0 -177
  90. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_edit_image.py +0 -182
  91. package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_mini.py +0 -167
  92. package/templates/api/src/boards/generators/implementations/fal/image/ideogram_character_edit.py +0 -299
  93. package/templates/api/src/boards/generators/implementations/fal/image/ideogram_v2.py +0 -190
  94. package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview.py +0 -191
  95. package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview_fast.py +0 -179
  96. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana.py +0 -183
  97. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_edit.py +0 -212
  98. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro.py +0 -179
  99. package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro_edit.py +0 -226
  100. package/templates/api/src/boards/generators/implementations/fal/image/qwen_image.py +0 -249
  101. package/templates/api/src/boards/generators/implementations/fal/image/qwen_image_edit.py +0 -244
  102. package/templates/api/src/boards/generators/implementations/fal/image/reve_edit.py +0 -178
  103. package/templates/api/src/boards/generators/implementations/fal/image/reve_text_to_image.py +0 -155
  104. package/templates/api/src/boards/generators/implementations/fal/image/seedream_v45_text_to_image.py +0 -180
  105. package/templates/api/src/boards/generators/implementations/fal/utils.py +0 -61
  106. package/templates/api/src/boards/generators/implementations/fal/video/__init__.py +0 -77
  107. package/templates/api/src/boards/generators/implementations/fal/video/bytedance_seedance_v1_pro_text_to_video.py +0 -209
  108. package/templates/api/src/boards/generators/implementations/fal/video/creatify_lipsync.py +0 -161
  109. package/templates/api/src/boards/generators/implementations/fal/video/fal_bytedance_seedance_v1_pro_image_to_video.py +0 -222
  110. package/templates/api/src/boards/generators/implementations/fal/video/fal_minimax_hailuo_02_standard_text_to_video.py +0 -152
  111. package/templates/api/src/boards/generators/implementations/fal/video/fal_pixverse_lipsync.py +0 -197
  112. package/templates/api/src/boards/generators/implementations/fal/video/fal_sora_2_text_to_video.py +0 -173
  113. package/templates/api/src/boards/generators/implementations/fal/video/infinitalk.py +0 -221
  114. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_pro.py +0 -168
  115. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_standard.py +0 -159
  116. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_image_to_video.py +0 -175
  117. package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_text_to_video.py +0 -168
  118. package/templates/api/src/boards/generators/implementations/fal/video/minimax_hailuo_2_3_pro_image_to_video.py +0 -153
  119. package/templates/api/src/boards/generators/implementations/fal/video/sora2_image_to_video.py +0 -172
  120. package/templates/api/src/boards/generators/implementations/fal/video/sora_2_image_to_video_pro.py +0 -175
  121. package/templates/api/src/boards/generators/implementations/fal/video/sora_2_text_to_video_pro.py +0 -163
  122. package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2.py +0 -167
  123. package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2_pro.py +0 -155
  124. package/templates/api/src/boards/generators/implementations/fal/video/veed_fabric_1_0.py +0 -180
  125. package/templates/api/src/boards/generators/implementations/fal/video/veed_lipsync.py +0 -174
  126. package/templates/api/src/boards/generators/implementations/fal/video/veo3.py +0 -194
  127. package/templates/api/src/boards/generators/implementations/fal/video/veo31.py +0 -190
  128. package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast.py +0 -190
  129. package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast_image_to_video.py +0 -191
  130. package/templates/api/src/boards/generators/implementations/fal/video/veo31_first_last_frame_to_video.py +0 -187
  131. package/templates/api/src/boards/generators/implementations/fal/video/veo31_image_to_video.py +0 -183
  132. package/templates/api/src/boards/generators/implementations/fal/video/veo31_reference_to_video.py +0 -172
  133. package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_image_to_video.py +0 -212
  134. package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_text_to_video.py +0 -208
  135. package/templates/api/src/boards/generators/implementations/fal/video/wan_pro_image_to_video.py +0 -158
  136. package/templates/api/src/boards/generators/implementations/kie/__init__.py +0 -11
  137. package/templates/api/src/boards/generators/implementations/kie/base.py +0 -316
  138. package/templates/api/src/boards/generators/implementations/kie/image/__init__.py +0 -3
  139. package/templates/api/src/boards/generators/implementations/kie/image/nano_banana_edit.py +0 -190
  140. package/templates/api/src/boards/generators/implementations/kie/utils.py +0 -98
  141. package/templates/api/src/boards/generators/implementations/kie/video/__init__.py +0 -8
  142. package/templates/api/src/boards/generators/implementations/kie/video/veo3.py +0 -161
  143. package/templates/api/src/boards/generators/implementations/openai/__init__.py +0 -1
  144. package/templates/api/src/boards/generators/implementations/openai/audio/__init__.py +0 -1
  145. package/templates/api/src/boards/generators/implementations/openai/audio/whisper.py +0 -69
  146. package/templates/api/src/boards/generators/implementations/openai/image/__init__.py +0 -1
  147. package/templates/api/src/boards/generators/implementations/openai/image/dalle3.py +0 -96
  148. package/templates/api/src/boards/generators/implementations/replicate/__init__.py +0 -1
  149. package/templates/api/src/boards/generators/implementations/replicate/image/__init__.py +0 -1
  150. package/templates/api/src/boards/generators/implementations/replicate/image/flux_pro.py +0 -88
  151. package/templates/api/src/boards/generators/implementations/replicate/video/__init__.py +0 -1
  152. package/templates/api/src/boards/generators/implementations/replicate/video/lipsync.py +0 -73
  153. package/templates/api/src/boards/generators/loader.py +0 -253
  154. package/templates/api/src/boards/generators/registry.py +0 -114
  155. package/templates/api/src/boards/generators/resolution.py +0 -632
  156. package/templates/api/src/boards/generators/testmods/class_gen.py +0 -34
  157. package/templates/api/src/boards/generators/testmods/import_side_effect.py +0 -35
  158. package/templates/api/src/boards/graphql/__init__.py +0 -7
  159. package/templates/api/src/boards/graphql/access_control.py +0 -136
  160. package/templates/api/src/boards/graphql/mutations/root.py +0 -148
  161. package/templates/api/src/boards/graphql/queries/root.py +0 -116
  162. package/templates/api/src/boards/graphql/resolvers/__init__.py +0 -8
  163. package/templates/api/src/boards/graphql/resolvers/auth.py +0 -12
  164. package/templates/api/src/boards/graphql/resolvers/board.py +0 -1053
  165. package/templates/api/src/boards/graphql/resolvers/generation.py +0 -666
  166. package/templates/api/src/boards/graphql/resolvers/generator.py +0 -50
  167. package/templates/api/src/boards/graphql/resolvers/lineage.py +0 -381
  168. package/templates/api/src/boards/graphql/resolvers/upload.py +0 -463
  169. package/templates/api/src/boards/graphql/resolvers/user.py +0 -25
  170. package/templates/api/src/boards/graphql/schema.py +0 -81
  171. package/templates/api/src/boards/graphql/types/board.py +0 -102
  172. package/templates/api/src/boards/graphql/types/generation.py +0 -166
  173. package/templates/api/src/boards/graphql/types/generator.py +0 -17
  174. package/templates/api/src/boards/graphql/types/user.py +0 -47
  175. package/templates/api/src/boards/jobs/repository.py +0 -153
  176. package/templates/api/src/boards/logging.py +0 -195
  177. package/templates/api/src/boards/middleware.py +0 -339
  178. package/templates/api/src/boards/progress/__init__.py +0 -4
  179. package/templates/api/src/boards/progress/models.py +0 -25
  180. package/templates/api/src/boards/progress/publisher.py +0 -64
  181. package/templates/api/src/boards/py.typed +0 -0
  182. package/templates/api/src/boards/redis_pool.py +0 -118
  183. package/templates/api/src/boards/storage/__init__.py +0 -52
  184. package/templates/api/src/boards/storage/base.py +0 -363
  185. package/templates/api/src/boards/storage/config.py +0 -187
  186. package/templates/api/src/boards/storage/factory.py +0 -288
  187. package/templates/api/src/boards/storage/implementations/__init__.py +0 -27
  188. package/templates/api/src/boards/storage/implementations/gcs.py +0 -340
  189. package/templates/api/src/boards/storage/implementations/local.py +0 -201
  190. package/templates/api/src/boards/storage/implementations/s3.py +0 -294
  191. package/templates/api/src/boards/storage/implementations/supabase.py +0 -218
  192. package/templates/api/src/boards/tenant_isolation.py +0 -446
  193. package/templates/api/src/boards/validation.py +0 -262
  194. package/templates/api/src/boards/workers/__init__.py +0 -1
  195. package/templates/api/src/boards/workers/actors.py +0 -274
  196. package/templates/api/src/boards/workers/cli.py +0 -125
  197. package/templates/api/src/boards/workers/context.py +0 -348
  198. package/templates/api/src/boards/workers/middleware.py +0 -58
  199. package/templates/api/src/py.typed +0 -0
  200. package/templates/compose.web.yaml +0 -35
  201. package/templates/compose.yaml +0 -116
  202. package/templates/docker/env.example +0 -23
  203. package/templates/web/.env.example +0 -28
  204. package/templates/web/Dockerfile +0 -51
  205. package/templates/web/components.json +0 -22
  206. package/templates/web/imageLoader.js +0 -18
  207. package/templates/web/next-env.d.ts +0 -5
  208. package/templates/web/next.config.js +0 -36
  209. package/templates/web/package.json +0 -41
  210. package/templates/web/postcss.config.mjs +0 -7
  211. package/templates/web/public/favicon.ico +0 -0
  212. package/templates/web/src/app/boards/[boardId]/page.tsx +0 -353
  213. package/templates/web/src/app/globals.css +0 -123
  214. package/templates/web/src/app/layout.tsx +0 -31
  215. package/templates/web/src/app/lineage/[generationId]/page.tsx +0 -235
  216. package/templates/web/src/app/page.tsx +0 -35
  217. package/templates/web/src/app/providers.tsx +0 -18
  218. package/templates/web/src/components/boards/ArtifactInputSlots.tsx +0 -206
  219. package/templates/web/src/components/boards/ArtifactPreview.tsx +0 -466
  220. package/templates/web/src/components/boards/GenerationGrid.tsx +0 -282
  221. package/templates/web/src/components/boards/GenerationInput.tsx +0 -370
  222. package/templates/web/src/components/boards/GeneratorSelector.tsx +0 -272
  223. package/templates/web/src/components/boards/UploadArtifact.tsx +0 -563
  224. package/templates/web/src/components/header.tsx +0 -32
  225. package/templates/web/src/components/theme-provider.tsx +0 -10
  226. package/templates/web/src/components/theme-toggle.tsx +0 -75
  227. package/templates/web/src/components/ui/alert-dialog.tsx +0 -157
  228. package/templates/web/src/components/ui/button.tsx +0 -58
  229. package/templates/web/src/components/ui/card.tsx +0 -92
  230. package/templates/web/src/components/ui/dropdown-menu.tsx +0 -200
  231. package/templates/web/src/components/ui/navigation-menu.tsx +0 -168
  232. package/templates/web/src/components/ui/toast.tsx +0 -128
  233. package/templates/web/src/components/ui/toaster.tsx +0 -35
  234. package/templates/web/src/components/ui/use-toast.ts +0 -187
  235. package/templates/web/src/hooks/useGeneratorMRU.ts +0 -57
  236. package/templates/web/src/lib/utils.ts +0 -6
  237. package/templates/web/tsconfig.json +0 -41
@@ -1,502 +0,0 @@
1
- # Generators API Reference
2
-
3
- This document provides detailed API reference for the Boards generators system.
4
-
5
- ## Core Classes
6
-
7
- ### BaseGenerator
8
-
9
- Abstract base class for all generators.
10
-
11
- ```python
12
- from boards.generators.base import BaseGenerator
13
-
14
- class MyGenerator(BaseGenerator):
15
- name: str # Unique identifier for the generator
16
- artifact_type: str # Type of artifact produced ('image', 'video', 'audio', 'text', 'lora')
17
- description: str # Human-readable description
18
-
19
- def get_input_schema(self) -> Type[BaseModel]:
20
- """Return Pydantic model class for input validation."""
21
- pass
22
-
23
- async def generate(self, inputs: BaseModel) -> BaseModel:
24
- """Execute generation and return results."""
25
- pass
26
-
27
- async def estimate_cost(self, inputs: BaseModel) -> float:
28
- """Estimate cost in USD for this generation."""
29
- pass
30
-
31
- def get_output_schema(self) -> Type[BaseModel]:
32
- """Return Pydantic model class for output (optional override)."""
33
- pass
34
- ```
35
-
36
- #### Required Attributes
37
-
38
- - **`name`**: Unique string identifier (e.g., `"flux-pro"`, `"whisper"`)
39
- - **`artifact_type`**: One of `"image"`, `"video"`, `"audio"`, `"text"`, `"lora"`
40
- - **`description`**: Brief description of what the generator does
41
-
42
- #### Required Methods
43
-
44
- - **`get_input_schema()`**: Return the Pydantic model class that defines valid inputs
45
- - **`generate(inputs)`**: Core generation logic that produces artifacts
46
- - **`estimate_cost(inputs)`**: Return estimated cost in USD as a float
47
-
48
- ## Artifact Types
49
-
50
- ### ImageArtifact
51
-
52
- Represents generated or input images.
53
-
54
- ```python
55
- from boards.generators.artifacts import ImageArtifact
56
-
57
- artifact = ImageArtifact(
58
- generation_id="gen_123", # ID of generation that created this
59
- storage_url="https://...", # URL where image is stored
60
- width=1024, # Image width in pixels
61
- height=1024, # Image height in pixels
62
- format="png" # Image format (png, jpg, webp, etc.)
63
- )
64
- ```
65
-
66
- ### VideoArtifact
67
-
68
- Represents generated or input videos.
69
-
70
- ```python
71
- from boards.generators.artifacts import VideoArtifact
72
-
73
- artifact = VideoArtifact(
74
- generation_id="gen_456", # Required: generation ID
75
- storage_url="https://...", # Required: storage location
76
- width=1920, # Required: video width
77
- height=1080, # Required: video height
78
- format="mp4", # Required: video format
79
- duration=60.5, # Optional: duration in seconds
80
- fps=30.0 # Optional: frames per second
81
- )
82
- ```
83
-
84
- ### AudioArtifact
85
-
86
- Represents generated or input audio.
87
-
88
- ```python
89
- from boards.generators.artifacts import AudioArtifact
90
-
91
- artifact = AudioArtifact(
92
- generation_id="gen_789", # Required: generation ID
93
- storage_url="https://...", # Required: storage location
94
- format="mp3", # Required: audio format
95
- duration=120.0, # Optional: duration in seconds
96
- sample_rate=44100, # Optional: sample rate in Hz
97
- channels=2 # Optional: number of channels
98
- )
99
- ```
100
-
101
- ### TextArtifact
102
-
103
- Represents generated or input text.
104
-
105
- ```python
106
- from boards.generators.artifacts import TextArtifact
107
-
108
- artifact = TextArtifact(
109
- generation_id="gen_text", # Required: generation ID
110
- content="Generated text...", # Required: the actual text content
111
- format="plain" # Optional: format (plain, markdown, html)
112
- )
113
- ```
114
-
115
- ### LoRArtifact
116
-
117
- Represents LoRA (Low-Rank Adaptation) models.
118
-
119
- ```python
120
- from boards.generators.artifacts import LoRArtifact
121
-
122
- artifact = LoRArtifact(
123
- generation_id="gen_lora", # Required: generation ID
124
- storage_url="https://...", # Required: storage location
125
- base_model="sd-v1.5", # Required: base model name
126
- format="safetensors", # Required: file format
127
- trigger_words=["style1", "tag"] # Optional: trigger words list
128
- )
129
- ```
130
-
131
- ## Generator Registry
132
-
133
- ### Global Registry
134
-
135
- The system provides a global registry for managing generators:
136
-
137
- ```python
138
- from boards.generators.registry import registry
139
-
140
- # Register a generator
141
- generator_instance = MyGenerator()
142
- registry.register(generator_instance)
143
-
144
- # Get a generator by name
145
- generator = registry.get("my-generator")
146
-
147
- # List all generators
148
- all_generators = registry.list_all()
149
-
150
- # List generators by artifact type
151
- image_generators = registry.list_by_artifact_type("image")
152
-
153
- # Check if generator exists
154
- if "my-generator" in registry:
155
- print("Generator is registered")
156
-
157
- # Get count of registered generators
158
- count = len(registry)
159
- ```
160
-
161
- ### GeneratorRegistry Methods
162
-
163
- ```python
164
- class GeneratorRegistry:
165
- def register(self, generator: BaseGenerator) -> None:
166
- """Register a generator instance."""
167
-
168
- def get(self, name: str) -> Optional[BaseGenerator]:
169
- """Get generator by name, returns None if not found."""
170
-
171
- def list_all(self) -> List[BaseGenerator]:
172
- """Return all registered generators."""
173
-
174
- def list_by_artifact_type(self, artifact_type: str) -> List[BaseGenerator]:
175
- """Return generators that produce the specified artifact type."""
176
-
177
- def list_names(self) -> List[str]:
178
- """Return list of all registered generator names."""
179
-
180
- def unregister(self, name: str) -> bool:
181
- """Remove generator by name. Returns True if found and removed."""
182
-
183
- def clear(self) -> None:
184
- """Remove all registered generators."""
185
-
186
- def __contains__(self, name: str) -> bool:
187
- """Check if generator with name is registered."""
188
-
189
- def __len__(self) -> int:
190
- """Return number of registered generators."""
191
- ```
192
-
193
- ## Artifact Resolution
194
-
195
- ### resolve_artifact()
196
-
197
- Converts artifact references to local file paths for use with provider SDKs:
198
-
199
- ```python
200
- from boards.generators.resolution import resolve_artifact
201
-
202
- async def generate(self, inputs):
203
- # Resolve artifacts to local file paths
204
- audio_path = await resolve_artifact(inputs.audio_source)
205
- video_path = await resolve_artifact(inputs.video_source)
206
-
207
- # Now you can pass file paths to any provider SDK
208
- result = await provider.process(audio=audio_path, video=video_path)
209
- ```
210
-
211
- **Supported artifacts**: `AudioArtifact`, `VideoArtifact`, `ImageArtifact`, `LoRArtifact`
212
-
213
- **Not supported**: `TextArtifact` (use `.content` property directly)
214
-
215
- ### Store Result Functions
216
-
217
- Create artifact instances from generated content:
218
-
219
- ```python
220
- from boards.generators.resolution import (
221
- store_image_result,
222
- store_video_result,
223
- store_audio_result
224
- )
225
-
226
- # Store generated image
227
- image_artifact = await store_image_result(
228
- storage_url="https://storage.com/image.png",
229
- format="png",
230
- generation_id="gen_123",
231
- width=1024,
232
- height=1024
233
- )
234
-
235
- # Store generated video
236
- video_artifact = await store_video_result(
237
- storage_url="https://storage.com/video.mp4",
238
- format="mp4",
239
- generation_id="gen_456",
240
- width=1920,
241
- height=1080,
242
- duration=60.0, # Optional
243
- fps=30.0 # Optional
244
- )
245
-
246
- # Store generated audio
247
- audio_artifact = await store_audio_result(
248
- storage_url="https://storage.com/audio.mp3",
249
- format="mp3",
250
- generation_id="gen_789",
251
- duration=120.0, # Optional
252
- sample_rate=44100, # Optional
253
- channels=2 # Optional
254
- )
255
- ```
256
-
257
- ## Pydantic Integration
258
-
259
- ### Input Schema Patterns
260
-
261
- #### Basic Inputs
262
-
263
- ```python
264
- from pydantic import BaseModel, Field
265
-
266
- class BasicInput(BaseModel):
267
- prompt: str = Field(description="Text prompt")
268
- strength: float = Field(default=0.75, ge=0.0, le=1.0, description="Generation strength")
269
- seed: Optional[int] = Field(None, description="Random seed")
270
- ```
271
-
272
- #### Artifact Inputs
273
-
274
- ```python
275
- class ArtifactInput(BaseModel):
276
- image_source: ImageArtifact = Field(description="Input image")
277
- audio_source: AudioArtifact = Field(description="Input audio")
278
- reference_text: TextArtifact = Field(description="Reference text")
279
- ```
280
-
281
- #### Validation and Constraints
282
-
283
- ```python
284
- from pydantic import field_validator
285
-
286
- class ValidatedInput(BaseModel):
287
- prompt: str = Field(min_length=1, max_length=500)
288
- quality: str = Field(pattern="^(low|medium|high)$")
289
- dimensions: str = Field(pattern="^\\d+x\\d+$")
290
-
291
- @field_validator('prompt')
292
- @classmethod
293
- def validate_prompt(cls, v):
294
- if 'forbidden' in v.lower():
295
- raise ValueError('Prompt contains forbidden content')
296
- return v.strip()
297
- ```
298
-
299
- #### Conditional Fields
300
-
301
- ```python
302
- class ConditionalInput(BaseModel):
303
- mode: str = Field(pattern="^(text|image)$")
304
- text_prompt: Optional[str] = Field(None)
305
- image_prompt: Optional[ImageArtifact] = Field(None)
306
-
307
- @model_validator(mode='after')
308
- def validate_conditional_fields(self):
309
- if self.mode == 'text' and not self.text_prompt:
310
- raise ValueError('text_prompt required when mode=text')
311
- elif self.mode == 'image' and not self.image_prompt:
312
- raise ValueError('image_prompt required when mode=image')
313
- return self
314
- ```
315
-
316
- ### Output Schema Patterns
317
-
318
- #### Simple Outputs
319
-
320
- ```python
321
- class SimpleOutput(BaseModel):
322
- result: ImageArtifact
323
- metadata: dict = Field(default_factory=dict)
324
- ```
325
-
326
- #### Multiple Artifacts
327
-
328
- ```python
329
- class MultiOutput(BaseModel):
330
- images: List[ImageArtifact] = Field(description="Generated images")
331
- preview: ImageArtifact = Field(description="Low-res preview")
332
- generation_time: float = Field(description="Time taken in seconds")
333
- ```
334
-
335
- ## JSON Schema Generation
336
-
337
- Pydantic models automatically generate JSON schemas for frontend integration:
338
-
339
- ```python
340
- # Get JSON schema for frontend type generation
341
- schema = MyInputClass.model_json_schema()
342
-
343
- # Example output:
344
- {
345
- "type": "object",
346
- "properties": {
347
- "prompt": {
348
- "type": "string",
349
- "description": "Text prompt",
350
- "minLength": 1,
351
- "maxLength": 500
352
- },
353
- "strength": {
354
- "type": "number",
355
- "minimum": 0.0,
356
- "maximum": 1.0,
357
- "default": 0.75,
358
- "description": "Generation strength"
359
- }
360
- },
361
- "required": ["prompt"]
362
- }
363
- ```
364
-
365
- ## Error Handling
366
-
367
- ### Common Error Patterns
368
-
369
- ```python
370
- async def generate(self, inputs):
371
- # Check environment variables
372
- api_key = os.getenv("PROVIDER_API_KEY")
373
- if not api_key:
374
- raise ValueError(
375
- "PROVIDER_API_KEY environment variable required. "
376
- "Get your key from https://provider.com/keys"
377
- )
378
-
379
- # Provider-specific error handling
380
- try:
381
- result = await provider.generate(inputs)
382
- except provider.AuthenticationError:
383
- raise ValueError("Invalid API key - check PROVIDER_API_KEY")
384
- except provider.RateLimitError as e:
385
- raise ValueError(f"Rate limited - retry after {e.retry_after} seconds")
386
- except provider.ValidationError as e:
387
- raise ValueError(f"Invalid input: {e.message}")
388
- except Exception as e:
389
- raise RuntimeError(f"Generation failed: {str(e)}")
390
- ```
391
-
392
- ### Best Practices
393
-
394
- 1. **Specific Error Messages**: Provide actionable error messages
395
- 2. **Environment Variable Checks**: Validate required configuration early
396
- 3. **Provider Error Translation**: Convert provider errors to user-friendly messages
397
- 4. **Resource Cleanup**: Clean up temporary files in finally blocks
398
-
399
- ## Testing
400
-
401
- ### Generator Testing Pattern
402
-
403
- ```python
404
- import pytest
405
- from unittest.mock import patch, AsyncMock
406
-
407
- class TestMyGenerator:
408
- def setup_method(self):
409
- self.generator = MyGenerator()
410
-
411
- def test_metadata(self):
412
- assert self.generator.name == "my-generator"
413
- assert self.generator.artifact_type == "image"
414
-
415
- def test_input_schema(self):
416
- schema_class = self.generator.get_input_schema()
417
- assert schema_class == MyInputClass
418
-
419
- # Test schema validation
420
- valid_input = schema_class(prompt="test")
421
- assert valid_input.prompt == "test"
422
-
423
- @pytest.mark.asyncio
424
- async def test_generate_success(self):
425
- inputs = MyInputClass(prompt="test prompt")
426
-
427
- with patch.dict(os.environ, {"API_KEY": "fake-key"}):
428
- with patch('provider.generate') as mock_generate:
429
- mock_generate.return_value = "fake_result_url"
430
-
431
- result = await self.generator.generate(inputs)
432
-
433
- assert isinstance(result, MyOutputClass)
434
- mock_generate.assert_called_once()
435
-
436
- @pytest.mark.asyncio
437
- async def test_generate_missing_api_key(self):
438
- inputs = MyInputClass(prompt="test")
439
-
440
- with patch.dict(os.environ, {}, clear=True):
441
- with pytest.raises(ValueError, match="API_KEY.*required"):
442
- await self.generator.generate(inputs)
443
-
444
- @pytest.mark.asyncio
445
- async def test_estimate_cost(self):
446
- inputs = MyInputClass(prompt="short")
447
- cost = await self.generator.estimate_cost(inputs)
448
-
449
- assert isinstance(cost, float)
450
- assert cost > 0
451
- ```
452
-
453
- ## Integration Points
454
-
455
- ### Storage System Integration
456
-
457
- Generators integrate with the Boards storage system through the resolution utilities:
458
-
459
- ```python
460
- # The store_*_result functions will be implemented to:
461
- # 1. Upload content to configured storage backend (S3, local, etc.)
462
- # 2. Return artifact with proper storage_url
463
- # 3. Handle metadata and thumbnails
464
- ```
465
-
466
- ### Database Integration
467
-
468
- Generated artifacts are automatically stored in the database with:
469
-
470
- - Generation metadata (model, parameters, cost)
471
- - Artifact metadata (dimensions, duration, format)
472
- - Relationships to boards and users
473
- - Audit trail information
474
-
475
- ### GraphQL API Integration
476
-
477
- Registered generators are automatically exposed via GraphQL:
478
-
479
- ```graphql
480
- query GetGenerators($artifactType: String) {
481
- generators(artifactType: $artifactType) {
482
- name
483
- artifactType
484
- description
485
- inputSchema # JSON schema for frontend
486
- }
487
- }
488
-
489
- mutation RunGeneration($generatorName: String!, $inputs: JSON!) {
490
- runGeneration(generatorName: $generatorName, inputs: $inputs) {
491
- id
492
- status
493
- result {
494
- ... on ImageArtifact {
495
- storageUrl
496
- width
497
- height
498
- }
499
- }
500
- }
501
- }
502
- ```