@weirdfingers/baseboards 0.9.5 → 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.
- package/dist/index.js +561 -469
- package/dist/index.js.map +1 -1
- package/package.json +2 -5
- package/templates/README.md +0 -122
- package/templates/api/.env.example +0 -65
- package/templates/api/ARTIFACT_RESOLUTION_GUIDE.md +0 -148
- package/templates/api/Dockerfile +0 -32
- package/templates/api/README.md +0 -264
- package/templates/api/alembic/env.py +0 -114
- package/templates/api/alembic/script.py.mako +0 -28
- package/templates/api/alembic/versions/20250101_000000_initial_schema.py +0 -506
- package/templates/api/alembic/versions/20251022_174729_remove_provider_name_from_generations.py +0 -75
- package/templates/api/alembic/versions/20251023_165852_switch_to_declarative_base_and_mapping.py +0 -467
- package/templates/api/alembic/versions/20251202_000000_add_artifact_lineage.py +0 -134
- package/templates/api/alembic/versions/2025925_62735_add_seed_data_for_default_tenant.py +0 -88
- package/templates/api/alembic.ini +0 -36
- package/templates/api/config/generators.yaml +0 -237
- package/templates/api/config/storage_config.yaml +0 -26
- package/templates/api/docs/ADDING_GENERATORS.md +0 -409
- package/templates/api/docs/GENERATORS_API.md +0 -502
- package/templates/api/docs/MIGRATIONS.md +0 -472
- package/templates/api/docs/TESTING_LIVE_APIS.md +0 -417
- package/templates/api/docs/storage_providers.md +0 -337
- package/templates/api/pyproject.toml +0 -205
- package/templates/api/src/boards/__init__.py +0 -10
- package/templates/api/src/boards/api/app.py +0 -172
- package/templates/api/src/boards/api/auth.py +0 -75
- package/templates/api/src/boards/api/endpoints/__init__.py +0 -3
- package/templates/api/src/boards/api/endpoints/jobs.py +0 -76
- package/templates/api/src/boards/api/endpoints/setup.py +0 -505
- package/templates/api/src/boards/api/endpoints/sse.py +0 -129
- package/templates/api/src/boards/api/endpoints/storage.py +0 -155
- package/templates/api/src/boards/api/endpoints/tenant_registration.py +0 -296
- package/templates/api/src/boards/api/endpoints/uploads.py +0 -149
- package/templates/api/src/boards/api/endpoints/webhooks.py +0 -13
- package/templates/api/src/boards/auth/__init__.py +0 -15
- package/templates/api/src/boards/auth/adapters/__init__.py +0 -27
- package/templates/api/src/boards/auth/adapters/auth0.py +0 -220
- package/templates/api/src/boards/auth/adapters/base.py +0 -73
- package/templates/api/src/boards/auth/adapters/clerk.py +0 -172
- package/templates/api/src/boards/auth/adapters/jwt.py +0 -122
- package/templates/api/src/boards/auth/adapters/none.py +0 -102
- package/templates/api/src/boards/auth/adapters/oidc.py +0 -284
- package/templates/api/src/boards/auth/adapters/supabase.py +0 -110
- package/templates/api/src/boards/auth/context.py +0 -35
- package/templates/api/src/boards/auth/factory.py +0 -129
- package/templates/api/src/boards/auth/middleware.py +0 -221
- package/templates/api/src/boards/auth/provisioning.py +0 -129
- package/templates/api/src/boards/auth/tenant_extraction.py +0 -278
- package/templates/api/src/boards/cli.py +0 -354
- package/templates/api/src/boards/config.py +0 -131
- package/templates/api/src/boards/database/__init__.py +0 -7
- package/templates/api/src/boards/database/cli.py +0 -110
- package/templates/api/src/boards/database/connection.py +0 -292
- package/templates/api/src/boards/database/models.py +0 -19
- package/templates/api/src/boards/database/seed_data.py +0 -182
- package/templates/api/src/boards/dbmodels/__init__.py +0 -441
- package/templates/api/src/boards/generators/__init__.py +0 -57
- package/templates/api/src/boards/generators/artifact_resolution.py +0 -405
- package/templates/api/src/boards/generators/artifacts.py +0 -53
- package/templates/api/src/boards/generators/base.py +0 -144
- package/templates/api/src/boards/generators/implementations/__init__.py +0 -14
- package/templates/api/src/boards/generators/implementations/fal/__init__.py +0 -25
- package/templates/api/src/boards/generators/implementations/fal/audio/__init__.py +0 -23
- package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_music_generation.py +0 -171
- package/templates/api/src/boards/generators/implementations/fal/audio/beatoven_sound_effect_generation.py +0 -167
- package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_text_to_speech.py +0 -176
- package/templates/api/src/boards/generators/implementations/fal/audio/chatterbox_tts_turbo.py +0 -195
- package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_sound_effects_v2.py +0 -194
- package/templates/api/src/boards/generators/implementations/fal/audio/elevenlabs_tts_eleven_v3.py +0 -209
- package/templates/api/src/boards/generators/implementations/fal/audio/fal_elevenlabs_tts_turbo_v2_5.py +0 -206
- package/templates/api/src/boards/generators/implementations/fal/audio/fal_minimax_speech_26_hd.py +0 -237
- package/templates/api/src/boards/generators/implementations/fal/audio/minimax_music_v2.py +0 -173
- package/templates/api/src/boards/generators/implementations/fal/audio/minimax_speech_2_6_turbo.py +0 -221
- package/templates/api/src/boards/generators/implementations/fal/image/__init__.py +0 -63
- package/templates/api/src/boards/generators/implementations/fal/image/bytedance_seedream_v45_edit.py +0 -219
- package/templates/api/src/boards/generators/implementations/fal/image/clarity_upscaler.py +0 -220
- package/templates/api/src/boards/generators/implementations/fal/image/crystal_upscaler.py +0 -173
- package/templates/api/src/boards/generators/implementations/fal/image/fal_ideogram_character.py +0 -227
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2.py +0 -203
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_edit.py +0 -230
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro.py +0 -204
- package/templates/api/src/boards/generators/implementations/fal/image/flux_2_pro_edit.py +0 -221
- package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_kontext.py +0 -216
- package/templates/api/src/boards/generators/implementations/fal/image/flux_pro_ultra.py +0 -197
- package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image.py +0 -177
- package/templates/api/src/boards/generators/implementations/fal/image/gemini_25_flash_image_edit.py +0 -208
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_15_edit.py +0 -216
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_5.py +0 -177
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_edit_image.py +0 -182
- package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_mini.py +0 -167
- package/templates/api/src/boards/generators/implementations/fal/image/ideogram_character_edit.py +0 -299
- package/templates/api/src/boards/generators/implementations/fal/image/ideogram_v2.py +0 -190
- package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview.py +0 -191
- package/templates/api/src/boards/generators/implementations/fal/image/imagen4_preview_fast.py +0 -179
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana.py +0 -183
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_edit.py +0 -212
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro.py +0 -179
- package/templates/api/src/boards/generators/implementations/fal/image/nano_banana_pro_edit.py +0 -226
- package/templates/api/src/boards/generators/implementations/fal/image/qwen_image.py +0 -249
- package/templates/api/src/boards/generators/implementations/fal/image/qwen_image_edit.py +0 -244
- package/templates/api/src/boards/generators/implementations/fal/image/reve_edit.py +0 -178
- package/templates/api/src/boards/generators/implementations/fal/image/reve_text_to_image.py +0 -155
- package/templates/api/src/boards/generators/implementations/fal/image/seedream_v45_text_to_image.py +0 -180
- package/templates/api/src/boards/generators/implementations/fal/utils.py +0 -61
- package/templates/api/src/boards/generators/implementations/fal/video/__init__.py +0 -77
- package/templates/api/src/boards/generators/implementations/fal/video/bytedance_seedance_v1_pro_text_to_video.py +0 -209
- package/templates/api/src/boards/generators/implementations/fal/video/creatify_lipsync.py +0 -161
- package/templates/api/src/boards/generators/implementations/fal/video/fal_bytedance_seedance_v1_pro_image_to_video.py +0 -222
- package/templates/api/src/boards/generators/implementations/fal/video/fal_minimax_hailuo_02_standard_text_to_video.py +0 -152
- package/templates/api/src/boards/generators/implementations/fal/video/fal_pixverse_lipsync.py +0 -197
- package/templates/api/src/boards/generators/implementations/fal/video/fal_sora_2_text_to_video.py +0 -173
- package/templates/api/src/boards/generators/implementations/fal/video/infinitalk.py +0 -221
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_pro.py +0 -168
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_ai_avatar_v2_standard.py +0 -159
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_image_to_video.py +0 -175
- package/templates/api/src/boards/generators/implementations/fal/video/kling_video_v2_5_turbo_pro_text_to_video.py +0 -168
- package/templates/api/src/boards/generators/implementations/fal/video/minimax_hailuo_2_3_pro_image_to_video.py +0 -153
- package/templates/api/src/boards/generators/implementations/fal/video/sora2_image_to_video.py +0 -172
- package/templates/api/src/boards/generators/implementations/fal/video/sora_2_image_to_video_pro.py +0 -175
- package/templates/api/src/boards/generators/implementations/fal/video/sora_2_text_to_video_pro.py +0 -163
- package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2.py +0 -167
- package/templates/api/src/boards/generators/implementations/fal/video/sync_lipsync_v2_pro.py +0 -155
- package/templates/api/src/boards/generators/implementations/fal/video/veed_fabric_1_0.py +0 -180
- package/templates/api/src/boards/generators/implementations/fal/video/veed_lipsync.py +0 -174
- package/templates/api/src/boards/generators/implementations/fal/video/veo3.py +0 -194
- package/templates/api/src/boards/generators/implementations/fal/video/veo31.py +0 -190
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast.py +0 -190
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_fast_image_to_video.py +0 -191
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_first_last_frame_to_video.py +0 -187
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_image_to_video.py +0 -183
- package/templates/api/src/boards/generators/implementations/fal/video/veo31_reference_to_video.py +0 -172
- package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_image_to_video.py +0 -212
- package/templates/api/src/boards/generators/implementations/fal/video/wan_25_preview_text_to_video.py +0 -208
- package/templates/api/src/boards/generators/implementations/fal/video/wan_pro_image_to_video.py +0 -158
- package/templates/api/src/boards/generators/implementations/kie/__init__.py +0 -11
- package/templates/api/src/boards/generators/implementations/kie/base.py +0 -316
- package/templates/api/src/boards/generators/implementations/kie/image/__init__.py +0 -3
- package/templates/api/src/boards/generators/implementations/kie/image/nano_banana_edit.py +0 -190
- package/templates/api/src/boards/generators/implementations/kie/utils.py +0 -98
- package/templates/api/src/boards/generators/implementations/kie/video/__init__.py +0 -8
- package/templates/api/src/boards/generators/implementations/kie/video/veo3.py +0 -161
- package/templates/api/src/boards/generators/implementations/openai/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/openai/audio/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/openai/audio/whisper.py +0 -69
- package/templates/api/src/boards/generators/implementations/openai/image/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/openai/image/dalle3.py +0 -96
- package/templates/api/src/boards/generators/implementations/replicate/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/replicate/image/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/replicate/image/flux_pro.py +0 -88
- package/templates/api/src/boards/generators/implementations/replicate/video/__init__.py +0 -1
- package/templates/api/src/boards/generators/implementations/replicate/video/lipsync.py +0 -73
- package/templates/api/src/boards/generators/loader.py +0 -253
- package/templates/api/src/boards/generators/registry.py +0 -114
- package/templates/api/src/boards/generators/resolution.py +0 -632
- package/templates/api/src/boards/generators/testmods/class_gen.py +0 -34
- package/templates/api/src/boards/generators/testmods/import_side_effect.py +0 -35
- package/templates/api/src/boards/graphql/__init__.py +0 -7
- package/templates/api/src/boards/graphql/access_control.py +0 -136
- package/templates/api/src/boards/graphql/mutations/root.py +0 -148
- package/templates/api/src/boards/graphql/queries/root.py +0 -116
- package/templates/api/src/boards/graphql/resolvers/__init__.py +0 -8
- package/templates/api/src/boards/graphql/resolvers/auth.py +0 -12
- package/templates/api/src/boards/graphql/resolvers/board.py +0 -1053
- package/templates/api/src/boards/graphql/resolvers/generation.py +0 -666
- package/templates/api/src/boards/graphql/resolvers/generator.py +0 -50
- package/templates/api/src/boards/graphql/resolvers/lineage.py +0 -381
- package/templates/api/src/boards/graphql/resolvers/upload.py +0 -463
- package/templates/api/src/boards/graphql/resolvers/user.py +0 -25
- package/templates/api/src/boards/graphql/schema.py +0 -81
- package/templates/api/src/boards/graphql/types/board.py +0 -102
- package/templates/api/src/boards/graphql/types/generation.py +0 -166
- package/templates/api/src/boards/graphql/types/generator.py +0 -17
- package/templates/api/src/boards/graphql/types/user.py +0 -47
- package/templates/api/src/boards/jobs/repository.py +0 -153
- package/templates/api/src/boards/logging.py +0 -195
- package/templates/api/src/boards/middleware.py +0 -339
- package/templates/api/src/boards/progress/__init__.py +0 -4
- package/templates/api/src/boards/progress/models.py +0 -25
- package/templates/api/src/boards/progress/publisher.py +0 -64
- package/templates/api/src/boards/py.typed +0 -0
- package/templates/api/src/boards/redis_pool.py +0 -118
- package/templates/api/src/boards/storage/__init__.py +0 -52
- package/templates/api/src/boards/storage/base.py +0 -363
- package/templates/api/src/boards/storage/config.py +0 -187
- package/templates/api/src/boards/storage/factory.py +0 -288
- package/templates/api/src/boards/storage/implementations/__init__.py +0 -27
- package/templates/api/src/boards/storage/implementations/gcs.py +0 -340
- package/templates/api/src/boards/storage/implementations/local.py +0 -201
- package/templates/api/src/boards/storage/implementations/s3.py +0 -294
- package/templates/api/src/boards/storage/implementations/supabase.py +0 -218
- package/templates/api/src/boards/tenant_isolation.py +0 -446
- package/templates/api/src/boards/validation.py +0 -262
- package/templates/api/src/boards/workers/__init__.py +0 -1
- package/templates/api/src/boards/workers/actors.py +0 -274
- package/templates/api/src/boards/workers/cli.py +0 -125
- package/templates/api/src/boards/workers/context.py +0 -348
- package/templates/api/src/boards/workers/middleware.py +0 -58
- package/templates/api/src/py.typed +0 -0
- package/templates/compose.web.yaml +0 -35
- package/templates/compose.yaml +0 -116
- package/templates/docker/env.example +0 -23
- package/templates/web/.env.example +0 -28
- package/templates/web/Dockerfile +0 -51
- package/templates/web/components.json +0 -22
- package/templates/web/imageLoader.js +0 -18
- package/templates/web/next-env.d.ts +0 -5
- package/templates/web/next.config.js +0 -36
- package/templates/web/package.json +0 -41
- package/templates/web/postcss.config.mjs +0 -7
- package/templates/web/public/favicon.ico +0 -0
- package/templates/web/src/app/boards/[boardId]/page.tsx +0 -353
- package/templates/web/src/app/globals.css +0 -123
- package/templates/web/src/app/layout.tsx +0 -31
- package/templates/web/src/app/lineage/[generationId]/page.tsx +0 -235
- package/templates/web/src/app/page.tsx +0 -35
- package/templates/web/src/app/providers.tsx +0 -18
- package/templates/web/src/components/boards/ArtifactInputSlots.tsx +0 -206
- package/templates/web/src/components/boards/ArtifactPreview.tsx +0 -466
- package/templates/web/src/components/boards/GenerationGrid.tsx +0 -282
- package/templates/web/src/components/boards/GenerationInput.tsx +0 -370
- package/templates/web/src/components/boards/GeneratorSelector.tsx +0 -272
- package/templates/web/src/components/boards/UploadArtifact.tsx +0 -563
- package/templates/web/src/components/header.tsx +0 -32
- package/templates/web/src/components/theme-provider.tsx +0 -10
- package/templates/web/src/components/theme-toggle.tsx +0 -75
- package/templates/web/src/components/ui/alert-dialog.tsx +0 -157
- package/templates/web/src/components/ui/button.tsx +0 -58
- package/templates/web/src/components/ui/card.tsx +0 -92
- package/templates/web/src/components/ui/dropdown-menu.tsx +0 -200
- package/templates/web/src/components/ui/navigation-menu.tsx +0 -168
- package/templates/web/src/components/ui/toast.tsx +0 -128
- package/templates/web/src/components/ui/toaster.tsx +0 -35
- package/templates/web/src/components/ui/use-toast.ts +0 -187
- package/templates/web/src/hooks/useGeneratorMRU.ts +0 -57
- package/templates/web/src/lib/utils.ts +0 -6
- package/templates/web/tsconfig.json +0 -41
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
fal.ai GPT Image 1.5 text-to-image generator.
|
|
3
|
-
|
|
4
|
-
Generate high-fidelity images using GPT Image 1.5 with strong prompt adherence,
|
|
5
|
-
preserving composition, lighting, and fine-grained detail.
|
|
6
|
-
|
|
7
|
-
Based on Fal AI's fal-ai/gpt-image-1.5 model.
|
|
8
|
-
See: https://fal.ai/models/fal-ai/gpt-image-1.5
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
from typing import Literal
|
|
13
|
-
|
|
14
|
-
from pydantic import BaseModel, Field
|
|
15
|
-
|
|
16
|
-
from ....base import BaseGenerator, GeneratorExecutionContext, GeneratorResult
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class GptImage15Input(BaseModel):
|
|
20
|
-
"""Input schema for GPT Image 1.5.
|
|
21
|
-
|
|
22
|
-
Artifact fields are automatically detected via type introspection
|
|
23
|
-
and resolved from generation IDs to artifact objects.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
prompt: str = Field(
|
|
27
|
-
description="The prompt for image generation",
|
|
28
|
-
min_length=2,
|
|
29
|
-
)
|
|
30
|
-
num_images: int = Field(
|
|
31
|
-
default=1,
|
|
32
|
-
ge=1,
|
|
33
|
-
le=4,
|
|
34
|
-
description="Number of images to generate",
|
|
35
|
-
)
|
|
36
|
-
image_size: Literal["1024x1024", "1536x1024", "1024x1536"] = Field(
|
|
37
|
-
default="1024x1024",
|
|
38
|
-
description="Aspect ratio for the generated image",
|
|
39
|
-
)
|
|
40
|
-
background: Literal["auto", "transparent", "opaque"] = Field(
|
|
41
|
-
default="auto",
|
|
42
|
-
description="Background for the generated image",
|
|
43
|
-
)
|
|
44
|
-
quality: Literal["low", "medium", "high"] = Field(
|
|
45
|
-
default="high",
|
|
46
|
-
description="Quality for the generated image",
|
|
47
|
-
)
|
|
48
|
-
output_format: Literal["jpeg", "png", "webp"] = Field(
|
|
49
|
-
default="png",
|
|
50
|
-
description="Output format for the images",
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class FalGptImage15Generator(BaseGenerator):
|
|
55
|
-
"""GPT Image 1.5 text-to-image generator using fal.ai."""
|
|
56
|
-
|
|
57
|
-
name = "fal-gpt-image-1-5"
|
|
58
|
-
artifact_type = "image"
|
|
59
|
-
description = "Fal: GPT Image 1.5 - High-fidelity image generation with strong prompt adherence"
|
|
60
|
-
|
|
61
|
-
def get_input_schema(self) -> type[GptImage15Input]:
|
|
62
|
-
return GptImage15Input
|
|
63
|
-
|
|
64
|
-
async def generate(
|
|
65
|
-
self, inputs: GptImage15Input, context: GeneratorExecutionContext
|
|
66
|
-
) -> GeneratorResult:
|
|
67
|
-
"""Generate images using fal.ai gpt-image-1.5 model."""
|
|
68
|
-
# Check for API key (fal-client uses FAL_KEY environment variable)
|
|
69
|
-
if not os.getenv("FAL_KEY"):
|
|
70
|
-
raise ValueError("API configuration invalid. Missing FAL_KEY environment variable")
|
|
71
|
-
|
|
72
|
-
# Import fal_client
|
|
73
|
-
try:
|
|
74
|
-
import fal_client
|
|
75
|
-
except ImportError as e:
|
|
76
|
-
raise ImportError(
|
|
77
|
-
"fal.ai SDK is required for FalGptImage15Generator. "
|
|
78
|
-
"Install with: pip install weirdfingers-boards[generators-fal]"
|
|
79
|
-
) from e
|
|
80
|
-
|
|
81
|
-
# Prepare arguments for fal.ai API
|
|
82
|
-
arguments = {
|
|
83
|
-
"prompt": inputs.prompt,
|
|
84
|
-
"num_images": inputs.num_images,
|
|
85
|
-
"image_size": inputs.image_size,
|
|
86
|
-
"background": inputs.background,
|
|
87
|
-
"quality": inputs.quality,
|
|
88
|
-
"output_format": inputs.output_format,
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
# Submit async job and get handler
|
|
92
|
-
handler = await fal_client.submit_async(
|
|
93
|
-
"fal-ai/gpt-image-1.5",
|
|
94
|
-
arguments=arguments,
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
# Store the external job ID for tracking
|
|
98
|
-
await context.set_external_job_id(handler.request_id)
|
|
99
|
-
|
|
100
|
-
# Stream progress updates (sample every 3rd event to avoid spam)
|
|
101
|
-
from .....progress.models import ProgressUpdate
|
|
102
|
-
|
|
103
|
-
event_count = 0
|
|
104
|
-
async for event in handler.iter_events(with_logs=True):
|
|
105
|
-
event_count += 1
|
|
106
|
-
|
|
107
|
-
# Process every 3rd event to provide feedback without overwhelming
|
|
108
|
-
if event_count % 3 == 0:
|
|
109
|
-
# Extract logs if available
|
|
110
|
-
logs = getattr(event, "logs", None)
|
|
111
|
-
if logs:
|
|
112
|
-
# Join log entries into a single message
|
|
113
|
-
if isinstance(logs, list):
|
|
114
|
-
message = " | ".join(str(log) for log in logs if log)
|
|
115
|
-
else:
|
|
116
|
-
message = str(logs)
|
|
117
|
-
|
|
118
|
-
if message:
|
|
119
|
-
await context.publish_progress(
|
|
120
|
-
ProgressUpdate(
|
|
121
|
-
job_id=handler.request_id,
|
|
122
|
-
status="processing",
|
|
123
|
-
progress=50.0, # Approximate mid-point progress
|
|
124
|
-
phase="processing",
|
|
125
|
-
message=message,
|
|
126
|
-
)
|
|
127
|
-
)
|
|
128
|
-
|
|
129
|
-
# Get final result
|
|
130
|
-
result = await handler.get()
|
|
131
|
-
|
|
132
|
-
# Extract image URLs from result
|
|
133
|
-
# fal.ai returns: {
|
|
134
|
-
# "images": [{"url": "...", "content_type": "...", "width": ..., "height": ...}, ...]
|
|
135
|
-
# }
|
|
136
|
-
images = result.get("images", [])
|
|
137
|
-
|
|
138
|
-
if not images:
|
|
139
|
-
raise ValueError("No images returned from fal.ai API")
|
|
140
|
-
|
|
141
|
-
# Parse target dimensions from image_size
|
|
142
|
-
size_parts = inputs.image_size.split("x")
|
|
143
|
-
target_width = int(size_parts[0])
|
|
144
|
-
target_height = int(size_parts[1])
|
|
145
|
-
|
|
146
|
-
# Store each image using output_index
|
|
147
|
-
artifacts = []
|
|
148
|
-
for idx, image_data in enumerate(images):
|
|
149
|
-
image_url = image_data.get("url")
|
|
150
|
-
# Extract dimensions if available, otherwise use target dimensions from input
|
|
151
|
-
width = image_data.get("width") or target_width
|
|
152
|
-
height = image_data.get("height") or target_height
|
|
153
|
-
|
|
154
|
-
if not image_url:
|
|
155
|
-
raise ValueError(f"Image {idx} missing URL in fal.ai response")
|
|
156
|
-
|
|
157
|
-
# Store with appropriate output_index
|
|
158
|
-
artifact = await context.store_image_result(
|
|
159
|
-
storage_url=image_url,
|
|
160
|
-
format=inputs.output_format,
|
|
161
|
-
width=width,
|
|
162
|
-
height=height,
|
|
163
|
-
output_index=idx,
|
|
164
|
-
)
|
|
165
|
-
artifacts.append(artifact)
|
|
166
|
-
|
|
167
|
-
return GeneratorResult(outputs=artifacts)
|
|
168
|
-
|
|
169
|
-
async def estimate_cost(self, inputs: GptImage15Input) -> float:
|
|
170
|
-
"""Estimate cost for GPT Image 1.5 generation.
|
|
171
|
-
|
|
172
|
-
Using estimated cost per image (pricing not documented).
|
|
173
|
-
GPT Image 1.5 is a higher-quality model compared to mini version.
|
|
174
|
-
"""
|
|
175
|
-
# Estimated cost per image
|
|
176
|
-
per_image_cost = 0.04
|
|
177
|
-
return per_image_cost * inputs.num_images
|
package/templates/api/src/boards/generators/implementations/fal/image/gpt_image_1_edit_image.py
DELETED
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
fal.ai GPT-Image-1 image editing generator.
|
|
3
|
-
|
|
4
|
-
Edit images using OpenAI's GPT-Image-1 model via fal.ai.
|
|
5
|
-
Based on Fal AI's fal-ai/gpt-image-1/edit-image model.
|
|
6
|
-
See: https://fal.ai/models/fal-ai/gpt-image-1/edit-image
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import os
|
|
10
|
-
from typing import Literal
|
|
11
|
-
|
|
12
|
-
from pydantic import BaseModel, Field
|
|
13
|
-
|
|
14
|
-
from ....artifacts import ImageArtifact
|
|
15
|
-
from ....base import BaseGenerator, GeneratorExecutionContext, GeneratorResult
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class GptImage1EditImageInput(BaseModel):
|
|
19
|
-
"""Input schema for GPT-Image-1 image editing.
|
|
20
|
-
|
|
21
|
-
Artifact fields are automatically detected via type introspection
|
|
22
|
-
and resolved from generation IDs to artifact objects.
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
prompt: str = Field(
|
|
26
|
-
description="Edit instruction for transforming the input images",
|
|
27
|
-
min_length=1,
|
|
28
|
-
max_length=32000,
|
|
29
|
-
)
|
|
30
|
-
image_urls: list[ImageArtifact] = Field(
|
|
31
|
-
description="URLs of images to use as reference for editing",
|
|
32
|
-
min_length=1,
|
|
33
|
-
)
|
|
34
|
-
num_images: int = Field(
|
|
35
|
-
default=1,
|
|
36
|
-
ge=1,
|
|
37
|
-
le=4,
|
|
38
|
-
description="Number of edited images to generate (1-4)",
|
|
39
|
-
)
|
|
40
|
-
image_size: Literal["auto", "1024x1024", "1536x1024", "1024x1536"] = Field(
|
|
41
|
-
default="auto",
|
|
42
|
-
description="Size of the output images",
|
|
43
|
-
)
|
|
44
|
-
input_fidelity: Literal["low", "high"] = Field(
|
|
45
|
-
default="low",
|
|
46
|
-
description="How closely to follow the input image",
|
|
47
|
-
)
|
|
48
|
-
quality: Literal["auto", "low", "medium", "high"] = Field(
|
|
49
|
-
default="auto",
|
|
50
|
-
description="Quality level of the output images",
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class FalGptImage1EditImageGenerator(BaseGenerator):
|
|
55
|
-
"""Generator for OpenAI's GPT-Image-1 image editing via fal.ai."""
|
|
56
|
-
|
|
57
|
-
name = "fal-gpt-image-1-edit-image"
|
|
58
|
-
description = "Fal: GPT-Image-1 Edit - OpenAI's image editing model"
|
|
59
|
-
artifact_type = "image"
|
|
60
|
-
|
|
61
|
-
def get_input_schema(self) -> type[GptImage1EditImageInput]:
|
|
62
|
-
"""Return the input schema for this generator."""
|
|
63
|
-
return GptImage1EditImageInput
|
|
64
|
-
|
|
65
|
-
async def generate(
|
|
66
|
-
self, inputs: GptImage1EditImageInput, context: GeneratorExecutionContext
|
|
67
|
-
) -> GeneratorResult:
|
|
68
|
-
"""Generate edited images using fal.ai GPT-Image-1."""
|
|
69
|
-
# Check for API key
|
|
70
|
-
if not os.getenv("FAL_KEY"):
|
|
71
|
-
raise ValueError("API configuration invalid. Missing FAL_KEY environment variable")
|
|
72
|
-
|
|
73
|
-
# Import fal_client
|
|
74
|
-
try:
|
|
75
|
-
import fal_client
|
|
76
|
-
except ImportError as e:
|
|
77
|
-
raise ImportError(
|
|
78
|
-
"fal.ai SDK is required for FalGptImage1EditImageGenerator. "
|
|
79
|
-
"Install with: pip install weirdfingers-boards[generators-fal]"
|
|
80
|
-
) from e
|
|
81
|
-
|
|
82
|
-
# Upload image artifacts to Fal's public storage
|
|
83
|
-
# Fal API requires publicly accessible URLs
|
|
84
|
-
from ..utils import upload_artifacts_to_fal
|
|
85
|
-
|
|
86
|
-
image_urls = await upload_artifacts_to_fal(inputs.image_urls, context)
|
|
87
|
-
|
|
88
|
-
# Prepare arguments for fal.ai API
|
|
89
|
-
arguments = {
|
|
90
|
-
"prompt": inputs.prompt,
|
|
91
|
-
"image_urls": image_urls,
|
|
92
|
-
"num_images": inputs.num_images,
|
|
93
|
-
"image_size": inputs.image_size,
|
|
94
|
-
"input_fidelity": inputs.input_fidelity,
|
|
95
|
-
"quality": inputs.quality,
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
# Submit async job
|
|
99
|
-
handler = await fal_client.submit_async(
|
|
100
|
-
"fal-ai/gpt-image-1/edit-image",
|
|
101
|
-
arguments=arguments,
|
|
102
|
-
)
|
|
103
|
-
|
|
104
|
-
# Store external job ID
|
|
105
|
-
await context.set_external_job_id(handler.request_id)
|
|
106
|
-
|
|
107
|
-
# Stream progress updates
|
|
108
|
-
from .....progress.models import ProgressUpdate
|
|
109
|
-
|
|
110
|
-
event_count = 0
|
|
111
|
-
async for event in handler.iter_events(with_logs=True):
|
|
112
|
-
event_count += 1
|
|
113
|
-
# Sample every 3rd event to avoid spam
|
|
114
|
-
if event_count % 3 == 0:
|
|
115
|
-
logs = getattr(event, "logs", None)
|
|
116
|
-
if logs:
|
|
117
|
-
# Join log entries into a single message
|
|
118
|
-
if isinstance(logs, list):
|
|
119
|
-
message = " | ".join(str(log) for log in logs if log)
|
|
120
|
-
else:
|
|
121
|
-
message = str(logs)
|
|
122
|
-
|
|
123
|
-
if message:
|
|
124
|
-
await context.publish_progress(
|
|
125
|
-
ProgressUpdate(
|
|
126
|
-
job_id=handler.request_id,
|
|
127
|
-
status="processing",
|
|
128
|
-
progress=50.0,
|
|
129
|
-
phase="processing",
|
|
130
|
-
message=message,
|
|
131
|
-
)
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
# Get final result
|
|
135
|
-
result = await handler.get()
|
|
136
|
-
|
|
137
|
-
# Extract images from result
|
|
138
|
-
# Response structure: {"images": [{"url": "...", "width": 1024, "height": 1024, ...}, ...]}
|
|
139
|
-
images = result.get("images", [])
|
|
140
|
-
|
|
141
|
-
if not images:
|
|
142
|
-
raise ValueError("No images returned from fal.ai API")
|
|
143
|
-
|
|
144
|
-
# Store each image using output_index
|
|
145
|
-
artifacts = []
|
|
146
|
-
for idx, image_data in enumerate(images):
|
|
147
|
-
image_url = image_data.get("url")
|
|
148
|
-
width = image_data.get("width", 1024)
|
|
149
|
-
height = image_data.get("height", 1024)
|
|
150
|
-
|
|
151
|
-
if not image_url:
|
|
152
|
-
raise ValueError(f"Image {idx} missing URL in fal.ai response")
|
|
153
|
-
|
|
154
|
-
# Determine format from image_size or content_type
|
|
155
|
-
format = "png" # GPT-Image-1 typically returns PNG
|
|
156
|
-
if "content_type" in image_data:
|
|
157
|
-
content_type = image_data["content_type"]
|
|
158
|
-
if "jpeg" in content_type:
|
|
159
|
-
format = "jpeg"
|
|
160
|
-
elif "webp" in content_type:
|
|
161
|
-
format = "webp"
|
|
162
|
-
|
|
163
|
-
artifact = await context.store_image_result(
|
|
164
|
-
storage_url=image_url,
|
|
165
|
-
format=format,
|
|
166
|
-
width=width,
|
|
167
|
-
height=height,
|
|
168
|
-
output_index=idx,
|
|
169
|
-
)
|
|
170
|
-
artifacts.append(artifact)
|
|
171
|
-
|
|
172
|
-
return GeneratorResult(outputs=artifacts)
|
|
173
|
-
|
|
174
|
-
async def estimate_cost(self, inputs: GptImage1EditImageInput) -> float:
|
|
175
|
-
"""Estimate cost for GPT-Image-1 edit generation.
|
|
176
|
-
|
|
177
|
-
Note: Pricing information not available in documentation.
|
|
178
|
-
Using estimated cost based on similar OpenAI image models.
|
|
179
|
-
"""
|
|
180
|
-
# Estimated cost per image (similar to other image editing models)
|
|
181
|
-
per_image_cost = 0.04
|
|
182
|
-
return per_image_cost * inputs.num_images
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
fal.ai GPT Image 1 Mini text-to-image generator.
|
|
3
|
-
|
|
4
|
-
Generate images using OpenAI's GPT-5 language capabilities combined with GPT Image 1 Mini
|
|
5
|
-
for efficient image generation.
|
|
6
|
-
|
|
7
|
-
Based on Fal AI's fal-ai/gpt-image-1-mini model.
|
|
8
|
-
See: https://fal.ai/models/fal-ai/gpt-image-1-mini
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import os
|
|
12
|
-
from typing import Literal
|
|
13
|
-
|
|
14
|
-
from pydantic import BaseModel, Field
|
|
15
|
-
|
|
16
|
-
from ....base import BaseGenerator, GeneratorExecutionContext, GeneratorResult
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
class GptImage1MiniInput(BaseModel):
|
|
20
|
-
"""Input schema for GPT Image 1 Mini.
|
|
21
|
-
|
|
22
|
-
Artifact fields are automatically detected via type introspection
|
|
23
|
-
and resolved from generation IDs to artifact objects.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
prompt: str = Field(
|
|
27
|
-
description="Image generation instruction",
|
|
28
|
-
min_length=3,
|
|
29
|
-
max_length=5000,
|
|
30
|
-
)
|
|
31
|
-
num_images: int = Field(
|
|
32
|
-
default=1,
|
|
33
|
-
ge=1,
|
|
34
|
-
le=4,
|
|
35
|
-
description="Number of images to generate",
|
|
36
|
-
)
|
|
37
|
-
output_format: Literal["jpeg", "png", "webp"] = Field(
|
|
38
|
-
default="jpeg",
|
|
39
|
-
description="Output image format",
|
|
40
|
-
)
|
|
41
|
-
sync_mode: bool = Field(
|
|
42
|
-
default=False,
|
|
43
|
-
description=(
|
|
44
|
-
"If True, the media will be returned as a data URI and the output "
|
|
45
|
-
"data won't be available in the request history"
|
|
46
|
-
),
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
class FalGptImage1MiniGenerator(BaseGenerator):
|
|
51
|
-
"""GPT Image 1 Mini text-to-image generator using fal.ai."""
|
|
52
|
-
|
|
53
|
-
name = "fal-gpt-image-1-mini"
|
|
54
|
-
artifact_type = "image"
|
|
55
|
-
description = "Fal: GPT Image 1 Mini - Efficient text-to-image generation with GPT-5"
|
|
56
|
-
|
|
57
|
-
def get_input_schema(self) -> type[GptImage1MiniInput]:
|
|
58
|
-
return GptImage1MiniInput
|
|
59
|
-
|
|
60
|
-
async def generate(
|
|
61
|
-
self, inputs: GptImage1MiniInput, context: GeneratorExecutionContext
|
|
62
|
-
) -> GeneratorResult:
|
|
63
|
-
"""Generate images using fal.ai gpt-image-1-mini model."""
|
|
64
|
-
# Check for API key (fal-client uses FAL_KEY environment variable)
|
|
65
|
-
if not os.getenv("FAL_KEY"):
|
|
66
|
-
raise ValueError("API configuration invalid. Missing FAL_KEY environment variable")
|
|
67
|
-
|
|
68
|
-
# Import fal_client
|
|
69
|
-
try:
|
|
70
|
-
import fal_client
|
|
71
|
-
except ImportError as e:
|
|
72
|
-
raise ImportError(
|
|
73
|
-
"fal.ai SDK is required for FalGptImage1MiniGenerator. "
|
|
74
|
-
"Install with: pip install weirdfingers-boards[generators-fal]"
|
|
75
|
-
) from e
|
|
76
|
-
|
|
77
|
-
# Prepare arguments for fal.ai API
|
|
78
|
-
arguments = {
|
|
79
|
-
"prompt": inputs.prompt,
|
|
80
|
-
"num_images": inputs.num_images,
|
|
81
|
-
"output_format": inputs.output_format,
|
|
82
|
-
"sync_mode": inputs.sync_mode,
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
# Submit async job and get handler
|
|
86
|
-
handler = await fal_client.submit_async(
|
|
87
|
-
"fal-ai/gpt-image-1-mini",
|
|
88
|
-
arguments=arguments,
|
|
89
|
-
)
|
|
90
|
-
|
|
91
|
-
# Store the external job ID for tracking
|
|
92
|
-
await context.set_external_job_id(handler.request_id)
|
|
93
|
-
|
|
94
|
-
# Stream progress updates (sample every 3rd event to avoid spam)
|
|
95
|
-
from .....progress.models import ProgressUpdate
|
|
96
|
-
|
|
97
|
-
event_count = 0
|
|
98
|
-
async for event in handler.iter_events(with_logs=True):
|
|
99
|
-
event_count += 1
|
|
100
|
-
|
|
101
|
-
# Process every 3rd event to provide feedback without overwhelming
|
|
102
|
-
if event_count % 3 == 0:
|
|
103
|
-
# Extract logs if available
|
|
104
|
-
logs = getattr(event, "logs", None)
|
|
105
|
-
if logs:
|
|
106
|
-
# Join log entries into a single message
|
|
107
|
-
if isinstance(logs, list):
|
|
108
|
-
message = " | ".join(str(log) for log in logs if log)
|
|
109
|
-
else:
|
|
110
|
-
message = str(logs)
|
|
111
|
-
|
|
112
|
-
if message:
|
|
113
|
-
await context.publish_progress(
|
|
114
|
-
ProgressUpdate(
|
|
115
|
-
job_id=handler.request_id,
|
|
116
|
-
status="processing",
|
|
117
|
-
progress=50.0, # Approximate mid-point progress
|
|
118
|
-
phase="processing",
|
|
119
|
-
message=message,
|
|
120
|
-
)
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
# Get final result
|
|
124
|
-
result = await handler.get()
|
|
125
|
-
|
|
126
|
-
# Extract image URLs and description from result
|
|
127
|
-
# fal.ai returns: {
|
|
128
|
-
# "images": [{"url": "...", "content_type": "...", ...}, ...],
|
|
129
|
-
# "description": "Text description"
|
|
130
|
-
# }
|
|
131
|
-
images = result.get("images", [])
|
|
132
|
-
|
|
133
|
-
if not images:
|
|
134
|
-
raise ValueError("No images returned from fal.ai API")
|
|
135
|
-
|
|
136
|
-
# Store each image using output_index
|
|
137
|
-
artifacts = []
|
|
138
|
-
for idx, image_data in enumerate(images):
|
|
139
|
-
image_url = image_data.get("url")
|
|
140
|
-
# Extract dimensions if available, otherwise use sensible defaults
|
|
141
|
-
# Use 'or' to handle explicit None values from API
|
|
142
|
-
width = image_data.get("width") or 1024
|
|
143
|
-
height = image_data.get("height") or 1024
|
|
144
|
-
|
|
145
|
-
if not image_url:
|
|
146
|
-
raise ValueError(f"Image {idx} missing URL in fal.ai response")
|
|
147
|
-
|
|
148
|
-
# Store with appropriate output_index
|
|
149
|
-
artifact = await context.store_image_result(
|
|
150
|
-
storage_url=image_url,
|
|
151
|
-
format=inputs.output_format,
|
|
152
|
-
width=width,
|
|
153
|
-
height=height,
|
|
154
|
-
output_index=idx,
|
|
155
|
-
)
|
|
156
|
-
artifacts.append(artifact)
|
|
157
|
-
|
|
158
|
-
return GeneratorResult(outputs=artifacts)
|
|
159
|
-
|
|
160
|
-
async def estimate_cost(self, inputs: GptImage1MiniInput) -> float:
|
|
161
|
-
"""Estimate cost for GPT Image 1 Mini generation.
|
|
162
|
-
|
|
163
|
-
Using estimated cost per image (pricing not documented).
|
|
164
|
-
"""
|
|
165
|
-
# Estimated cost per image
|
|
166
|
-
per_image_cost = 0.01
|
|
167
|
-
return per_image_cost * inputs.num_images
|