@ai-sdk/black-forest-labs 2.0.0-beta.5 → 2.0.0-beta.52

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.
@@ -0,0 +1,51 @@
1
+ import {
2
+ lazySchema,
3
+ zodSchema,
4
+ type InferSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod/v4';
7
+
8
+ export const blackForestLabsImageModelOptionsSchema = lazySchema(() =>
9
+ zodSchema(
10
+ z.object({
11
+ imagePrompt: z.string().optional(),
12
+ imagePromptStrength: z.number().min(0).max(1).optional(),
13
+ /** @deprecated use prompt.images instead */
14
+ inputImage: z.string().optional(),
15
+ /** @deprecated use prompt.images instead */
16
+ inputImage2: z.string().optional(),
17
+ /** @deprecated use prompt.images instead */
18
+ inputImage3: z.string().optional(),
19
+ /** @deprecated use prompt.images instead */
20
+ inputImage4: z.string().optional(),
21
+ /** @deprecated use prompt.images instead */
22
+ inputImage5: z.string().optional(),
23
+ /** @deprecated use prompt.images instead */
24
+ inputImage6: z.string().optional(),
25
+ /** @deprecated use prompt.images instead */
26
+ inputImage7: z.string().optional(),
27
+ /** @deprecated use prompt.images instead */
28
+ inputImage8: z.string().optional(),
29
+ /** @deprecated use prompt.images instead */
30
+ inputImage9: z.string().optional(),
31
+ /** @deprecated use prompt.images instead */
32
+ inputImage10: z.string().optional(),
33
+ steps: z.number().int().positive().optional(),
34
+ guidance: z.number().min(0).optional(),
35
+ width: z.number().int().min(256).max(1920).optional(),
36
+ height: z.number().int().min(256).max(1920).optional(),
37
+ outputFormat: z.enum(['jpeg', 'png']).optional(),
38
+ promptUpsampling: z.boolean().optional(),
39
+ raw: z.boolean().optional(),
40
+ safetyTolerance: z.number().int().min(0).max(6).optional(),
41
+ webhookSecret: z.string().optional(),
42
+ webhookUrl: z.url().optional(),
43
+ pollIntervalMillis: z.number().int().positive().optional(),
44
+ pollTimeoutMillis: z.number().int().positive().optional(),
45
+ }),
46
+ ),
47
+ );
48
+
49
+ export type BlackForestLabsImageModelOptions = InferSchema<
50
+ typeof blackForestLabsImageModelOptionsSchema
51
+ >;
@@ -1,7 +1,5 @@
1
1
  import type { ImageModelV4, SharedV4Warning } from '@ai-sdk/provider';
2
- import type { InferSchema, Resolvable } from '@ai-sdk/provider-utils';
3
2
  import {
4
- FetchFunction,
5
3
  combineHeaders,
6
4
  createBinaryResponseHandler,
7
5
  createJsonErrorResponseHandler,
@@ -9,15 +7,22 @@ import {
9
7
  createStatusCodeErrorResponseHandler,
10
8
  delay,
11
9
  getFromApi,
12
- lazySchema,
10
+ isSameOrigin,
13
11
  parseProviderOptions,
14
12
  postJsonToApi,
15
13
  resolve,
16
- zodSchema,
14
+ serializeModelOptions,
15
+ WORKFLOW_SERIALIZE,
16
+ WORKFLOW_DESERIALIZE,
17
+ type Resolvable,
18
+ type FetchFunction,
17
19
  } from '@ai-sdk/provider-utils';
18
20
  import { z } from 'zod/v4';
19
- import type { BlackForestLabsAspectRatio } from './black-forest-labs-image-settings';
20
- import { BlackForestLabsImageModelId } from './black-forest-labs-image-settings';
21
+ import { blackForestLabsImageModelOptionsSchema } from './black-forest-labs-image-model-options';
22
+ import type {
23
+ BlackForestLabsAspectRatio,
24
+ BlackForestLabsImageModelId,
25
+ } from './black-forest-labs-image-settings';
21
26
 
22
27
  const DEFAULT_POLL_INTERVAL_MILLIS = 500;
23
28
  const DEFAULT_POLL_TIMEOUT_MILLIS = 60000;
@@ -48,6 +53,20 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
48
53
  return this.config.provider;
49
54
  }
50
55
 
56
+ static [WORKFLOW_SERIALIZE](model: BlackForestLabsImageModel) {
57
+ return serializeModelOptions({
58
+ modelId: model.modelId,
59
+ config: model.config,
60
+ });
61
+ }
62
+
63
+ static [WORKFLOW_DESERIALIZE](options: {
64
+ modelId: BlackForestLabsImageModelId;
65
+ config: BlackForestLabsImageModelConfig;
66
+ }) {
67
+ return new BlackForestLabsImageModel(options.modelId, options.config);
68
+ }
69
+
51
70
  constructor(
52
71
  readonly modelId: BlackForestLabsImageModelId,
53
72
  private readonly config: BlackForestLabsImageModelConfig,
@@ -108,10 +127,12 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
108
127
  throw new Error('Black Forest Labs supports up to 10 input images.');
109
128
  }
110
129
 
130
+ const inputImageField =
131
+ this.modelId === 'flux-pro-1.0-fill' ? 'image' : 'input_image';
111
132
  const inputImagesObj: Record<string, string> = inputImages.reduce<
112
133
  Record<string, string>
113
134
  >((acc, img, index) => {
114
- acc[`input_image${index === 0 ? '' : `_${index + 1}`}`] = img;
135
+ acc[`${inputImageField}${index === 0 ? '' : `_${index + 1}`}`] = img;
115
136
  return acc;
116
137
  }, {});
117
138
 
@@ -148,7 +169,7 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
148
169
  webhook_url: bflOptions?.webhookUrl,
149
170
  };
150
171
 
151
- return { body, warnings };
172
+ return { body, warnings, bflOptions };
152
173
  }
153
174
 
154
175
  async doGenerate({
@@ -164,7 +185,7 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
164
185
  }: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
165
186
  Awaited<ReturnType<ImageModelV4['doGenerate']>>
166
187
  > {
167
- const { body, warnings } = await this.getArgs({
188
+ const { body, warnings, bflOptions } = await this.getArgs({
168
189
  prompt,
169
190
  files,
170
191
  mask,
@@ -177,12 +198,6 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
177
198
  abortSignal,
178
199
  } as Parameters<ImageModelV4['doGenerate']>[0]);
179
200
 
180
- const bflOptions = await parseProviderOptions({
181
- provider: 'blackForestLabs',
182
- providerOptions,
183
- schema: blackForestLabsImageModelOptionsSchema,
184
- });
185
-
186
201
  const currentDate = this.config._internal?.currentDate?.() ?? new Date();
187
202
  const combinedHeaders = combineHeaders(
188
203
  await resolve(this.config.headers),
@@ -221,7 +236,12 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
221
236
 
222
237
  const { value: imageBytes, responseHeaders } = await getFromApi({
223
238
  url: imageUrl,
224
- headers: combinedHeaders,
239
+ // Only send credentials if the response-supplied URL points back at the
240
+ // provider; the image is typically delivered from a CDN, so the API key
241
+ // must not travel to a foreign host.
242
+ headers: isTrustedUrl(imageUrl, this.config.baseURL)
243
+ ? combinedHeaders
244
+ : undefined,
225
245
  abortSignal,
226
246
  failedResponseHandler: createStatusCodeErrorResponseHandler(),
227
247
  successfulResponseHandler: createBinaryResponseHandler(),
@@ -300,7 +320,11 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
300
320
  for (let i = 0; i < maxPollAttempts; i++) {
301
321
  const { value } = await getFromApi({
302
322
  url: url.toString(),
303
- headers,
323
+ // The polling URL comes from the provider response; only send
324
+ // credentials when it stays on a trusted provider host.
325
+ headers: isTrustedUrl(url.toString(), this.config.baseURL)
326
+ ? headers
327
+ : undefined,
304
328
  failedResponseHandler: bflFailedResponseHandler,
305
329
  successfulResponseHandler: createJsonResponseHandler(bflPollSchema),
306
330
  abortSignal,
@@ -333,50 +357,28 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
333
357
  }
334
358
  }
335
359
 
336
- export const blackForestLabsImageModelOptionsSchema = lazySchema(() =>
337
- zodSchema(
338
- z.object({
339
- imagePrompt: z.string().optional(),
340
- imagePromptStrength: z.number().min(0).max(1).optional(),
341
- /** @deprecated use prompt.images instead */
342
- inputImage: z.string().optional(),
343
- /** @deprecated use prompt.images instead */
344
- inputImage2: z.string().optional(),
345
- /** @deprecated use prompt.images instead */
346
- inputImage3: z.string().optional(),
347
- /** @deprecated use prompt.images instead */
348
- inputImage4: z.string().optional(),
349
- /** @deprecated use prompt.images instead */
350
- inputImage5: z.string().optional(),
351
- /** @deprecated use prompt.images instead */
352
- inputImage6: z.string().optional(),
353
- /** @deprecated use prompt.images instead */
354
- inputImage7: z.string().optional(),
355
- /** @deprecated use prompt.images instead */
356
- inputImage8: z.string().optional(),
357
- /** @deprecated use prompt.images instead */
358
- inputImage9: z.string().optional(),
359
- /** @deprecated use prompt.images instead */
360
- inputImage10: z.string().optional(),
361
- steps: z.number().int().positive().optional(),
362
- guidance: z.number().min(0).optional(),
363
- width: z.number().int().min(256).max(1920).optional(),
364
- height: z.number().int().min(256).max(1920).optional(),
365
- outputFormat: z.enum(['jpeg', 'png']).optional(),
366
- promptUpsampling: z.boolean().optional(),
367
- raw: z.boolean().optional(),
368
- safetyTolerance: z.number().int().min(0).max(6).optional(),
369
- webhookSecret: z.string().optional(),
370
- webhookUrl: z.url().optional(),
371
- pollIntervalMillis: z.number().int().positive().optional(),
372
- pollTimeoutMillis: z.number().int().positive().optional(),
373
- }),
374
- ),
375
- );
376
-
377
- export type BlackForestLabsImageModelOptions = InferSchema<
378
- typeof blackForestLabsImageModelOptionsSchema
379
- >;
360
+ /**
361
+ * Black Forest Labs returns response-supplied URLs (polling and delivery) on
362
+ * sibling cluster hosts of the API origin (e.g. `api.us1.bfl.ai` for a base
363
+ * URL on `api.bfl.ai`), so a strict same-origin check against the configured
364
+ * base URL is not enough. Credentials may also be sent to any https host under
365
+ * the official `bfl.ai` domain.
366
+ */
367
+ function isTrustedUrl(url: string, baseUrl: string): boolean {
368
+ if (isSameOrigin(url, baseUrl)) {
369
+ return true;
370
+ }
371
+
372
+ try {
373
+ const { protocol, hostname } = new URL(url);
374
+ return (
375
+ protocol === 'https:' &&
376
+ (hostname === 'bfl.ai' || hostname.endsWith('.bfl.ai'))
377
+ );
378
+ } catch {
379
+ return false;
380
+ }
381
+ }
380
382
 
381
383
  function convertSizeToAspectRatio(
382
384
  size: string,
@@ -1,12 +1,16 @@
1
- import { ImageModelV4, NoSuchModelError, ProviderV4 } from '@ai-sdk/provider';
2
- import type { FetchFunction } from '@ai-sdk/provider-utils';
1
+ import {
2
+ NoSuchModelError,
3
+ type ImageModelV4,
4
+ type ProviderV4,
5
+ } from '@ai-sdk/provider';
3
6
  import {
4
7
  loadApiKey,
5
8
  withoutTrailingSlash,
6
9
  withUserAgentSuffix,
10
+ type FetchFunction,
7
11
  } from '@ai-sdk/provider-utils';
8
12
  import { BlackForestLabsImageModel } from './black-forest-labs-image-model';
9
- import { BlackForestLabsImageModelId } from './black-forest-labs-image-settings';
13
+ import type { BlackForestLabsImageModelId } from './black-forest-labs-image-settings';
10
14
  import { VERSION } from './version';
11
15
 
12
16
  export interface BlackForestLabsProviderSettings {
package/src/index.ts CHANGED
@@ -14,5 +14,5 @@ export type {
14
14
  BlackForestLabsImageModelOptions,
15
15
  /** @deprecated Use `BlackForestLabsImageModelOptions` instead. */
16
16
  BlackForestLabsImageModelOptions as BlackForestLabsImageProviderOptions,
17
- } from './black-forest-labs-image-model';
17
+ } from './black-forest-labs-image-model-options';
18
18
  export { VERSION } from './version';
package/dist/index.d.mts DELETED
@@ -1,82 +0,0 @@
1
- import { ProviderV4, ImageModelV4 } from '@ai-sdk/provider';
2
- import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
3
- import { FetchFunction, InferSchema } from '@ai-sdk/provider-utils';
4
-
5
- type BlackForestLabsImageModelId = 'flux-kontext-pro' | 'flux-kontext-max' | 'flux-pro-1.1-ultra' | 'flux-pro-1.1' | 'flux-pro-1.0-fill' | (string & {});
6
- type BlackForestLabsAspectRatio = `${number}:${number}`;
7
-
8
- interface BlackForestLabsProviderSettings {
9
- /**
10
- * Black Forest Labs API key. Default value is taken from the `BFL_API_KEY` environment variable.
11
- */
12
- apiKey?: string;
13
- /**
14
- * Base URL for the API calls. Defaults to `https://api.bfl.ai/v1`.
15
- */
16
- baseURL?: string;
17
- /**
18
- * Custom headers to include in the requests.
19
- */
20
- headers?: Record<string, string>;
21
- /**
22
- * Custom fetch implementation. You can use it as a middleware to intercept
23
- * requests, or to provide a custom fetch implementation for e.g. testing.
24
- */
25
- fetch?: FetchFunction;
26
- /**
27
- * Poll interval in milliseconds between status checks. Defaults to 500ms.
28
- */
29
- pollIntervalMillis?: number;
30
- /**
31
- * Overall timeout in milliseconds for polling before giving up. Defaults to 60s.
32
- */
33
- pollTimeoutMillis?: number;
34
- }
35
- interface BlackForestLabsProvider extends ProviderV4 {
36
- /**
37
- * Creates a model for image generation.
38
- */
39
- image(modelId: BlackForestLabsImageModelId): ImageModelV4;
40
- /**
41
- * Creates a model for image generation.
42
- */
43
- imageModel(modelId: BlackForestLabsImageModelId): ImageModelV4;
44
- /**
45
- * @deprecated Use `embeddingModel` instead.
46
- */
47
- textEmbeddingModel(modelId: string): never;
48
- }
49
- declare function createBlackForestLabs(options?: BlackForestLabsProviderSettings): BlackForestLabsProvider;
50
- declare const blackForestLabs: BlackForestLabsProvider;
51
-
52
- declare const blackForestLabsImageModelOptionsSchema: _ai_sdk_provider_utils.LazySchema<{
53
- imagePrompt?: string | undefined;
54
- imagePromptStrength?: number | undefined;
55
- inputImage?: string | undefined;
56
- inputImage2?: string | undefined;
57
- inputImage3?: string | undefined;
58
- inputImage4?: string | undefined;
59
- inputImage5?: string | undefined;
60
- inputImage6?: string | undefined;
61
- inputImage7?: string | undefined;
62
- inputImage8?: string | undefined;
63
- inputImage9?: string | undefined;
64
- inputImage10?: string | undefined;
65
- steps?: number | undefined;
66
- guidance?: number | undefined;
67
- width?: number | undefined;
68
- height?: number | undefined;
69
- outputFormat?: "jpeg" | "png" | undefined;
70
- promptUpsampling?: boolean | undefined;
71
- raw?: boolean | undefined;
72
- safetyTolerance?: number | undefined;
73
- webhookSecret?: string | undefined;
74
- webhookUrl?: string | undefined;
75
- pollIntervalMillis?: number | undefined;
76
- pollTimeoutMillis?: number | undefined;
77
- }>;
78
- type BlackForestLabsImageModelOptions = InferSchema<typeof blackForestLabsImageModelOptionsSchema>;
79
-
80
- declare const VERSION: string;
81
-
82
- export { type BlackForestLabsAspectRatio, type BlackForestLabsImageModelId, type BlackForestLabsImageModelOptions, type BlackForestLabsImageModelOptions as BlackForestLabsImageProviderOptions, type BlackForestLabsProvider, type BlackForestLabsProviderSettings, VERSION, blackForestLabs, createBlackForestLabs };