Skip to content

Commit 162eb87

Browse files
authored
fal plugin
Co-authored-by: Chris Tate <ctate@users.noreply.github.com>
1 parent a0f58e9 commit 162eb87

File tree

11 files changed

+859
-1
lines changed

11 files changed

+859
-1
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ Visit [http://localhost:3000](http://localhost:3000) to get started.
8181
<!-- PLUGINS:START - Do not remove. Auto-generated by discover-plugins -->
8282
- **AI Gateway**: Generate Text, Generate Image
8383
- **Blob**: Put Blob, List Blobs
84+
- **fal.ai**: Generate Image, Generate Video, Upscale Image, Remove Background, Image to Image
8485
- **Firecrawl**: Scrape URL, Search Web
8586
- **GitHub**: Create Issue, List Issues, Get Issue, Update Issue
8687
- **Linear**: Create Ticket, Find Issues

plugins/fal/credentials.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type FalCredentials = {
2+
FAL_API_KEY?: string;
3+
};

plugins/fal/icon.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export function FalIcon({ className }: { className?: string }) {
2+
return (
3+
<svg
4+
aria-label="fal.ai logo"
5+
className={className}
6+
fill="currentColor"
7+
viewBox="0 0 24 24"
8+
xmlns="http://www.w3.org/2000/svg"
9+
>
10+
<title>fal.ai</title>
11+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 15.5v-2.54c-2.24-.59-4-2.57-4-4.96 0-.34.03-.67.09-1h1.99c-.05.33-.08.66-.08 1 0 1.93 1.57 3.5 3.5 3.5h.5v2.54c-1.04-.13-2-.41-2.86-.81zm3-5.5c0-1.93-1.57-3.5-3.5-3.5H10V6c1.04.13 2 .41 2.86.81L13 5.5v2.54c2.24.59 4 2.57 4 4.96 0 .34-.03.67-.09 1h-1.99c.05-.33.08-.66.08-1z" />
12+
</svg>
13+
);
14+
}

plugins/fal/index.ts

Lines changed: 270 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,270 @@
1+
import type { IntegrationPlugin } from "../registry";
2+
import { registerIntegration } from "../registry";
3+
import { FalIcon } from "./icon";
4+
5+
const falPlugin: IntegrationPlugin = {
6+
type: "fal",
7+
label: "fal.ai",
8+
description: "Fast AI inference for image, video, and audio generation",
9+
10+
icon: FalIcon,
11+
12+
formFields: [
13+
{
14+
id: "falApiKey",
15+
label: "API Key",
16+
type: "password",
17+
placeholder: "fal_...",
18+
configKey: "apiKey",
19+
envVar: "FAL_API_KEY",
20+
helpText: "Get your API key from ",
21+
helpLink: {
22+
text: "fal.ai/dashboard/keys",
23+
url: "https://fal.ai/dashboard/keys",
24+
},
25+
},
26+
],
27+
28+
testConfig: {
29+
getTestFunction: async () => {
30+
const { testFal } = await import("./test");
31+
return testFal;
32+
},
33+
},
34+
35+
actions: [
36+
{
37+
slug: "generate-image",
38+
label: "Generate Image",
39+
description: "Generate images using Flux models",
40+
category: "fal.ai",
41+
stepFunction: "falGenerateImageStep",
42+
stepImportPath: "generate-image",
43+
outputFields: [
44+
{ field: "imageUrl", description: "URL of the generated image" },
45+
{ field: "width", description: "Width of the generated image" },
46+
{ field: "height", description: "Height of the generated image" },
47+
],
48+
configFields: [
49+
{
50+
key: "model",
51+
label: "Model",
52+
type: "select",
53+
defaultValue: "fal-ai/flux/schnell",
54+
options: [
55+
{ value: "fal-ai/flux/schnell", label: "Flux Schnell (Fast)" },
56+
{ value: "fal-ai/flux/dev", label: "Flux Dev (Quality)" },
57+
{ value: "fal-ai/flux-pro/v1.1", label: "Flux Pro 1.1" },
58+
{ value: "fal-ai/flux-pro/v1.1-ultra", label: "Flux Pro 1.1 Ultra" },
59+
{ value: "fal-ai/flux-lora", label: "Flux LoRA" },
60+
{
61+
value: "fal-ai/stable-diffusion-v3-medium",
62+
label: "Stable Diffusion 3 Medium",
63+
},
64+
{ value: "fal-ai/recraft-v3", label: "Recraft V3" },
65+
],
66+
},
67+
{
68+
key: "prompt",
69+
label: "Prompt",
70+
type: "template-textarea",
71+
placeholder:
72+
"Describe the image you want to generate. Use {{NodeName.field}} to reference previous outputs.",
73+
rows: 4,
74+
example: "A serene mountain landscape at sunset with dramatic clouds",
75+
required: true,
76+
},
77+
{
78+
key: "imageSize",
79+
label: "Image Size",
80+
type: "select",
81+
defaultValue: "landscape_16_9",
82+
options: [
83+
{ value: "square", label: "Square (1024x1024)" },
84+
{ value: "square_hd", label: "Square HD (1536x1536)" },
85+
{ value: "portrait_4_3", label: "Portrait 4:3" },
86+
{ value: "portrait_16_9", label: "Portrait 16:9" },
87+
{ value: "landscape_4_3", label: "Landscape 4:3" },
88+
{ value: "landscape_16_9", label: "Landscape 16:9" },
89+
],
90+
},
91+
{
92+
key: "numImages",
93+
label: "Number of Images",
94+
type: "number",
95+
placeholder: "1",
96+
min: 1,
97+
defaultValue: "1",
98+
},
99+
],
100+
},
101+
{
102+
slug: "generate-video",
103+
label: "Generate Video",
104+
description: "Generate videos from text or images",
105+
category: "fal.ai",
106+
stepFunction: "falGenerateVideoStep",
107+
stepImportPath: "generate-video",
108+
outputFields: [
109+
{ field: "videoUrl", description: "URL of the generated video" },
110+
],
111+
configFields: [
112+
{
113+
key: "model",
114+
label: "Model",
115+
type: "select",
116+
defaultValue: "fal-ai/minimax-video",
117+
options: [
118+
{ value: "fal-ai/minimax-video", label: "MiniMax Video" },
119+
{ value: "fal-ai/kling-video/v1/standard/text-to-video", label: "Kling 1.0" },
120+
{ value: "fal-ai/kling-video/v1.5/pro/text-to-video", label: "Kling 1.5 Pro" },
121+
{ value: "fal-ai/hunyuan-video", label: "Hunyuan Video" },
122+
{ value: "fal-ai/luma-dream-machine", label: "Luma Dream Machine" },
123+
{ value: "fal-ai/runway-gen3/turbo/image-to-video", label: "Runway Gen3 (Image to Video)" },
124+
],
125+
},
126+
{
127+
key: "prompt",
128+
label: "Prompt",
129+
type: "template-textarea",
130+
placeholder:
131+
"Describe the video you want to generate. Use {{NodeName.field}} to reference previous outputs.",
132+
rows: 4,
133+
example: "A cat walking through a garden",
134+
required: true,
135+
},
136+
{
137+
key: "imageUrl",
138+
label: "Image URL (Optional)",
139+
type: "template-input",
140+
placeholder: "URL of image to animate (for image-to-video models)",
141+
},
142+
],
143+
},
144+
{
145+
slug: "upscale-image",
146+
label: "Upscale Image",
147+
description: "Upscale images to higher resolution",
148+
category: "fal.ai",
149+
stepFunction: "falUpscaleImageStep",
150+
stepImportPath: "upscale-image",
151+
outputFields: [
152+
{ field: "imageUrl", description: "URL of the upscaled image" },
153+
{ field: "width", description: "Width of the upscaled image" },
154+
{ field: "height", description: "Height of the upscaled image" },
155+
],
156+
configFields: [
157+
{
158+
key: "model",
159+
label: "Model",
160+
type: "select",
161+
defaultValue: "fal-ai/creative-upscaler",
162+
options: [
163+
{ value: "fal-ai/creative-upscaler", label: "Creative Upscaler" },
164+
{ value: "fal-ai/clarity-upscaler", label: "Clarity Upscaler" },
165+
{ value: "fal-ai/real-esrgan", label: "Real-ESRGAN" },
166+
],
167+
},
168+
{
169+
key: "imageUrl",
170+
label: "Image URL",
171+
type: "template-input",
172+
placeholder: "URL of image to upscale or {{NodeName.imageUrl}}",
173+
example: "https://example.com/image.jpg",
174+
required: true,
175+
},
176+
{
177+
key: "scale",
178+
label: "Scale Factor",
179+
type: "select",
180+
defaultValue: "2",
181+
options: [
182+
{ value: "2", label: "2x" },
183+
{ value: "4", label: "4x" },
184+
],
185+
},
186+
],
187+
},
188+
{
189+
slug: "remove-background",
190+
label: "Remove Background",
191+
description: "Remove background from images",
192+
category: "fal.ai",
193+
stepFunction: "falRemoveBackgroundStep",
194+
stepImportPath: "remove-background",
195+
outputFields: [
196+
{ field: "imageUrl", description: "URL of the image with background removed" },
197+
],
198+
configFields: [
199+
{
200+
key: "imageUrl",
201+
label: "Image URL",
202+
type: "template-input",
203+
placeholder: "URL of image or {{NodeName.imageUrl}}",
204+
example: "https://example.com/image.jpg",
205+
required: true,
206+
},
207+
],
208+
},
209+
{
210+
slug: "image-to-image",
211+
label: "Image to Image",
212+
description: "Transform images with text prompts",
213+
category: "fal.ai",
214+
stepFunction: "falImageToImageStep",
215+
stepImportPath: "image-to-image",
216+
outputFields: [
217+
{ field: "imageUrl", description: "URL of the transformed image" },
218+
{ field: "width", description: "Width of the generated image" },
219+
{ field: "height", description: "Height of the generated image" },
220+
],
221+
configFields: [
222+
{
223+
key: "model",
224+
label: "Model",
225+
type: "select",
226+
defaultValue: "fal-ai/flux/dev/image-to-image",
227+
options: [
228+
{ value: "fal-ai/flux/dev/image-to-image", label: "Flux Dev Image-to-Image" },
229+
{ value: "fal-ai/flux-pro/v1/redux", label: "Flux Pro Redux" },
230+
],
231+
},
232+
{
233+
key: "imageUrl",
234+
label: "Image URL",
235+
type: "template-input",
236+
placeholder: "URL of source image or {{NodeName.imageUrl}}",
237+
example: "https://example.com/image.jpg",
238+
required: true,
239+
},
240+
{
241+
key: "prompt",
242+
label: "Prompt",
243+
type: "template-textarea",
244+
placeholder:
245+
"Describe how to transform the image. Use {{NodeName.field}} to reference previous outputs.",
246+
rows: 4,
247+
example: "Transform into a watercolor painting style",
248+
required: true,
249+
},
250+
{
251+
key: "strength",
252+
label: "Strength",
253+
type: "select",
254+
defaultValue: "0.75",
255+
options: [
256+
{ value: "0.25", label: "Subtle (0.25)" },
257+
{ value: "0.5", label: "Moderate (0.5)" },
258+
{ value: "0.75", label: "Strong (0.75)" },
259+
{ value: "0.9", label: "Very Strong (0.9)" },
260+
],
261+
},
262+
],
263+
},
264+
],
265+
};
266+
267+
// Auto-register on import
268+
registerIntegration(falPlugin);
269+
270+
export default falPlugin;

0 commit comments

Comments
 (0)