@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.
- package/CHANGELOG.md +392 -4
- package/README.md +2 -0
- package/dist/index.js +148 -126
- package/dist/index.js.map +1 -1
- package/package.json +14 -14
- package/src/black-forest-labs-image-model-options.ts +51 -0
- package/src/black-forest-labs-image-model.ts +63 -61
- package/src/black-forest-labs-provider.ts +7 -3
- package/src/index.ts +1 -1
- package/dist/index.d.mts +0 -82
- package/dist/index.mjs +0 -436
- package/dist/index.mjs.map +0 -1
|
@@ -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
|
-
|
|
10
|
+
isSameOrigin,
|
|
13
11
|
parseProviderOptions,
|
|
14
12
|
postJsonToApi,
|
|
15
13
|
resolve,
|
|
16
|
-
|
|
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
|
|
20
|
-
import {
|
|
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[
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
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 {
|
|
2
|
-
|
|
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 };
|