@ai-sdk/black-forest-labs 2.0.0-canary.49 → 2.0.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,78 @@
1
1
  # @ai-sdk/black-forest-labs
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - ef992f8: Remove CommonJS exports from all packages. All packages are now ESM-only (`"type": "module"`). Consumers using `require()` must switch to ESM `import` syntax.
8
+ - 8359612: Start v7 pre-release
9
+ - 04e9009: chore: make provider implementations code patterns more consistent, including renaming certain exported symbols
10
+
11
+ For all externally exported symbols that were renamed, the old names continue to work via deprecated aliases.
12
+
13
+ ### Patch Changes
14
+
15
+ - 53f9cbf: fix(bfl): remove duplicate parseProviderOptions call in doGenerate
16
+ - 38fc777: Add AI Gateway hint to provider READMEs
17
+ - 9f0e36c: trigger release for all packages after provenance setup
18
+ - 23b6aca: fix(bfl): use 'image' field instead of 'input_image' for fill pro model
19
+ - aeda373: fix: only send provider credentials to same-origin response-supplied URLs
20
+
21
+ Several provider clients followed a URL taken from the provider's API response (a polling/status URL or a final media URL such as `polling_url`, `urls.get`, `result_url`, `result.sample`, or `video.uri`) and reused the authenticated headers — or appended `?key=<API_KEY>` — on that request. Because the host of the response-supplied URL was never validated, the long-lived API key was sent to whatever host the response named (a CDN in the benign case, or an attacker-chosen host if the provider response was tampered with), allowing credential exfiltration.
22
+
23
+ A new `isSameOrigin` helper is added to `@ai-sdk/provider-utils`, and the affected fetches in `@ai-sdk/black-forest-labs`, `@ai-sdk/fireworks`, `@ai-sdk/replicate`, `@ai-sdk/gladia`, `@ai-sdk/fal`, and `@ai-sdk/google` now attach credentials only when the followed URL is same-origin with the provider's configured API origin. Requests to a foreign origin are made without the credential.
24
+
25
+ - 7fc6bd6: Raise minimum supported Node.js version to 22. Supported versions: 22, 24, and 26.
26
+ - 0c4c275: trigger initial canary release
27
+ - 258c093: chore: ensure consistent import handling and avoid import duplicates or cycles
28
+ - b8396f0: trigger initial beta release
29
+ - b3976a2: Add workflow serialization support to all provider models.
30
+
31
+ **`@ai-sdk/provider-utils`:** New `serializeModel()` helper that extracts only serializable properties from a model instance, filtering out functions and objects containing functions. Third-party provider authors can use this to add workflow support to their own models.
32
+
33
+ **All providers:** `headers` is now optional in provider config types. This is non-breaking — existing code that passes `headers` continues to work. Custom provider implementations that construct model configs manually can now omit `headers`, which is useful when models are deserialized from a workflow step boundary where auth is provided separately.
34
+
35
+ All provider model classes now include `WORKFLOW_SERIALIZE` and `WORKFLOW_DESERIALIZE` static methods, enabling them to cross workflow step boundaries without serialization errors.
36
+
37
+
38
+ ## 2.0.0-beta.53
39
+
40
+ ### Patch Changes
41
+
42
+ - Updated dependencies [0416e3e]
43
+ - @ai-sdk/provider@4.0.0-beta.20
44
+ - @ai-sdk/provider-utils@5.0.0-beta.50
45
+
46
+ ## 2.0.0-beta.52
47
+
48
+ ### Patch Changes
49
+
50
+ - 53f9cbf: fix(bfl): remove duplicate parseProviderOptions call in doGenerate
51
+
52
+ ## 2.0.0-beta.51
53
+
54
+ ### Patch Changes
55
+
56
+ - b8396f0: trigger initial beta release
57
+ - Updated dependencies [b8396f0]
58
+ - @ai-sdk/provider-utils@5.0.0-beta.49
59
+ - @ai-sdk/provider@4.0.0-beta.19
60
+
61
+ ## 2.0.0-canary.50
62
+
63
+ ### Patch Changes
64
+
65
+ - aeda373: fix: only send provider credentials to same-origin response-supplied URLs
66
+
67
+ Several provider clients followed a URL taken from the provider's API response (a polling/status URL or a final media URL such as `polling_url`, `urls.get`, `result_url`, `result.sample`, or `video.uri`) and reused the authenticated headers — or appended `?key=<API_KEY>` — on that request. Because the host of the response-supplied URL was never validated, the long-lived API key was sent to whatever host the response named (a CDN in the benign case, or an attacker-chosen host if the provider response was tampered with), allowing credential exfiltration.
68
+
69
+ A new `isSameOrigin` helper is added to `@ai-sdk/provider-utils`, and the affected fetches in `@ai-sdk/black-forest-labs`, `@ai-sdk/fireworks`, `@ai-sdk/replicate`, `@ai-sdk/gladia`, `@ai-sdk/fal`, and `@ai-sdk/google` now attach credentials only when the followed URL is same-origin with the provider's configured API origin. Requests to a foreign origin are made without the credential.
70
+
71
+ - Updated dependencies [aeda373]
72
+ - Updated dependencies [375fdd7]
73
+ - Updated dependencies [b4507d5]
74
+ - @ai-sdk/provider-utils@5.0.0-canary.48
75
+
3
76
  ## 2.0.0-canary.49
4
77
 
5
78
  ### Patch Changes
package/dist/index.js CHANGED
@@ -17,6 +17,7 @@ import {
17
17
  createStatusCodeErrorResponseHandler,
18
18
  delay,
19
19
  getFromApi,
20
+ isSameOrigin,
20
21
  parseProviderOptions,
21
22
  postJsonToApi,
22
23
  resolve,
@@ -174,7 +175,7 @@ var BlackForestLabsImageModel = class _BlackForestLabsImageModel {
174
175
  webhook_secret: bflOptions == null ? void 0 : bflOptions.webhookSecret,
175
176
  webhook_url: bflOptions == null ? void 0 : bflOptions.webhookUrl
176
177
  };
177
- return { body, warnings };
178
+ return { body, warnings, bflOptions };
178
179
  }
179
180
  async doGenerate({
180
181
  prompt,
@@ -188,7 +189,7 @@ var BlackForestLabsImageModel = class _BlackForestLabsImageModel {
188
189
  abortSignal
189
190
  }) {
190
191
  var _a, _b, _c;
191
- const { body, warnings } = await this.getArgs({
192
+ const { body, warnings, bflOptions } = await this.getArgs({
192
193
  prompt,
193
194
  files,
194
195
  mask,
@@ -200,11 +201,6 @@ var BlackForestLabsImageModel = class _BlackForestLabsImageModel {
200
201
  headers,
201
202
  abortSignal
202
203
  });
203
- const bflOptions = await parseProviderOptions({
204
- provider: "blackForestLabs",
205
- providerOptions,
206
- schema: blackForestLabsImageModelOptionsSchema
207
- });
208
204
  const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
209
205
  const combinedHeaders = combineHeaders(
210
206
  await resolve(this.config.headers),
@@ -239,7 +235,10 @@ var BlackForestLabsImageModel = class _BlackForestLabsImageModel {
239
235
  });
240
236
  const { value: imageBytes, responseHeaders } = await getFromApi({
241
237
  url: imageUrl,
242
- headers: combinedHeaders,
238
+ // Only send credentials if the response-supplied URL points back at the
239
+ // provider; the image is typically delivered from a CDN, so the API key
240
+ // must not travel to a foreign host.
241
+ headers: isTrustedUrl(imageUrl, this.config.baseURL) ? combinedHeaders : void 0,
243
242
  abortSignal,
244
243
  failedResponseHandler: createStatusCodeErrorResponseHandler(),
245
244
  successfulResponseHandler: createBinaryResponseHandler(),
@@ -294,7 +293,9 @@ var BlackForestLabsImageModel = class _BlackForestLabsImageModel {
294
293
  for (let i = 0; i < maxPollAttempts; i++) {
295
294
  const { value } = await getFromApi({
296
295
  url: url.toString(),
297
- headers,
296
+ // The polling URL comes from the provider response; only send
297
+ // credentials when it stays on a trusted provider host.
298
+ headers: isTrustedUrl(url.toString(), this.config.baseURL) ? headers : void 0,
298
299
  failedResponseHandler: bflFailedResponseHandler,
299
300
  successfulResponseHandler: createJsonResponseHandler(bflPollSchema),
300
301
  abortSignal,
@@ -323,6 +324,17 @@ var BlackForestLabsImageModel = class _BlackForestLabsImageModel {
323
324
  throw new Error("Black Forest Labs generation timed out.");
324
325
  }
325
326
  };
327
+ function isTrustedUrl(url, baseUrl) {
328
+ if (isSameOrigin(url, baseUrl)) {
329
+ return true;
330
+ }
331
+ try {
332
+ const { protocol, hostname } = new URL(url);
333
+ return protocol === "https:" && (hostname === "bfl.ai" || hostname.endsWith(".bfl.ai"));
334
+ } catch (e) {
335
+ return false;
336
+ }
337
+ }
326
338
  function convertSizeToAspectRatio(size) {
327
339
  const [wStr, hStr] = size.split("x");
328
340
  const width = Number(wStr);
@@ -403,7 +415,7 @@ function bflErrorToMessage(error) {
403
415
  }
404
416
 
405
417
  // src/version.ts
406
- var VERSION = true ? "2.0.0-canary.49" : "0.0.0-test";
418
+ var VERSION = true ? "2.0.0" : "0.0.0-test";
407
419
 
408
420
  // src/black-forest-labs-provider.ts
409
421
  var defaultBaseURL = "https://api.bfl.ai/v1";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/black-forest-labs-provider.ts","../src/black-forest-labs-image-model.ts","../src/black-forest-labs-image-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ImageModelV4,\n type ProviderV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { BlackForestLabsImageModel } from './black-forest-labs-image-model';\nimport type { BlackForestLabsImageModelId } from './black-forest-labs-image-settings';\nimport { VERSION } from './version';\n\nexport interface BlackForestLabsProviderSettings {\n /**\n * Black Forest Labs API key. Default value is taken from the `BFL_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls. Defaults to `https://api.bfl.ai/v1`.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\n * Poll interval in milliseconds between status checks. Defaults to 500ms.\n */\n pollIntervalMillis?: number;\n\n /**\n * Overall timeout in milliseconds for polling before giving up. Defaults to 60s.\n */\n pollTimeoutMillis?: number;\n}\n\nexport interface BlackForestLabsProvider extends ProviderV4 {\n /**\n * Creates a model for image generation.\n */\n image(modelId: BlackForestLabsImageModelId): ImageModelV4;\n\n /**\n * Creates a model for image generation.\n */\n imageModel(modelId: BlackForestLabsImageModelId): ImageModelV4;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\nconst defaultBaseURL = 'https://api.bfl.ai/v1';\n\nexport function createBlackForestLabs(\n options: BlackForestLabsProviderSettings = {},\n): BlackForestLabsProvider {\n const baseURL = withoutTrailingSlash(options.baseURL ?? defaultBaseURL);\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n 'x-key': loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'BFL_API_KEY',\n description: 'Black Forest Labs',\n }),\n ...options.headers,\n },\n `ai-sdk/black-forest-labs/${VERSION}`,\n );\n\n const createImageModel = (modelId: BlackForestLabsImageModelId) =>\n new BlackForestLabsImageModel(modelId, {\n provider: 'black-forest-labs.image',\n baseURL: baseURL ?? defaultBaseURL,\n headers: getHeaders,\n fetch: options.fetch,\n pollIntervalMillis: options.pollIntervalMillis,\n pollTimeoutMillis: options.pollTimeoutMillis,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v4',\n imageModel: createImageModel,\n image: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\nexport const blackForestLabs = createBlackForestLabs();\n","import type { ImageModelV4, SharedV4Warning } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createBinaryResponseHandler,\n createJsonErrorResponseHandler,\n createJsonResponseHandler,\n createStatusCodeErrorResponseHandler,\n delay,\n getFromApi,\n parseProviderOptions,\n postJsonToApi,\n resolve,\n serializeModelOptions,\n WORKFLOW_SERIALIZE,\n WORKFLOW_DESERIALIZE,\n type Resolvable,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { blackForestLabsImageModelOptionsSchema } from './black-forest-labs-image-model-options';\nimport type {\n BlackForestLabsAspectRatio,\n BlackForestLabsImageModelId,\n} from './black-forest-labs-image-settings';\n\nconst DEFAULT_POLL_INTERVAL_MILLIS = 500;\nconst DEFAULT_POLL_TIMEOUT_MILLIS = 60000;\n\ninterface BlackForestLabsImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: Resolvable<Record<string, string | undefined>>;\n fetch?: FetchFunction;\n /**\n * Poll interval in milliseconds between status checks. Defaults to 500ms.\n */\n pollIntervalMillis?: number;\n /**\n * Overall timeout in milliseconds for polling before giving up. Defaults to 60s.\n */\n pollTimeoutMillis?: number;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class BlackForestLabsImageModel implements ImageModelV4 {\n readonly specificationVersion = 'v4';\n readonly maxImagesPerCall = 1;\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: BlackForestLabsImageModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: BlackForestLabsImageModelId;\n config: BlackForestLabsImageModelConfig;\n }) {\n return new BlackForestLabsImageModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: BlackForestLabsImageModelId,\n private readonly config: BlackForestLabsImageModelConfig,\n ) {}\n\n private async getArgs({\n prompt,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n }: Parameters<ImageModelV4['doGenerate']>[0]) {\n const warnings: Array<SharedV4Warning> = [];\n\n const finalAspectRatio =\n aspectRatio ?? (size ? convertSizeToAspectRatio(size) : undefined);\n\n if (size && !aspectRatio) {\n warnings.push({\n type: 'unsupported',\n feature: 'size',\n details:\n 'Deriving aspect_ratio from size. Use the width and height provider options to specify dimensions for models that support them.',\n });\n } else if (size && aspectRatio) {\n warnings.push({\n type: 'unsupported',\n feature: 'size',\n details:\n 'Black Forest Labs ignores size when aspectRatio is provided. Use the width and height provider options to specify dimensions for models that support them',\n });\n }\n\n const bflOptions = await parseProviderOptions({\n provider: 'blackForestLabs',\n providerOptions,\n schema: blackForestLabsImageModelOptionsSchema,\n });\n\n const [widthStr, heightStr] = size?.split('x') ?? [];\n\n const inputImages: string[] =\n files?.map(file => {\n if (file.type === 'url') {\n return file.url;\n }\n\n if (typeof file.data === 'string') {\n return file.data;\n }\n\n return Buffer.from(file.data).toString('base64');\n }) || [];\n\n if (inputImages.length > 10) {\n throw new Error('Black Forest Labs supports up to 10 input images.');\n }\n\n const inputImageField =\n this.modelId === 'flux-pro-1.0-fill' ? 'image' : 'input_image';\n const inputImagesObj: Record<string, string> = inputImages.reduce<\n Record<string, string>\n >((acc, img, index) => {\n acc[`${inputImageField}${index === 0 ? '' : `_${index + 1}`}`] = img;\n return acc;\n }, {});\n\n let maskValue: string | undefined;\n if (mask) {\n if (mask.type === 'url') {\n maskValue = mask.url;\n } else {\n if (typeof mask.data === 'string') {\n maskValue = mask.data;\n } else {\n maskValue = Buffer.from(mask.data).toString('base64');\n }\n }\n }\n\n const body: Record<string, unknown> = {\n prompt,\n seed,\n aspect_ratio: finalAspectRatio,\n width: bflOptions?.width ?? (size ? Number(widthStr) : undefined),\n height: bflOptions?.height ?? (size ? Number(heightStr) : undefined),\n steps: bflOptions?.steps,\n guidance: bflOptions?.guidance,\n image_prompt_strength: bflOptions?.imagePromptStrength,\n image_prompt: bflOptions?.imagePrompt,\n ...inputImagesObj,\n mask: maskValue,\n output_format: bflOptions?.outputFormat,\n prompt_upsampling: bflOptions?.promptUpsampling,\n raw: bflOptions?.raw,\n safety_tolerance: bflOptions?.safetyTolerance,\n webhook_secret: bflOptions?.webhookSecret,\n webhook_url: bflOptions?.webhookUrl,\n };\n\n return { body, warnings };\n }\n\n async doGenerate({\n prompt,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n headers,\n abortSignal,\n }: Parameters<ImageModelV4['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV4['doGenerate']>>\n > {\n const { body, warnings } = await this.getArgs({\n prompt,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n n: 1,\n headers,\n abortSignal,\n } as Parameters<ImageModelV4['doGenerate']>[0]);\n\n const bflOptions = await parseProviderOptions({\n provider: 'blackForestLabs',\n providerOptions,\n schema: blackForestLabsImageModelOptionsSchema,\n });\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const combinedHeaders = combineHeaders(\n await resolve(this.config.headers),\n headers,\n );\n\n const submit = await postJsonToApi({\n url: `${this.config.baseURL}/${this.modelId}`,\n headers: combinedHeaders,\n body,\n failedResponseHandler: bflFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(bflSubmitSchema),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const pollUrl = submit.value.polling_url;\n const requestId = submit.value.id;\n\n const {\n imageUrl,\n seed: resultSeed,\n start_time: resultStartTime,\n end_time: resultEndTime,\n duration: resultDuration,\n } = await this.pollForImageUrl({\n pollUrl,\n requestId,\n headers: combinedHeaders,\n abortSignal,\n pollOverrides: {\n pollIntervalMillis: bflOptions?.pollIntervalMillis,\n pollTimeoutMillis: bflOptions?.pollTimeoutMillis,\n },\n });\n\n const { value: imageBytes, responseHeaders } = await getFromApi({\n url: imageUrl,\n headers: combinedHeaders,\n abortSignal,\n failedResponseHandler: createStatusCodeErrorResponseHandler(),\n successfulResponseHandler: createBinaryResponseHandler(),\n fetch: this.config.fetch,\n });\n\n return {\n images: [imageBytes],\n warnings,\n providerMetadata: {\n blackForestLabs: {\n images: [\n {\n ...(resultSeed != null && { seed: resultSeed }),\n ...(resultStartTime != null && { start_time: resultStartTime }),\n ...(resultEndTime != null && { end_time: resultEndTime }),\n ...(resultDuration != null && { duration: resultDuration }),\n ...(submit.value.cost != null && { cost: submit.value.cost }),\n ...(submit.value.input_mp != null && {\n inputMegapixels: submit.value.input_mp,\n }),\n ...(submit.value.output_mp != null && {\n outputMegapixels: submit.value.output_mp,\n }),\n },\n ],\n },\n },\n response: {\n modelId: this.modelId,\n timestamp: currentDate,\n headers: responseHeaders,\n },\n };\n }\n\n private async pollForImageUrl({\n pollUrl,\n requestId,\n headers,\n abortSignal,\n pollOverrides,\n }: {\n pollUrl: string;\n requestId: string;\n headers: Record<string, string | undefined>;\n abortSignal: AbortSignal | undefined;\n pollOverrides?: {\n pollIntervalMillis?: number;\n pollTimeoutMillis?: number;\n };\n }): Promise<{\n imageUrl: string;\n seed?: number;\n start_time?: number;\n end_time?: number;\n duration?: number;\n }> {\n const pollIntervalMillis =\n pollOverrides?.pollIntervalMillis ??\n this.config.pollIntervalMillis ??\n DEFAULT_POLL_INTERVAL_MILLIS;\n const pollTimeoutMillis =\n pollOverrides?.pollTimeoutMillis ??\n this.config.pollTimeoutMillis ??\n DEFAULT_POLL_TIMEOUT_MILLIS;\n const maxPollAttempts = Math.ceil(\n pollTimeoutMillis / Math.max(1, pollIntervalMillis),\n );\n\n const url = new URL(pollUrl);\n if (!url.searchParams.has('id')) {\n url.searchParams.set('id', requestId);\n }\n\n for (let i = 0; i < maxPollAttempts; i++) {\n const { value } = await getFromApi({\n url: url.toString(),\n headers,\n failedResponseHandler: bflFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(bflPollSchema),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const status = value.status;\n if (status === 'Ready') {\n if (typeof value.result?.sample === 'string') {\n return {\n imageUrl: value.result.sample,\n seed: value.result.seed ?? undefined,\n start_time: value.result.start_time ?? undefined,\n end_time: value.result.end_time ?? undefined,\n duration: value.result.duration ?? undefined,\n };\n }\n throw new Error(\n 'Black Forest Labs poll response is Ready but missing result.sample',\n );\n }\n if (status === 'Error' || status === 'Failed') {\n throw new Error('Black Forest Labs generation failed.');\n }\n\n await delay(pollIntervalMillis);\n }\n\n throw new Error('Black Forest Labs generation timed out.');\n }\n}\n\nfunction convertSizeToAspectRatio(\n size: string,\n): BlackForestLabsAspectRatio | undefined {\n const [wStr, hStr] = size.split('x');\n const width = Number(wStr);\n const height = Number(hStr);\n if (\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n width <= 0 ||\n height <= 0\n ) {\n return undefined;\n }\n const g = gcd(width, height);\n return `${Math.round(width / g)}:${Math.round(height / g)}`;\n}\n\nfunction gcd(a: number, b: number): number {\n let x = Math.abs(a);\n let y = Math.abs(b);\n while (y !== 0) {\n const t = y;\n y = x % y;\n x = t;\n }\n return x;\n}\n\nconst bflSubmitSchema = z.object({\n id: z.string(),\n polling_url: z.url(),\n cost: z.number().nullish(),\n input_mp: z.number().nullish(),\n output_mp: z.number().nullish(),\n});\n\nconst bflStatus = z.union([\n z.literal('Pending'),\n z.literal('Ready'),\n z.literal('Error'),\n z.literal('Failed'),\n z.literal('Request Moderated'),\n]);\n\nconst bflPollSchema = z\n .object({\n status: bflStatus.optional(),\n state: bflStatus.optional(),\n details: z.unknown().optional(),\n result: z\n .object({\n sample: z.url(),\n seed: z.number().optional(),\n start_time: z.number().optional(),\n end_time: z.number().optional(),\n duration: z.number().optional(),\n })\n .nullish(),\n })\n .refine(v => v.status != null || v.state != null, {\n message: 'Missing status in Black Forest Labs poll response',\n })\n .transform(v => ({\n status: (v.status ?? v.state)!,\n result: v.result,\n }));\n\nconst bflErrorSchema = z.object({\n message: z.string().optional(),\n detail: z.any().optional(),\n});\n\nconst bflFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: bflErrorSchema,\n errorToMessage: error =>\n bflErrorToMessage(error) ?? 'Unknown Black Forest Labs error',\n});\n\nfunction bflErrorToMessage(error: unknown): string | undefined {\n const parsed = bflErrorSchema.safeParse(error);\n if (!parsed.success) return undefined;\n const { message, detail } = parsed.data;\n if (typeof detail === 'string') return detail;\n if (detail != null) {\n try {\n return JSON.stringify(detail);\n } catch {\n // ignore\n }\n }\n return message;\n}\n","import {\n lazySchema,\n zodSchema,\n type InferSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nexport const blackForestLabsImageModelOptionsSchema = lazySchema(() =>\n zodSchema(\n z.object({\n imagePrompt: z.string().optional(),\n imagePromptStrength: z.number().min(0).max(1).optional(),\n /** @deprecated use prompt.images instead */\n inputImage: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage2: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage3: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage4: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage5: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage6: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage7: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage8: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage9: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage10: z.string().optional(),\n steps: z.number().int().positive().optional(),\n guidance: z.number().min(0).optional(),\n width: z.number().int().min(256).max(1920).optional(),\n height: z.number().int().min(256).max(1920).optional(),\n outputFormat: z.enum(['jpeg', 'png']).optional(),\n promptUpsampling: z.boolean().optional(),\n raw: z.boolean().optional(),\n safetyTolerance: z.number().int().min(0).max(6).optional(),\n webhookSecret: z.string().optional(),\n webhookUrl: z.url().optional(),\n pollIntervalMillis: z.number().int().positive().optional(),\n pollTimeoutMillis: z.number().int().positive().optional(),\n }),\n ),\n);\n\nexport type BlackForestLabsImageModelOptions = InferSchema<\n typeof blackForestLabsImageModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":";AAAA;AAAA,EACE;AAAA,OAGK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OAEK;;;ACTP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAGK;AACP,SAAS,KAAAA,UAAS;;;AClBlB;AAAA,EACE;AAAA,EACA;AAAA,OAEK;AACP,SAAS,SAAS;AAEX,IAAM,yCAAyC;AAAA,EAAW,MAC/D;AAAA,IACE,EAAE,OAAO;AAAA,MACP,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,MACjC,qBAAqB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,MAEvD,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEhC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA;AAAA,MAEjC,cAAc,EAAE,OAAO,EAAE,SAAS;AAAA,MAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,MAC5C,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,MACrC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE,SAAS;AAAA,MACpD,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,EAAE,IAAI,IAAI,EAAE,SAAS;AAAA,MACrD,cAAc,EAAE,KAAK,CAAC,QAAQ,KAAK,CAAC,EAAE,SAAS;AAAA,MAC/C,kBAAkB,EAAE,QAAQ,EAAE,SAAS;AAAA,MACvC,KAAK,EAAE,QAAQ,EAAE,SAAS;AAAA,MAC1B,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,MACzD,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,MACnC,YAAY,EAAE,IAAI,EAAE,SAAS;AAAA,MAC7B,oBAAoB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,MACzD,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,IAC1D,CAAC;AAAA,EACH;AACF;;;ADrBA,IAAM,+BAA+B;AACrC,IAAM,8BAA8B;AAoB7B,IAAM,4BAAN,MAAM,2BAAkD;AAAA,EAsB7D,YACW,SACQ,QACjB;AAFS;AACQ;AAvBnB,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAAA,EAuBzB;AAAA,EArBH,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,QAAQ,kBAAkB,EAAE,OAAkC;AAC5D,WAAO,sBAAsB;AAAA,MAC3B,SAAS,MAAM;AAAA,MACf,QAAQ,MAAM;AAAA,IAChB,CAAC;AAAA,EACH;AAAA,EAEA,QAAQ,oBAAoB,EAAE,SAG3B;AACD,WAAO,IAAI,2BAA0B,QAAQ,SAAS,QAAQ,MAAM;AAAA,EACtE;AAAA,EAOA,MAAc,QAAQ;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAA8C;AAjFhD;AAkFI,UAAM,WAAmC,CAAC;AAE1C,UAAM,mBACJ,oCAAgB,OAAO,yBAAyB,IAAI,IAAI;AAE1D,QAAI,QAAQ,CAAC,aAAa;AACxB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH,WAAW,QAAQ,aAAa;AAC9B,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,UAAM,aAAa,MAAM,qBAAqB;AAAA,MAC5C,UAAU;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,CAAC,UAAU,SAAS,KAAI,kCAAM,MAAM,SAAZ,YAAoB,CAAC;AAEnD,UAAM,eACJ,+BAAO,IAAI,UAAQ;AACjB,UAAI,KAAK,SAAS,OAAO;AACvB,eAAO,KAAK;AAAA,MACd;AAEA,UAAI,OAAO,KAAK,SAAS,UAAU;AACjC,eAAO,KAAK;AAAA,MACd;AAEA,aAAO,OAAO,KAAK,KAAK,IAAI,EAAE,SAAS,QAAQ;AAAA,IACjD,OAAM,CAAC;AAET,QAAI,YAAY,SAAS,IAAI;AAC3B,YAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AAEA,UAAM,kBACJ,KAAK,YAAY,sBAAsB,UAAU;AACnD,UAAM,iBAAyC,YAAY,OAEzD,CAAC,KAAK,KAAK,UAAU;AACrB,UAAI,GAAG,eAAe,GAAG,UAAU,IAAI,KAAK,IAAI,QAAQ,CAAC,EAAE,EAAE,IAAI;AACjE,aAAO;AAAA,IACT,GAAG,CAAC,CAAC;AAEL,QAAI;AACJ,QAAI,MAAM;AACR,UAAI,KAAK,SAAS,OAAO;AACvB,oBAAY,KAAK;AAAA,MACnB,OAAO;AACL,YAAI,OAAO,KAAK,SAAS,UAAU;AACjC,sBAAY,KAAK;AAAA,QACnB,OAAO;AACL,sBAAY,OAAO,KAAK,KAAK,IAAI,EAAE,SAAS,QAAQ;AAAA,QACtD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,OAAgC;AAAA,MACpC;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,QAAO,8CAAY,UAAZ,YAAsB,OAAO,OAAO,QAAQ,IAAI;AAAA,MACvD,SAAQ,8CAAY,WAAZ,YAAuB,OAAO,OAAO,SAAS,IAAI;AAAA,MAC1D,OAAO,yCAAY;AAAA,MACnB,UAAU,yCAAY;AAAA,MACtB,uBAAuB,yCAAY;AAAA,MACnC,cAAc,yCAAY;AAAA,MAC1B,GAAG;AAAA,MACH,MAAM;AAAA,MACN,eAAe,yCAAY;AAAA,MAC3B,mBAAmB,yCAAY;AAAA,MAC/B,KAAK,yCAAY;AAAA,MACjB,kBAAkB,yCAAY;AAAA,MAC9B,gBAAgB,yCAAY;AAAA,MAC5B,aAAa,yCAAY;AAAA,IAC3B;AAEA,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AAAA,EAEA,MAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAEE;AAzLJ;AA0LI,UAAM,EAAE,MAAM,SAAS,IAAI,MAAM,KAAK,QAAQ;AAAA,MAC5C;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IACF,CAA8C;AAE9C,UAAM,aAAa,MAAM,qBAAqB;AAAA,MAC5C,UAAU;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,eAAc,sBAAK,OAAO,cAAZ,mBAAuB,gBAAvB,4CAA0C,oBAAI,KAAK;AACvE,UAAM,kBAAkB;AAAA,MACtB,MAAM,QAAQ,KAAK,OAAO,OAAO;AAAA,MACjC;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,cAAc;AAAA,MACjC,KAAK,GAAG,KAAK,OAAO,OAAO,IAAI,KAAK,OAAO;AAAA,MAC3C,SAAS;AAAA,MACT;AAAA,MACA,uBAAuB;AAAA,MACvB,2BAA2B,0BAA0B,eAAe;AAAA,MACpE;AAAA,MACA,OAAO,KAAK,OAAO;AAAA,IACrB,CAAC;AAED,UAAM,UAAU,OAAO,MAAM;AAC7B,UAAM,YAAY,OAAO,MAAM;AAE/B,UAAM;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,UAAU;AAAA,MACV,UAAU;AAAA,IACZ,IAAI,MAAM,KAAK,gBAAgB;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,SAAS;AAAA,MACT;AAAA,MACA,eAAe;AAAA,QACb,oBAAoB,yCAAY;AAAA,QAChC,mBAAmB,yCAAY;AAAA,MACjC;AAAA,IACF,CAAC;AAED,UAAM,EAAE,OAAO,YAAY,gBAAgB,IAAI,MAAM,WAAW;AAAA,MAC9D,KAAK;AAAA,MACL,SAAS;AAAA,MACT;AAAA,MACA,uBAAuB,qCAAqC;AAAA,MAC5D,2BAA2B,4BAA4B;AAAA,MACvD,OAAO,KAAK,OAAO;AAAA,IACrB,CAAC;AAED,WAAO;AAAA,MACL,QAAQ,CAAC,UAAU;AAAA,MACnB;AAAA,MACA,kBAAkB;AAAA,QAChB,iBAAiB;AAAA,UACf,QAAQ;AAAA,YACN;AAAA,cACE,GAAI,cAAc,QAAQ,EAAE,MAAM,WAAW;AAAA,cAC7C,GAAI,mBAAmB,QAAQ,EAAE,YAAY,gBAAgB;AAAA,cAC7D,GAAI,iBAAiB,QAAQ,EAAE,UAAU,cAAc;AAAA,cACvD,GAAI,kBAAkB,QAAQ,EAAE,UAAU,eAAe;AAAA,cACzD,GAAI,OAAO,MAAM,QAAQ,QAAQ,EAAE,MAAM,OAAO,MAAM,KAAK;AAAA,cAC3D,GAAI,OAAO,MAAM,YAAY,QAAQ;AAAA,gBACnC,iBAAiB,OAAO,MAAM;AAAA,cAChC;AAAA,cACA,GAAI,OAAO,MAAM,aAAa,QAAQ;AAAA,gBACpC,kBAAkB,OAAO,MAAM;AAAA,cACjC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,MACA,UAAU;AAAA,QACR,SAAS,KAAK;AAAA,QACd,WAAW;AAAA,QACX,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAeG;AA7SL;AA8SI,UAAM,sBACJ,0DAAe,uBAAf,YACA,KAAK,OAAO,uBADZ,YAEA;AACF,UAAM,qBACJ,0DAAe,sBAAf,YACA,KAAK,OAAO,sBADZ,YAEA;AACF,UAAM,kBAAkB,KAAK;AAAA,MAC3B,oBAAoB,KAAK,IAAI,GAAG,kBAAkB;AAAA,IACpD;AAEA,UAAM,MAAM,IAAI,IAAI,OAAO;AAC3B,QAAI,CAAC,IAAI,aAAa,IAAI,IAAI,GAAG;AAC/B,UAAI,aAAa,IAAI,MAAM,SAAS;AAAA,IACtC;AAEA,aAAS,IAAI,GAAG,IAAI,iBAAiB,KAAK;AACxC,YAAM,EAAE,MAAM,IAAI,MAAM,WAAW;AAAA,QACjC,KAAK,IAAI,SAAS;AAAA,QAClB;AAAA,QACA,uBAAuB;AAAA,QACvB,2BAA2B,0BAA0B,aAAa;AAAA,QAClE;AAAA,QACA,OAAO,KAAK,OAAO;AAAA,MACrB,CAAC;AAED,YAAM,SAAS,MAAM;AACrB,UAAI,WAAW,SAAS;AACtB,YAAI,SAAO,WAAM,WAAN,mBAAc,YAAW,UAAU;AAC5C,iBAAO;AAAA,YACL,UAAU,MAAM,OAAO;AAAA,YACvB,OAAM,WAAM,OAAO,SAAb,YAAqB;AAAA,YAC3B,aAAY,WAAM,OAAO,eAAb,YAA2B;AAAA,YACvC,WAAU,WAAM,OAAO,aAAb,YAAyB;AAAA,YACnC,WAAU,WAAM,OAAO,aAAb,YAAyB;AAAA,UACrC;AAAA,QACF;AACA,cAAM,IAAI;AAAA,UACR;AAAA,QACF;AAAA,MACF;AACA,UAAI,WAAW,WAAW,WAAW,UAAU;AAC7C,cAAM,IAAI,MAAM,sCAAsC;AAAA,MACxD;AAEA,YAAM,MAAM,kBAAkB;AAAA,IAChC;AAEA,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AACF;AAEA,SAAS,yBACP,MACwC;AACxC,QAAM,CAAC,MAAM,IAAI,IAAI,KAAK,MAAM,GAAG;AACnC,QAAM,QAAQ,OAAO,IAAI;AACzB,QAAM,SAAS,OAAO,IAAI;AAC1B,MACE,CAAC,OAAO,SAAS,KAAK,KACtB,CAAC,OAAO,SAAS,MAAM,KACvB,SAAS,KACT,UAAU,GACV;AACA,WAAO;AAAA,EACT;AACA,QAAM,IAAI,IAAI,OAAO,MAAM;AAC3B,SAAO,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC,IAAI,KAAK,MAAM,SAAS,CAAC,CAAC;AAC3D;AAEA,SAAS,IAAI,GAAW,GAAmB;AACzC,MAAI,IAAI,KAAK,IAAI,CAAC;AAClB,MAAI,IAAI,KAAK,IAAI,CAAC;AAClB,SAAO,MAAM,GAAG;AACd,UAAM,IAAI;AACV,QAAI,IAAI;AACR,QAAI;AAAA,EACN;AACA,SAAO;AACT;AAEA,IAAM,kBAAkBC,GAAE,OAAO;AAAA,EAC/B,IAAIA,GAAE,OAAO;AAAA,EACb,aAAaA,GAAE,IAAI;AAAA,EACnB,MAAMA,GAAE,OAAO,EAAE,QAAQ;AAAA,EACzB,UAAUA,GAAE,OAAO,EAAE,QAAQ;AAAA,EAC7B,WAAWA,GAAE,OAAO,EAAE,QAAQ;AAChC,CAAC;AAED,IAAM,YAAYA,GAAE,MAAM;AAAA,EACxBA,GAAE,QAAQ,SAAS;AAAA,EACnBA,GAAE,QAAQ,OAAO;AAAA,EACjBA,GAAE,QAAQ,OAAO;AAAA,EACjBA,GAAE,QAAQ,QAAQ;AAAA,EAClBA,GAAE,QAAQ,mBAAmB;AAC/B,CAAC;AAED,IAAM,gBAAgBA,GACnB,OAAO;AAAA,EACN,QAAQ,UAAU,SAAS;AAAA,EAC3B,OAAO,UAAU,SAAS;AAAA,EAC1B,SAASA,GAAE,QAAQ,EAAE,SAAS;AAAA,EAC9B,QAAQA,GACL,OAAO;AAAA,IACN,QAAQA,GAAE,IAAI;AAAA,IACd,MAAMA,GAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,YAAYA,GAAE,OAAO,EAAE,SAAS;AAAA,IAChC,UAAUA,GAAE,OAAO,EAAE,SAAS;AAAA,IAC9B,UAAUA,GAAE,OAAO,EAAE,SAAS;AAAA,EAChC,CAAC,EACA,QAAQ;AACb,CAAC,EACA,OAAO,OAAK,EAAE,UAAU,QAAQ,EAAE,SAAS,MAAM;AAAA,EAChD,SAAS;AACX,CAAC,EACA,UAAU,OAAE;AAlaf;AAkamB;AAAA,IACf,SAAS,OAAE,WAAF,YAAY,EAAE;AAAA,IACvB,QAAQ,EAAE;AAAA,EACZ;AAAA,CAAE;AAEJ,IAAM,iBAAiBA,GAAE,OAAO;AAAA,EAC9B,SAASA,GAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,QAAQA,GAAE,IAAI,EAAE,SAAS;AAC3B,CAAC;AAED,IAAM,2BAA2B,+BAA+B;AAAA,EAC9D,aAAa;AAAA,EACb,gBAAgB,WAAM;AA9axB;AA+aI,mCAAkB,KAAK,MAAvB,YAA4B;AAAA;AAChC,CAAC;AAED,SAAS,kBAAkB,OAAoC;AAC7D,QAAM,SAAS,eAAe,UAAU,KAAK;AAC7C,MAAI,CAAC,OAAO,QAAS,QAAO;AAC5B,QAAM,EAAE,SAAS,OAAO,IAAI,OAAO;AACnC,MAAI,OAAO,WAAW,SAAU,QAAO;AACvC,MAAI,UAAU,MAAM;AAClB,QAAI;AACF,aAAO,KAAK,UAAU,MAAM;AAAA,IAC9B,SAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;;;AE7bO,IAAM,UACX,OACI,oBACA;;;AH4DN,IAAM,iBAAiB;AAEhB,SAAS,sBACd,UAA2C,CAAC,GACnB;AArE3B;AAsEE,QAAM,UAAU,sBAAqB,aAAQ,YAAR,YAAmB,cAAc;AACtE,QAAM,aAAa,MACjB;AAAA,IACE;AAAA,MACE,SAAS,WAAW;AAAA,QAClB,QAAQ,QAAQ;AAAA,QAChB,yBAAyB;AAAA,QACzB,aAAa;AAAA,MACf,CAAC;AAAA,MACD,GAAG,QAAQ;AAAA,IACb;AAAA,IACA,4BAA4B,OAAO;AAAA,EACrC;AAEF,QAAM,mBAAmB,CAAC,YACxB,IAAI,0BAA0B,SAAS;AAAA,IACrC,UAAU;AAAA,IACV,SAAS,4BAAW;AAAA,IACpB,SAAS;AAAA,IACT,OAAO,QAAQ;AAAA,IACf,oBAAoB,QAAQ;AAAA,IAC5B,mBAAmB,QAAQ;AAAA,EAC7B,CAAC;AAEH,QAAM,iBAAiB,CAAC,YAAoB;AAC1C,UAAM,IAAI,iBAAiB;AAAA,MACzB;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,eAAe,CAAC,YAAoB;AAClC,YAAM,IAAI,iBAAiB;AAAA,QACzB;AAAA,QACA,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,EACtB;AACF;AAEO,IAAM,kBAAkB,sBAAsB;","names":["z","z"]}
1
+ {"version":3,"sources":["../src/black-forest-labs-provider.ts","../src/black-forest-labs-image-model.ts","../src/black-forest-labs-image-model-options.ts","../src/version.ts"],"sourcesContent":["import {\n NoSuchModelError,\n type ImageModelV4,\n type ProviderV4,\n} from '@ai-sdk/provider';\nimport {\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { BlackForestLabsImageModel } from './black-forest-labs-image-model';\nimport type { BlackForestLabsImageModelId } from './black-forest-labs-image-settings';\nimport { VERSION } from './version';\n\nexport interface BlackForestLabsProviderSettings {\n /**\n * Black Forest Labs API key. Default value is taken from the `BFL_API_KEY` environment variable.\n */\n apiKey?: string;\n\n /**\n * Base URL for the API calls. Defaults to `https://api.bfl.ai/v1`.\n */\n baseURL?: string;\n\n /**\n * Custom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\n * Custom fetch implementation. You can use it as a middleware to intercept\n * requests, or to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n\n /**\n * Poll interval in milliseconds between status checks. Defaults to 500ms.\n */\n pollIntervalMillis?: number;\n\n /**\n * Overall timeout in milliseconds for polling before giving up. Defaults to 60s.\n */\n pollTimeoutMillis?: number;\n}\n\nexport interface BlackForestLabsProvider extends ProviderV4 {\n /**\n * Creates a model for image generation.\n */\n image(modelId: BlackForestLabsImageModelId): ImageModelV4;\n\n /**\n * Creates a model for image generation.\n */\n imageModel(modelId: BlackForestLabsImageModelId): ImageModelV4;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\nconst defaultBaseURL = 'https://api.bfl.ai/v1';\n\nexport function createBlackForestLabs(\n options: BlackForestLabsProviderSettings = {},\n): BlackForestLabsProvider {\n const baseURL = withoutTrailingSlash(options.baseURL ?? defaultBaseURL);\n const getHeaders = () =>\n withUserAgentSuffix(\n {\n 'x-key': loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'BFL_API_KEY',\n description: 'Black Forest Labs',\n }),\n ...options.headers,\n },\n `ai-sdk/black-forest-labs/${VERSION}`,\n );\n\n const createImageModel = (modelId: BlackForestLabsImageModelId) =>\n new BlackForestLabsImageModel(modelId, {\n provider: 'black-forest-labs.image',\n baseURL: baseURL ?? defaultBaseURL,\n headers: getHeaders,\n fetch: options.fetch,\n pollIntervalMillis: options.pollIntervalMillis,\n pollTimeoutMillis: options.pollTimeoutMillis,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v4',\n imageModel: createImageModel,\n image: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\nexport const blackForestLabs = createBlackForestLabs();\n","import type { ImageModelV4, SharedV4Warning } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createBinaryResponseHandler,\n createJsonErrorResponseHandler,\n createJsonResponseHandler,\n createStatusCodeErrorResponseHandler,\n delay,\n getFromApi,\n isSameOrigin,\n parseProviderOptions,\n postJsonToApi,\n resolve,\n serializeModelOptions,\n WORKFLOW_SERIALIZE,\n WORKFLOW_DESERIALIZE,\n type Resolvable,\n type FetchFunction,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { blackForestLabsImageModelOptionsSchema } from './black-forest-labs-image-model-options';\nimport type {\n BlackForestLabsAspectRatio,\n BlackForestLabsImageModelId,\n} from './black-forest-labs-image-settings';\n\nconst DEFAULT_POLL_INTERVAL_MILLIS = 500;\nconst DEFAULT_POLL_TIMEOUT_MILLIS = 60000;\n\ninterface BlackForestLabsImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: Resolvable<Record<string, string | undefined>>;\n fetch?: FetchFunction;\n /**\n * Poll interval in milliseconds between status checks. Defaults to 500ms.\n */\n pollIntervalMillis?: number;\n /**\n * Overall timeout in milliseconds for polling before giving up. Defaults to 60s.\n */\n pollTimeoutMillis?: number;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nexport class BlackForestLabsImageModel implements ImageModelV4 {\n readonly specificationVersion = 'v4';\n readonly maxImagesPerCall = 1;\n\n get provider(): string {\n return this.config.provider;\n }\n\n static [WORKFLOW_SERIALIZE](model: BlackForestLabsImageModel) {\n return serializeModelOptions({\n modelId: model.modelId,\n config: model.config,\n });\n }\n\n static [WORKFLOW_DESERIALIZE](options: {\n modelId: BlackForestLabsImageModelId;\n config: BlackForestLabsImageModelConfig;\n }) {\n return new BlackForestLabsImageModel(options.modelId, options.config);\n }\n\n constructor(\n readonly modelId: BlackForestLabsImageModelId,\n private readonly config: BlackForestLabsImageModelConfig,\n ) {}\n\n private async getArgs({\n prompt,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n }: Parameters<ImageModelV4['doGenerate']>[0]) {\n const warnings: Array<SharedV4Warning> = [];\n\n const finalAspectRatio =\n aspectRatio ?? (size ? convertSizeToAspectRatio(size) : undefined);\n\n if (size && !aspectRatio) {\n warnings.push({\n type: 'unsupported',\n feature: 'size',\n details:\n 'Deriving aspect_ratio from size. Use the width and height provider options to specify dimensions for models that support them.',\n });\n } else if (size && aspectRatio) {\n warnings.push({\n type: 'unsupported',\n feature: 'size',\n details:\n 'Black Forest Labs ignores size when aspectRatio is provided. Use the width and height provider options to specify dimensions for models that support them',\n });\n }\n\n const bflOptions = await parseProviderOptions({\n provider: 'blackForestLabs',\n providerOptions,\n schema: blackForestLabsImageModelOptionsSchema,\n });\n\n const [widthStr, heightStr] = size?.split('x') ?? [];\n\n const inputImages: string[] =\n files?.map(file => {\n if (file.type === 'url') {\n return file.url;\n }\n\n if (typeof file.data === 'string') {\n return file.data;\n }\n\n return Buffer.from(file.data).toString('base64');\n }) || [];\n\n if (inputImages.length > 10) {\n throw new Error('Black Forest Labs supports up to 10 input images.');\n }\n\n const inputImageField =\n this.modelId === 'flux-pro-1.0-fill' ? 'image' : 'input_image';\n const inputImagesObj: Record<string, string> = inputImages.reduce<\n Record<string, string>\n >((acc, img, index) => {\n acc[`${inputImageField}${index === 0 ? '' : `_${index + 1}`}`] = img;\n return acc;\n }, {});\n\n let maskValue: string | undefined;\n if (mask) {\n if (mask.type === 'url') {\n maskValue = mask.url;\n } else {\n if (typeof mask.data === 'string') {\n maskValue = mask.data;\n } else {\n maskValue = Buffer.from(mask.data).toString('base64');\n }\n }\n }\n\n const body: Record<string, unknown> = {\n prompt,\n seed,\n aspect_ratio: finalAspectRatio,\n width: bflOptions?.width ?? (size ? Number(widthStr) : undefined),\n height: bflOptions?.height ?? (size ? Number(heightStr) : undefined),\n steps: bflOptions?.steps,\n guidance: bflOptions?.guidance,\n image_prompt_strength: bflOptions?.imagePromptStrength,\n image_prompt: bflOptions?.imagePrompt,\n ...inputImagesObj,\n mask: maskValue,\n output_format: bflOptions?.outputFormat,\n prompt_upsampling: bflOptions?.promptUpsampling,\n raw: bflOptions?.raw,\n safety_tolerance: bflOptions?.safetyTolerance,\n webhook_secret: bflOptions?.webhookSecret,\n webhook_url: bflOptions?.webhookUrl,\n };\n\n return { body, warnings, bflOptions };\n }\n\n async doGenerate({\n prompt,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n headers,\n abortSignal,\n }: Parameters<ImageModelV4['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV4['doGenerate']>>\n > {\n const { body, warnings, bflOptions } = await this.getArgs({\n prompt,\n files,\n mask,\n size,\n aspectRatio,\n seed,\n providerOptions,\n n: 1,\n headers,\n abortSignal,\n } as Parameters<ImageModelV4['doGenerate']>[0]);\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n const combinedHeaders = combineHeaders(\n await resolve(this.config.headers),\n headers,\n );\n\n const submit = await postJsonToApi({\n url: `${this.config.baseURL}/${this.modelId}`,\n headers: combinedHeaders,\n body,\n failedResponseHandler: bflFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(bflSubmitSchema),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const pollUrl = submit.value.polling_url;\n const requestId = submit.value.id;\n\n const {\n imageUrl,\n seed: resultSeed,\n start_time: resultStartTime,\n end_time: resultEndTime,\n duration: resultDuration,\n } = await this.pollForImageUrl({\n pollUrl,\n requestId,\n headers: combinedHeaders,\n abortSignal,\n pollOverrides: {\n pollIntervalMillis: bflOptions?.pollIntervalMillis,\n pollTimeoutMillis: bflOptions?.pollTimeoutMillis,\n },\n });\n\n const { value: imageBytes, responseHeaders } = await getFromApi({\n url: imageUrl,\n // Only send credentials if the response-supplied URL points back at the\n // provider; the image is typically delivered from a CDN, so the API key\n // must not travel to a foreign host.\n headers: isTrustedUrl(imageUrl, this.config.baseURL)\n ? combinedHeaders\n : undefined,\n abortSignal,\n failedResponseHandler: createStatusCodeErrorResponseHandler(),\n successfulResponseHandler: createBinaryResponseHandler(),\n fetch: this.config.fetch,\n });\n\n return {\n images: [imageBytes],\n warnings,\n providerMetadata: {\n blackForestLabs: {\n images: [\n {\n ...(resultSeed != null && { seed: resultSeed }),\n ...(resultStartTime != null && { start_time: resultStartTime }),\n ...(resultEndTime != null && { end_time: resultEndTime }),\n ...(resultDuration != null && { duration: resultDuration }),\n ...(submit.value.cost != null && { cost: submit.value.cost }),\n ...(submit.value.input_mp != null && {\n inputMegapixels: submit.value.input_mp,\n }),\n ...(submit.value.output_mp != null && {\n outputMegapixels: submit.value.output_mp,\n }),\n },\n ],\n },\n },\n response: {\n modelId: this.modelId,\n timestamp: currentDate,\n headers: responseHeaders,\n },\n };\n }\n\n private async pollForImageUrl({\n pollUrl,\n requestId,\n headers,\n abortSignal,\n pollOverrides,\n }: {\n pollUrl: string;\n requestId: string;\n headers: Record<string, string | undefined>;\n abortSignal: AbortSignal | undefined;\n pollOverrides?: {\n pollIntervalMillis?: number;\n pollTimeoutMillis?: number;\n };\n }): Promise<{\n imageUrl: string;\n seed?: number;\n start_time?: number;\n end_time?: number;\n duration?: number;\n }> {\n const pollIntervalMillis =\n pollOverrides?.pollIntervalMillis ??\n this.config.pollIntervalMillis ??\n DEFAULT_POLL_INTERVAL_MILLIS;\n const pollTimeoutMillis =\n pollOverrides?.pollTimeoutMillis ??\n this.config.pollTimeoutMillis ??\n DEFAULT_POLL_TIMEOUT_MILLIS;\n const maxPollAttempts = Math.ceil(\n pollTimeoutMillis / Math.max(1, pollIntervalMillis),\n );\n\n const url = new URL(pollUrl);\n if (!url.searchParams.has('id')) {\n url.searchParams.set('id', requestId);\n }\n\n for (let i = 0; i < maxPollAttempts; i++) {\n const { value } = await getFromApi({\n url: url.toString(),\n // The polling URL comes from the provider response; only send\n // credentials when it stays on a trusted provider host.\n headers: isTrustedUrl(url.toString(), this.config.baseURL)\n ? headers\n : undefined,\n failedResponseHandler: bflFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(bflPollSchema),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const status = value.status;\n if (status === 'Ready') {\n if (typeof value.result?.sample === 'string') {\n return {\n imageUrl: value.result.sample,\n seed: value.result.seed ?? undefined,\n start_time: value.result.start_time ?? undefined,\n end_time: value.result.end_time ?? undefined,\n duration: value.result.duration ?? undefined,\n };\n }\n throw new Error(\n 'Black Forest Labs poll response is Ready but missing result.sample',\n );\n }\n if (status === 'Error' || status === 'Failed') {\n throw new Error('Black Forest Labs generation failed.');\n }\n\n await delay(pollIntervalMillis);\n }\n\n throw new Error('Black Forest Labs generation timed out.');\n }\n}\n\n/**\n * Black Forest Labs returns response-supplied URLs (polling and delivery) on\n * sibling cluster hosts of the API origin (e.g. `api.us1.bfl.ai` for a base\n * URL on `api.bfl.ai`), so a strict same-origin check against the configured\n * base URL is not enough. Credentials may also be sent to any https host under\n * the official `bfl.ai` domain.\n */\nfunction isTrustedUrl(url: string, baseUrl: string): boolean {\n if (isSameOrigin(url, baseUrl)) {\n return true;\n }\n\n try {\n const { protocol, hostname } = new URL(url);\n return (\n protocol === 'https:' &&\n (hostname === 'bfl.ai' || hostname.endsWith('.bfl.ai'))\n );\n } catch {\n return false;\n }\n}\n\nfunction convertSizeToAspectRatio(\n size: string,\n): BlackForestLabsAspectRatio | undefined {\n const [wStr, hStr] = size.split('x');\n const width = Number(wStr);\n const height = Number(hStr);\n if (\n !Number.isFinite(width) ||\n !Number.isFinite(height) ||\n width <= 0 ||\n height <= 0\n ) {\n return undefined;\n }\n const g = gcd(width, height);\n return `${Math.round(width / g)}:${Math.round(height / g)}`;\n}\n\nfunction gcd(a: number, b: number): number {\n let x = Math.abs(a);\n let y = Math.abs(b);\n while (y !== 0) {\n const t = y;\n y = x % y;\n x = t;\n }\n return x;\n}\n\nconst bflSubmitSchema = z.object({\n id: z.string(),\n polling_url: z.url(),\n cost: z.number().nullish(),\n input_mp: z.number().nullish(),\n output_mp: z.number().nullish(),\n});\n\nconst bflStatus = z.union([\n z.literal('Pending'),\n z.literal('Ready'),\n z.literal('Error'),\n z.literal('Failed'),\n z.literal('Request Moderated'),\n]);\n\nconst bflPollSchema = z\n .object({\n status: bflStatus.optional(),\n state: bflStatus.optional(),\n details: z.unknown().optional(),\n result: z\n .object({\n sample: z.url(),\n seed: z.number().optional(),\n start_time: z.number().optional(),\n end_time: z.number().optional(),\n duration: z.number().optional(),\n })\n .nullish(),\n })\n .refine(v => v.status != null || v.state != null, {\n message: 'Missing status in Black Forest Labs poll response',\n })\n .transform(v => ({\n status: (v.status ?? v.state)!,\n result: v.result,\n }));\n\nconst bflErrorSchema = z.object({\n message: z.string().optional(),\n detail: z.any().optional(),\n});\n\nconst bflFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: bflErrorSchema,\n errorToMessage: error =>\n bflErrorToMessage(error) ?? 'Unknown Black Forest Labs error',\n});\n\nfunction bflErrorToMessage(error: unknown): string | undefined {\n const parsed = bflErrorSchema.safeParse(error);\n if (!parsed.success) return undefined;\n const { message, detail } = parsed.data;\n if (typeof detail === 'string') return detail;\n if (detail != null) {\n try {\n return JSON.stringify(detail);\n } catch {\n // ignore\n }\n }\n return message;\n}\n","import {\n lazySchema,\n zodSchema,\n type InferSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nexport const blackForestLabsImageModelOptionsSchema = lazySchema(() =>\n zodSchema(\n z.object({\n imagePrompt: z.string().optional(),\n imagePromptStrength: z.number().min(0).max(1).optional(),\n /** @deprecated use prompt.images instead */\n inputImage: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage2: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage3: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage4: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage5: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage6: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage7: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage8: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage9: z.string().optional(),\n /** @deprecated use prompt.images instead */\n inputImage10: z.string().optional(),\n steps: z.number().int().positive().optional(),\n guidance: z.number().min(0).optional(),\n width: z.number().int().min(256).max(1920).optional(),\n height: z.number().int().min(256).max(1920).optional(),\n outputFormat: z.enum(['jpeg', 'png']).optional(),\n promptUpsampling: z.boolean().optional(),\n raw: z.boolean().optional(),\n safetyTolerance: z.number().int().min(0).max(6).optional(),\n webhookSecret: z.string().optional(),\n webhookUrl: z.url().optional(),\n pollIntervalMillis: z.number().int().positive().optional(),\n pollTimeoutMillis: z.number().int().positive().optional(),\n }),\n ),\n);\n\nexport type BlackForestLabsImageModelOptions = InferSchema<\n typeof blackForestLabsImageModelOptionsSchema\n>;\n","// Version string of this package injected at build time.\ndeclare const __PACKAGE_VERSION__: string | undefined;\nexport const VERSION: string =\n typeof __PACKAGE_VERSION__ !== 'undefined'\n ? __PACKAGE_VERSION__\n : '0.0.0-test';\n"],"mappings":"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","names":["z","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/black-forest-labs",
3
- "version": "2.0.0-canary.49",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -28,15 +28,15 @@
28
28
  }
29
29
  },
30
30
  "dependencies": {
31
- "@ai-sdk/provider": "4.0.0-canary.18",
32
- "@ai-sdk/provider-utils": "5.0.0-canary.47"
31
+ "@ai-sdk/provider": "4.0.0",
32
+ "@ai-sdk/provider-utils": "5.0.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "22.19.19",
36
36
  "tsup": "^8.5.1",
37
37
  "typescript": "5.8.3",
38
38
  "zod": "3.25.76",
39
- "@ai-sdk/test-server": "2.0.0-canary.6",
39
+ "@ai-sdk/test-server": "2.0.0",
40
40
  "@vercel/ai-tsconfig": "0.0.0"
41
41
  },
42
42
  "peerDependencies": {
@@ -7,6 +7,7 @@ import {
7
7
  createStatusCodeErrorResponseHandler,
8
8
  delay,
9
9
  getFromApi,
10
+ isSameOrigin,
10
11
  parseProviderOptions,
11
12
  postJsonToApi,
12
13
  resolve,
@@ -168,7 +169,7 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
168
169
  webhook_url: bflOptions?.webhookUrl,
169
170
  };
170
171
 
171
- return { body, warnings };
172
+ return { body, warnings, bflOptions };
172
173
  }
173
174
 
174
175
  async doGenerate({
@@ -184,7 +185,7 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
184
185
  }: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
185
186
  Awaited<ReturnType<ImageModelV4['doGenerate']>>
186
187
  > {
187
- const { body, warnings } = await this.getArgs({
188
+ const { body, warnings, bflOptions } = await this.getArgs({
188
189
  prompt,
189
190
  files,
190
191
  mask,
@@ -197,12 +198,6 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
197
198
  abortSignal,
198
199
  } as Parameters<ImageModelV4['doGenerate']>[0]);
199
200
 
200
- const bflOptions = await parseProviderOptions({
201
- provider: 'blackForestLabs',
202
- providerOptions,
203
- schema: blackForestLabsImageModelOptionsSchema,
204
- });
205
-
206
201
  const currentDate = this.config._internal?.currentDate?.() ?? new Date();
207
202
  const combinedHeaders = combineHeaders(
208
203
  await resolve(this.config.headers),
@@ -241,7 +236,12 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
241
236
 
242
237
  const { value: imageBytes, responseHeaders } = await getFromApi({
243
238
  url: imageUrl,
244
- 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,
245
245
  abortSignal,
246
246
  failedResponseHandler: createStatusCodeErrorResponseHandler(),
247
247
  successfulResponseHandler: createBinaryResponseHandler(),
@@ -320,7 +320,11 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
320
320
  for (let i = 0; i < maxPollAttempts; i++) {
321
321
  const { value } = await getFromApi({
322
322
  url: url.toString(),
323
- 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,
324
328
  failedResponseHandler: bflFailedResponseHandler,
325
329
  successfulResponseHandler: createJsonResponseHandler(bflPollSchema),
326
330
  abortSignal,
@@ -353,6 +357,29 @@ export class BlackForestLabsImageModel implements ImageModelV4 {
353
357
  }
354
358
  }
355
359
 
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
+ }
382
+
356
383
  function convertSizeToAspectRatio(
357
384
  size: string,
358
385
  ): BlackForestLabsAspectRatio | undefined {