@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,409 +0,0 @@
1
- # Adding Generators to Boards
2
-
3
- This guide explains how to create and add new generators to the Boards system. Generators are components that integrate AI generation services and define their input/output schemas using Pydantic models.
4
-
5
- ## Quick Start
6
-
7
- Creating a new generator involves just 3 steps:
8
-
9
- 1. **Define input/output schemas** using Pydantic models
10
- 2. **Implement the generator class** with generation logic
11
- 3. **Register the generator** with the system
12
-
13
- ## Example: Creating a Text-to-Speech Generator
14
-
15
- Let's create a generator that converts text to speech using ElevenLabs API:
16
-
17
- ### Step 1: Define Pydantic Schemas
18
-
19
- ```python
20
- from typing import Type, Optional
21
- from pydantic import BaseModel, Field
22
- from boards.generators.base import BaseGenerator
23
- from boards.generators.artifacts import TextArtifact, AudioArtifact
24
-
25
- class TTSInput(BaseModel):
26
- """Input schema for text-to-speech generation."""
27
- text_source: TextArtifact = Field(description="Text to convert to speech")
28
- voice_id: str = Field(description="Voice ID to use for generation")
29
- stability: float = Field(default=0.75, ge=0.0, le=1.0, description="Voice stability")
30
- clarity: float = Field(default=0.75, ge=0.0, le=1.0, description="Voice clarity")
31
-
32
- class TTSOutput(BaseModel):
33
- """Output schema for text-to-speech generation."""
34
- audio: AudioArtifact
35
- ```
36
-
37
- ### Step 2: Implement Generator Class
38
-
39
- ```python
40
- import os
41
- from boards.generators.resolution import store_audio_result
42
-
43
- class ElevenLabsTTSGenerator(BaseGenerator):
44
- """Text-to-speech generator using ElevenLabs API."""
45
-
46
- name = "elevenlabs-tts"
47
- artifact_type = "audio"
48
- description = "ElevenLabs text-to-speech generation"
49
-
50
- def get_input_schema(self) -> Type[TTSInput]:
51
- return TTSInput
52
-
53
- def get_output_schema(self) -> Type[TTSOutput]:
54
- return TTSOutput
55
-
56
- async def generate(self, inputs: TTSInput) -> TTSOutput:
57
- """Generate speech from text using ElevenLabs."""
58
- # Check for API key
59
- if not os.getenv("ELEVENLABS_API_KEY"):
60
- raise ValueError("ELEVENLABS_API_KEY environment variable is required")
61
-
62
- # Import SDK directly - no wrapper layer
63
- import elevenlabs
64
-
65
- # Get text content from the text artifact
66
- text_content = inputs.text_source.content
67
-
68
- # Use ElevenLabs SDK directly
69
- audio_bytes = elevenlabs.generate(
70
- text=text_content,
71
- voice=inputs.voice_id,
72
- model="eleven_monolingual_v1",
73
- voice_settings=elevenlabs.VoiceSettings(
74
- stability=inputs.stability,
75
- similarity_boost=inputs.clarity
76
- )
77
- )
78
-
79
- # TODO: In real implementation, upload to storage and get URL
80
- storage_url = "https://storage.example.com/generated_audio.mp3"
81
-
82
- # Create audio artifact
83
- audio_artifact = await store_audio_result(
84
- storage_url=storage_url,
85
- format="mp3",
86
- generation_id="temp_gen_id", # TODO: Get from generation context
87
- duration=None, # Could estimate from text length
88
- sample_rate=22050,
89
- channels=1
90
- )
91
-
92
- return TTSOutput(audio=audio_artifact)
93
-
94
- async def estimate_cost(self, inputs: TTSInput) -> float:
95
- """Estimate cost based on text length."""
96
- text_length = len(inputs.text_source.content)
97
- # ElevenLabs charges per character, roughly $0.0001 per character
98
- return text_length * 0.0001
99
- ```
100
-
101
- ### Step 3: Register the Generator
102
-
103
- ```python
104
- from boards.generators.registry import registry
105
-
106
- # Register the generator so it's available to the system
107
- registry.register(ElevenLabsTTSGenerator())
108
- ```
109
-
110
- ## Key Concepts
111
-
112
- ### Artifact Types
113
-
114
- Artifacts represent generated content and can be used as inputs to other generators:
115
-
116
- - **`ImageArtifact`**: Images (PNG, JPG, WebP, etc.)
117
- - **`VideoArtifact`**: Videos (MP4, WebM, etc.)
118
- - **`AudioArtifact`**: Audio files (MP3, WAV, etc.)
119
- - **`TextArtifact`**: Text content (plain, markdown, HTML, etc.)
120
- - **`LoRArtifact`**: LoRA models (SafeTensors, etc.)
121
-
122
- ### Artifact Resolution
123
-
124
- The system automatically resolves artifact references to file paths:
125
-
126
- ```python
127
- # If input has an artifact, resolve it to a usable file path
128
- audio_file_path = await resolve_artifact(inputs.audio_source)
129
-
130
- # Now you can pass the file path to any provider SDK
131
- result = await some_api.process_audio(audio_file_path)
132
- ```
133
-
134
- For `TextArtifact`, use the `.content` property directly:
135
-
136
- ```python
137
- # Text artifacts contain content directly
138
- text_content = inputs.text_source.content
139
- ```
140
-
141
- ### Environment Variables
142
-
143
- Generators should use environment variables for API keys and configuration:
144
-
145
- ```python
146
- import os
147
-
148
- # Check for required environment variables
149
- if not os.getenv("PROVIDER_API_KEY"):
150
- raise ValueError("PROVIDER_API_KEY environment variable is required")
151
- ```
152
-
153
- ## Advanced Examples
154
-
155
- ### Multiple Input Artifacts
156
-
157
- Some generators need multiple artifacts as input:
158
-
159
- ```python
160
- class VideoWithMusicInput(BaseModel):
161
- """Add background music to a video."""
162
- video_source: VideoArtifact = Field(description="Video to add music to")
163
- audio_source: AudioArtifact = Field(description="Background music")
164
- music_volume: float = Field(default=0.3, ge=0.0, le=1.0, description="Music volume")
165
-
166
- async def generate(self, inputs: VideoWithMusicInput) -> VideoWithMusicOutput:
167
- # Resolve both artifacts
168
- video_path = await resolve_artifact(inputs.video_source)
169
- audio_path = await resolve_artifact(inputs.audio_source)
170
-
171
- # Use both files with your provider SDK
172
- result = await provider.add_background_music(
173
- video=video_path,
174
- audio=audio_path,
175
- volume=inputs.music_volume
176
- )
177
-
178
- return VideoWithMusicOutput(video=result_artifact)
179
- ```
180
-
181
- ### Custom Validation
182
-
183
- Use Pydantic validators for complex input validation:
184
-
185
- ```python
186
- from pydantic import field_validator
187
-
188
- class CustomInput(BaseModel):
189
- prompt: str
190
- style: str
191
-
192
- @field_validator('style')
193
- @classmethod
194
- def validate_style(cls, v):
195
- allowed_styles = ['realistic', 'artistic', 'cartoon']
196
- if v not in allowed_styles:
197
- raise ValueError(f'Style must be one of {allowed_styles}')
198
- return v
199
- ```
200
-
201
- ### Conditional Fields
202
-
203
- Some inputs might be conditional on other fields:
204
-
205
- ```python
206
- from typing import Union
207
- from pydantic import Field
208
-
209
- class ConditionalInput(BaseModel):
210
- input_type: str = Field(description="Type of input", pattern="^(text|image)$")
211
- text_input: Optional[str] = Field(None, description="Text input (if input_type=text)")
212
- image_input: Optional[ImageArtifact] = Field(None, description="Image input (if input_type=image)")
213
-
214
- def model_validate(cls, values):
215
- input_type = values.get('input_type')
216
- if input_type == 'text' and not values.get('text_input'):
217
- raise ValueError('text_input is required when input_type=text')
218
- elif input_type == 'image' and not values.get('image_input'):
219
- raise ValueError('image_input is required when input_type=image')
220
- return values
221
- ```
222
-
223
- ## Testing Your Generator
224
-
225
- Create comprehensive tests for your generator:
226
-
227
- ```python
228
- import pytest
229
- from unittest.mock import patch, AsyncMock
230
-
231
- class TestElevenLabsTTSGenerator:
232
- def setup_method(self):
233
- self.generator = ElevenLabsTTSGenerator()
234
-
235
- def test_generator_metadata(self):
236
- assert self.generator.name == "elevenlabs-tts"
237
- assert self.generator.artifact_type == "audio"
238
-
239
- @pytest.mark.asyncio
240
- async def test_generate_success(self):
241
- input_data = TTSInput(
242
- text_source=TextArtifact(
243
- generation_id="test",
244
- content="Hello world"
245
- ),
246
- voice_id="voice_123"
247
- )
248
-
249
- with patch.dict(os.environ, {"ELEVENLABS_API_KEY": "fake-key"}):
250
- with patch('elevenlabs.generate') as mock_generate:
251
- mock_generate.return_value = b"fake audio bytes"
252
-
253
- result = await self.generator.generate(input_data)
254
-
255
- assert isinstance(result, TTSOutput)
256
- assert isinstance(result.audio, AudioArtifact)
257
- ```
258
-
259
- ## Best Practices
260
-
261
- ### 1. Use Provider SDKs Directly
262
-
263
- Don't create wrapper layers - import and use provider SDKs directly:
264
-
265
- ```python
266
- # Good: Use SDK directly
267
- import replicate
268
- result = await replicate.async_run("model", input=data)
269
-
270
- # Avoid: Creating unnecessary wrappers
271
- class ReplicateWrapper:
272
- def __init__(self): ...
273
- ```
274
-
275
- ### 2. Handle Errors Gracefully
276
-
277
- Provide clear error messages for common issues:
278
-
279
- ```python
280
- async def generate(self, inputs):
281
- if not os.getenv("API_KEY"):
282
- raise ValueError(
283
- "API_KEY environment variable is required. "
284
- "Get your key from https://provider.com/api-keys"
285
- )
286
-
287
- try:
288
- result = await provider_api.generate(inputs)
289
- except provider_api.AuthError:
290
- raise ValueError("Invalid API key - check your API_KEY environment variable")
291
- except provider_api.RateLimitError:
292
- raise ValueError("Rate limit exceeded - please try again later")
293
- ```
294
-
295
- ### 3. Accurate Cost Estimation
296
-
297
- Implement realistic cost estimation:
298
-
299
- ```python
300
- async def estimate_cost(self, inputs: MyInput) -> float:
301
- # Base cost
302
- base_cost = 0.01
303
-
304
- # Variable costs based on input complexity
305
- if inputs.high_quality:
306
- base_cost *= 2
307
-
308
- # Consider input size
309
- if hasattr(inputs, 'image_input'):
310
- # Larger images might cost more
311
- pixels = inputs.image_input.width * inputs.image_input.height
312
- base_cost += (pixels / 1000000) * 0.005 # $0.005 per megapixel
313
-
314
- return base_cost
315
- ```
316
-
317
- ### 4. Comprehensive Input Validation
318
-
319
- Use Pydantic's full validation capabilities:
320
-
321
- ```python
322
- class WellValidatedInput(BaseModel):
323
- prompt: str = Field(min_length=1, max_length=1000, description="Generation prompt")
324
- strength: float = Field(ge=0.0, le=1.0, description="Generation strength")
325
- seed: Optional[int] = Field(None, ge=0, description="Random seed for reproducibility")
326
-
327
- @field_validator('prompt')
328
- @classmethod
329
- def validate_prompt(cls, v):
330
- if len(v.strip()) == 0:
331
- raise ValueError('Prompt cannot be empty or only whitespace')
332
- return v.strip()
333
- ```
334
-
335
- ## Deployment and Registration
336
-
337
- ### Auto-Registration
338
-
339
- Generators can register themselves when their module is imported:
340
-
341
- ```python
342
- # At the bottom of your generator file
343
- from boards.generators.registry import registry
344
- registry.register(MyGenerator())
345
- ```
346
-
347
- ### Manual Registration
348
-
349
- For more control, register generators manually:
350
-
351
- ```python
352
- from boards.generators.registry import registry
353
- from my_generators import MyGenerator
354
-
355
- def setup_generators():
356
- registry.register(MyGenerator())
357
- # Register other generators...
358
-
359
- # Call during application startup
360
- setup_generators()
361
- ```
362
-
363
- ## Frontend Integration
364
-
365
- Once your generator is registered, the frontend automatically gets:
366
-
367
- 1. **TypeScript types** generated from your Pydantic schemas
368
- 2. **Form UI** with appropriate input fields
369
- 3. **Drag/drop zones** for artifact inputs
370
- 4. **Validation** based on your schema constraints
371
-
372
- The frontend will automatically create:
373
- - Text inputs for `str` fields
374
- - Number inputs for `int`/`float` fields
375
- - Dropdowns for fields with `enum` constraints
376
- - Drag/drop zones for `*Artifact` fields
377
- - Sliders for fields with `ge`/`le` constraints
378
-
379
- ## Example Integration
380
-
381
- Here's how your generator would be used from the frontend:
382
-
383
- ```typescript
384
- // TypeScript types auto-generated from Pydantic
385
- interface TTSInput {
386
- text_source: TextArtifact;
387
- voice_id: string;
388
- stability: number;
389
- clarity: number;
390
- }
391
-
392
- // UI automatically generated
393
- <GeneratorForm
394
- generatorName="elevenlabs-tts"
395
- onSubmit={handleGeneration}
396
- />
397
- ```
398
-
399
- This creates a form with:
400
- - A drag/drop zone for `text_source` (accepts text artifacts only)
401
- - A text input for `voice_id`
402
- - Sliders for `stability` and `clarity` (constrained 0.0-1.0)
403
-
404
- ## Need Help?
405
-
406
- - Check existing generators in `boards/generators/implementations/` for examples
407
- - All generators follow the same simple pattern
408
- - The system handles artifact resolution, storage, and UI generation automatically
409
- - Focus on your generation logic - the framework handles the rest!