@ai-sdk/replicate 2.0.9 → 2.0.11

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,20 @@
1
1
  # @ai-sdk/replicate
2
2
 
3
+ ## 2.0.11
4
+
5
+ ### Patch Changes
6
+
7
+ - 4de5a1d: chore: excluded tests from src folder in npm package
8
+ - Updated dependencies [4de5a1d]
9
+ - @ai-sdk/provider@3.0.5
10
+ - @ai-sdk/provider-utils@4.0.9
11
+
12
+ ## 2.0.10
13
+
14
+ ### Patch Changes
15
+
16
+ - 2b8369d: chore: add docs to package dist
17
+
3
18
  ## 2.0.9
4
19
 
5
20
  ### Patch Changes
package/dist/index.js CHANGED
@@ -227,7 +227,7 @@ var replicateImageProviderOptionsSchema = (0, import_provider_utils2.lazySchema)
227
227
  );
228
228
 
229
229
  // src/version.ts
230
- var VERSION = true ? "2.0.9" : "0.0.0-test";
230
+ var VERSION = true ? "2.0.11" : "0.0.0-test";
231
231
 
232
232
  // src/replicate-provider.ts
233
233
  function createReplicate(options = {}) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/replicate-provider.ts","../src/replicate-image-model.ts","../src/replicate-error.ts","../src/version.ts"],"sourcesContent":["export { createReplicate, replicate } from './replicate-provider';\nexport type {\n ReplicateProvider,\n ReplicateProviderSettings,\n} from './replicate-provider';\nexport type { ReplicateImageProviderOptions } from './replicate-image-model';\nexport { VERSION } from './version';\n","import { NoSuchModelError, ProviderV3 } from '@ai-sdk/provider';\nimport type { FetchFunction } from '@ai-sdk/provider-utils';\nimport { loadApiKey, withUserAgentSuffix } from '@ai-sdk/provider-utils';\nimport { ReplicateImageModel } from './replicate-image-model';\nimport { ReplicateImageModelId } from './replicate-image-settings';\nimport { VERSION } from './version';\n\nexport interface ReplicateProviderSettings {\n /**\nAPI token that is being send using the `Authorization` header.\nIt defaults to the `REPLICATE_API_TOKEN` environment variable.\n */\n apiToken?: string;\n\n /**\nUse a different URL prefix for API calls, e.g. to use proxy servers.\nThe default prefix is `https://api.replicate.com/v1`.\n */\n baseURL?: string;\n\n /**\nCustom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface ReplicateProvider extends ProviderV3 {\n /**\n * Creates a Replicate image generation model.\n */\n image(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * Creates a Replicate image generation model.\n */\n imageModel(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\n/**\n * Create a Replicate provider instance.\n */\nexport function createReplicate(\n options: ReplicateProviderSettings = {},\n): ReplicateProvider {\n const createImageModel = (modelId: ReplicateImageModelId) =>\n new ReplicateImageModel(modelId, {\n provider: 'replicate',\n baseURL: options.baseURL ?? 'https://api.replicate.com/v1',\n headers: withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiToken,\n environmentVariableName: 'REPLICATE_API_TOKEN',\n description: 'Replicate',\n })}`,\n ...options.headers,\n },\n `ai-sdk/replicate/${VERSION}`,\n ),\n fetch: options.fetch,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v3' as const,\n image: createImageModel,\n imageModel: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\n/**\n * Default Replicate provider instance.\n */\nexport const replicate = createReplicate();\n","import type { ImageModelV3, SharedV3Warning } from '@ai-sdk/provider';\nimport type { Resolvable } from '@ai-sdk/provider-utils';\nimport {\n combineHeaders,\n convertImageModelFileToDataUri,\n createBinaryResponseHandler,\n createJsonResponseHandler,\n FetchFunction,\n getFromApi,\n InferSchema,\n lazySchema,\n parseProviderOptions,\n postJsonToApi,\n resolve,\n zodSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { replicateFailedResponseHandler } from './replicate-error';\nimport { ReplicateImageModelId } from './replicate-image-settings';\n\ninterface ReplicateImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: Resolvable<Record<string, string | undefined>>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\n// Flux-2 models support up to 8 input images with input_image, input_image_2, etc.\nconst FLUX_2_MODEL_PATTERN = /^black-forest-labs\\/flux-2-/;\nconst MAX_FLUX_2_INPUT_IMAGES = 8;\n\nexport class ReplicateImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3';\n\n get maxImagesPerCall(): number {\n // Flux-2 models support up to 8 input images\n return this.isFlux2Model ? MAX_FLUX_2_INPUT_IMAGES : 1;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private get isFlux2Model(): boolean {\n return FLUX_2_MODEL_PATTERN.test(this.modelId);\n }\n\n constructor(\n readonly modelId: ReplicateImageModelId,\n private readonly config: ReplicateImageModelConfig,\n ) {}\n\n async doGenerate({\n prompt,\n n,\n aspectRatio,\n size,\n seed,\n providerOptions,\n headers,\n abortSignal,\n files,\n mask,\n }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV3['doGenerate']>>\n > {\n const warnings: Array<SharedV3Warning> = [];\n\n const [modelId, version] = this.modelId.split(':');\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n // Parse provider options\n const replicateOptions = await parseProviderOptions({\n provider: 'replicate',\n providerOptions,\n schema: replicateImageProviderOptionsSchema,\n });\n\n // Handle image input from files\n let imageInputs: Record<string, string> = {};\n if (files != null && files.length > 0) {\n if (this.isFlux2Model) {\n // Flux-2 models use input_image, input_image_2, input_image_3, etc.\n for (\n let i = 0;\n i < Math.min(files.length, MAX_FLUX_2_INPUT_IMAGES);\n i++\n ) {\n const key = i === 0 ? 'input_image' : `input_image_${i + 1}`;\n imageInputs[key] = convertImageModelFileToDataUri(files[i]);\n }\n if (files.length > MAX_FLUX_2_INPUT_IMAGES) {\n warnings.push({\n type: 'other',\n message: `Flux-2 models support up to ${MAX_FLUX_2_INPUT_IMAGES} input images. Additional images are ignored.`,\n });\n }\n } else {\n // Other models use single 'image' parameter\n imageInputs = { image: convertImageModelFileToDataUri(files[0]) };\n if (files.length > 1) {\n warnings.push({\n type: 'other',\n message:\n 'This Replicate model only supports a single input image. Additional images are ignored.',\n });\n }\n }\n }\n\n // Handle mask input (not supported by Flux-2 models)\n let maskInput: string | undefined;\n if (mask != null) {\n if (this.isFlux2Model) {\n warnings.push({\n type: 'other',\n message:\n 'Flux-2 models do not support mask input. The mask will be ignored.',\n });\n } else {\n maskInput = convertImageModelFileToDataUri(mask);\n }\n }\n\n // Extract maxWaitTimeInSeconds from provider options and prepare the rest for the request body\n const { maxWaitTimeInSeconds, ...inputOptions } = replicateOptions ?? {};\n\n // Build the prefer header based on maxWaitTimeInSeconds:\n // - undefined/null: use default sync wait (prefer: wait)\n // - positive number: use custom wait duration (prefer: wait=N)\n const preferHeader: Record<string, string> =\n maxWaitTimeInSeconds != null\n ? { prefer: `wait=${maxWaitTimeInSeconds}` }\n : { prefer: 'wait' };\n\n const {\n value: { output },\n responseHeaders,\n } = await postJsonToApi({\n url:\n // different endpoints for versioned vs unversioned models:\n version != null\n ? `${this.config.baseURL}/predictions`\n : `${this.config.baseURL}/models/${modelId}/predictions`,\n\n headers: combineHeaders(\n await resolve(this.config.headers),\n headers,\n preferHeader,\n ),\n\n body: {\n input: {\n prompt,\n aspect_ratio: aspectRatio,\n size,\n seed,\n num_outputs: n,\n ...imageInputs,\n ...(maskInput != null ? { mask: maskInput } : {}),\n ...inputOptions,\n },\n // for versioned models, include the version in the body:\n ...(version != null ? { version } : {}),\n },\n\n successfulResponseHandler: createJsonResponseHandler(\n replicateImageResponseSchema,\n ),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n\n // download the images:\n const outputArray = Array.isArray(output) ? output : [output];\n const images = await Promise.all(\n outputArray.map(async url => {\n const { value: image } = await getFromApi({\n url,\n successfulResponseHandler: createBinaryResponseHandler(),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n return image;\n }),\n );\n\n return {\n images,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n };\n }\n}\n\nconst replicateImageResponseSchema = z.object({\n output: z.union([z.array(z.string()), z.string()]),\n});\n\n/**\n * Provider options schema for Replicate image generation.\n *\n * Note: Different Replicate models support different parameters.\n * This schema includes common parameters, but you can pass any\n * model-specific parameters through the passthrough.\n */\nexport const replicateImageProviderOptionsSchema = lazySchema(() =>\n zodSchema(\n z\n .object({\n /**\n * Maximum time in seconds to wait for the prediction to complete in sync mode.\n * By default, Replicate uses sync mode with a 60-second timeout.\n *\n * - When not specified: Uses default 60-second sync wait (`prefer: wait`)\n * - When set to a positive number: Uses that duration (`prefer: wait=N`)\n */\n maxWaitTimeInSeconds: z.number().positive().nullish(),\n\n /**\n * Guidance scale for classifier-free guidance.\n * Higher values make the output more closely match the prompt.\n */\n guidance_scale: z.number().nullish(),\n\n /**\n * Number of denoising steps. More steps = higher quality but slower.\n */\n num_inference_steps: z.number().nullish(),\n\n /**\n * Negative prompt to guide what to avoid in the generation.\n */\n negative_prompt: z.string().nullish(),\n\n /**\n * Output image format.\n */\n output_format: z.enum(['png', 'jpg', 'webp']).nullish(),\n\n /**\n * Output image quality (1-100). Only applies to jpg and webp.\n */\n output_quality: z.number().min(1).max(100).nullish(),\n\n /**\n * Strength of the transformation for img2img (0-1).\n * Lower values keep more of the original image.\n */\n strength: z.number().min(0).max(1).nullish(),\n })\n .passthrough(),\n ),\n);\n\nexport type ReplicateImageProviderOptions = InferSchema<\n typeof replicateImageProviderOptionsSchema\n>;\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nconst replicateErrorSchema = z.object({\n detail: z.string().optional(),\n error: z.string().optional(),\n});\n\nexport const replicateFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: replicateErrorSchema,\n errorToMessage: error =>\n error.detail ?? error.error ?? 'Unknown Replicate error',\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":["import_provider_utils","import_provider_utils","import_v4"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/replicate-provider.ts","../src/replicate-image-model.ts","../src/replicate-error.ts","../src/version.ts"],"sourcesContent":["export { createReplicate, replicate } from './replicate-provider';\nexport type {\n ReplicateProvider,\n ReplicateProviderSettings,\n} from './replicate-provider';\nexport type { ReplicateImageProviderOptions } from './replicate-image-model';\nexport { VERSION } from './version';\n","import { NoSuchModelError, ProviderV3 } from '@ai-sdk/provider';\nimport type { FetchFunction } from '@ai-sdk/provider-utils';\nimport { loadApiKey, withUserAgentSuffix } from '@ai-sdk/provider-utils';\nimport { ReplicateImageModel } from './replicate-image-model';\nimport { ReplicateImageModelId } from './replicate-image-settings';\nimport { VERSION } from './version';\n\nexport interface ReplicateProviderSettings {\n /**\nAPI token that is being send using the `Authorization` header.\nIt defaults to the `REPLICATE_API_TOKEN` environment variable.\n */\n apiToken?: string;\n\n /**\nUse a different URL prefix for API calls, e.g. to use proxy servers.\nThe default prefix is `https://api.replicate.com/v1`.\n */\n baseURL?: string;\n\n /**\nCustom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface ReplicateProvider extends ProviderV3 {\n /**\n * Creates a Replicate image generation model.\n */\n image(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * Creates a Replicate image generation model.\n */\n imageModel(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\n/**\n * Create a Replicate provider instance.\n */\nexport function createReplicate(\n options: ReplicateProviderSettings = {},\n): ReplicateProvider {\n const createImageModel = (modelId: ReplicateImageModelId) =>\n new ReplicateImageModel(modelId, {\n provider: 'replicate',\n baseURL: options.baseURL ?? 'https://api.replicate.com/v1',\n headers: withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiToken,\n environmentVariableName: 'REPLICATE_API_TOKEN',\n description: 'Replicate',\n })}`,\n ...options.headers,\n },\n `ai-sdk/replicate/${VERSION}`,\n ),\n fetch: options.fetch,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v3' as const,\n image: createImageModel,\n imageModel: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\n/**\n * Default Replicate provider instance.\n */\nexport const replicate = createReplicate();\n","import type { ImageModelV3, SharedV3Warning } from '@ai-sdk/provider';\nimport type { Resolvable } from '@ai-sdk/provider-utils';\nimport {\n combineHeaders,\n convertImageModelFileToDataUri,\n createBinaryResponseHandler,\n createJsonResponseHandler,\n FetchFunction,\n getFromApi,\n InferSchema,\n lazySchema,\n parseProviderOptions,\n postJsonToApi,\n resolve,\n zodSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { replicateFailedResponseHandler } from './replicate-error';\nimport { ReplicateImageModelId } from './replicate-image-settings';\n\ninterface ReplicateImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: Resolvable<Record<string, string | undefined>>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\n// Flux-2 models support up to 8 input images with input_image, input_image_2, etc.\nconst FLUX_2_MODEL_PATTERN = /^black-forest-labs\\/flux-2-/;\nconst MAX_FLUX_2_INPUT_IMAGES = 8;\n\nexport class ReplicateImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3';\n\n get maxImagesPerCall(): number {\n // Flux-2 models support up to 8 input images\n return this.isFlux2Model ? MAX_FLUX_2_INPUT_IMAGES : 1;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private get isFlux2Model(): boolean {\n return FLUX_2_MODEL_PATTERN.test(this.modelId);\n }\n\n constructor(\n readonly modelId: ReplicateImageModelId,\n private readonly config: ReplicateImageModelConfig,\n ) {}\n\n async doGenerate({\n prompt,\n n,\n aspectRatio,\n size,\n seed,\n providerOptions,\n headers,\n abortSignal,\n files,\n mask,\n }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV3['doGenerate']>>\n > {\n const warnings: Array<SharedV3Warning> = [];\n\n const [modelId, version] = this.modelId.split(':');\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n // Parse provider options\n const replicateOptions = await parseProviderOptions({\n provider: 'replicate',\n providerOptions,\n schema: replicateImageProviderOptionsSchema,\n });\n\n // Handle image input from files\n let imageInputs: Record<string, string> = {};\n if (files != null && files.length > 0) {\n if (this.isFlux2Model) {\n // Flux-2 models use input_image, input_image_2, input_image_3, etc.\n for (\n let i = 0;\n i < Math.min(files.length, MAX_FLUX_2_INPUT_IMAGES);\n i++\n ) {\n const key = i === 0 ? 'input_image' : `input_image_${i + 1}`;\n imageInputs[key] = convertImageModelFileToDataUri(files[i]);\n }\n if (files.length > MAX_FLUX_2_INPUT_IMAGES) {\n warnings.push({\n type: 'other',\n message: `Flux-2 models support up to ${MAX_FLUX_2_INPUT_IMAGES} input images. Additional images are ignored.`,\n });\n }\n } else {\n // Other models use single 'image' parameter\n imageInputs = { image: convertImageModelFileToDataUri(files[0]) };\n if (files.length > 1) {\n warnings.push({\n type: 'other',\n message:\n 'This Replicate model only supports a single input image. Additional images are ignored.',\n });\n }\n }\n }\n\n // Handle mask input (not supported by Flux-2 models)\n let maskInput: string | undefined;\n if (mask != null) {\n if (this.isFlux2Model) {\n warnings.push({\n type: 'other',\n message:\n 'Flux-2 models do not support mask input. The mask will be ignored.',\n });\n } else {\n maskInput = convertImageModelFileToDataUri(mask);\n }\n }\n\n // Extract maxWaitTimeInSeconds from provider options and prepare the rest for the request body\n const { maxWaitTimeInSeconds, ...inputOptions } = replicateOptions ?? {};\n\n // Build the prefer header based on maxWaitTimeInSeconds:\n // - undefined/null: use default sync wait (prefer: wait)\n // - positive number: use custom wait duration (prefer: wait=N)\n const preferHeader: Record<string, string> =\n maxWaitTimeInSeconds != null\n ? { prefer: `wait=${maxWaitTimeInSeconds}` }\n : { prefer: 'wait' };\n\n const {\n value: { output },\n responseHeaders,\n } = await postJsonToApi({\n url:\n // different endpoints for versioned vs unversioned models:\n version != null\n ? `${this.config.baseURL}/predictions`\n : `${this.config.baseURL}/models/${modelId}/predictions`,\n\n headers: combineHeaders(\n await resolve(this.config.headers),\n headers,\n preferHeader,\n ),\n\n body: {\n input: {\n prompt,\n aspect_ratio: aspectRatio,\n size,\n seed,\n num_outputs: n,\n ...imageInputs,\n ...(maskInput != null ? { mask: maskInput } : {}),\n ...inputOptions,\n },\n // for versioned models, include the version in the body:\n ...(version != null ? { version } : {}),\n },\n\n successfulResponseHandler: createJsonResponseHandler(\n replicateImageResponseSchema,\n ),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n\n // download the images:\n const outputArray = Array.isArray(output) ? output : [output];\n const images = await Promise.all(\n outputArray.map(async url => {\n const { value: image } = await getFromApi({\n url,\n successfulResponseHandler: createBinaryResponseHandler(),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n return image;\n }),\n );\n\n return {\n images,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n };\n }\n}\n\nconst replicateImageResponseSchema = z.object({\n output: z.union([z.array(z.string()), z.string()]),\n});\n\n/**\n * Provider options schema for Replicate image generation.\n *\n * Note: Different Replicate models support different parameters.\n * This schema includes common parameters, but you can pass any\n * model-specific parameters through the passthrough.\n */\nexport const replicateImageProviderOptionsSchema = lazySchema(() =>\n zodSchema(\n z\n .object({\n /**\n * Maximum time in seconds to wait for the prediction to complete in sync mode.\n * By default, Replicate uses sync mode with a 60-second timeout.\n *\n * - When not specified: Uses default 60-second sync wait (`prefer: wait`)\n * - When set to a positive number: Uses that duration (`prefer: wait=N`)\n */\n maxWaitTimeInSeconds: z.number().positive().nullish(),\n\n /**\n * Guidance scale for classifier-free guidance.\n * Higher values make the output more closely match the prompt.\n */\n guidance_scale: z.number().nullish(),\n\n /**\n * Number of denoising steps. More steps = higher quality but slower.\n */\n num_inference_steps: z.number().nullish(),\n\n /**\n * Negative prompt to guide what to avoid in the generation.\n */\n negative_prompt: z.string().nullish(),\n\n /**\n * Output image format.\n */\n output_format: z.enum(['png', 'jpg', 'webp']).nullish(),\n\n /**\n * Output image quality (1-100). Only applies to jpg and webp.\n */\n output_quality: z.number().min(1).max(100).nullish(),\n\n /**\n * Strength of the transformation for img2img (0-1).\n * Lower values keep more of the original image.\n */\n strength: z.number().min(0).max(1).nullish(),\n })\n .passthrough(),\n ),\n);\n\nexport type ReplicateImageProviderOptions = InferSchema<\n typeof replicateImageProviderOptionsSchema\n>;\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nconst replicateErrorSchema = z.object({\n detail: z.string().optional(),\n error: z.string().optional(),\n});\n\nexport const replicateFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: replicateErrorSchema,\n errorToMessage: error =>\n error.detail ?? error.error ?? 'Unknown Replicate error',\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;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sBAA6C;AAE7C,IAAAA,yBAAgD;;;ACAhD,IAAAC,yBAaO;AACP,IAAAC,aAAkB;;;AChBlB,4BAA+C;AAC/C,gBAAkB;AAElB,IAAM,uBAAuB,YAAE,OAAO;AAAA,EACpC,QAAQ,YAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,OAAO,YAAE,OAAO,EAAE,SAAS;AAC7B,CAAC;AAEM,IAAM,qCAAiC,sDAA+B;AAAA,EAC3E,aAAa;AAAA,EACb,gBAAgB,WAAM;AAVxB;AAWI,6BAAM,WAAN,YAAgB,MAAM,UAAtB,YAA+B;AAAA;AACnC,CAAC;;;ADmBD,IAAM,uBAAuB;AAC7B,IAAM,0BAA0B;AAEzB,IAAM,sBAAN,MAAkD;AAAA,EAgBvD,YACW,SACQ,QACjB;AAFS;AACQ;AAjBnB,SAAS,uBAAuB;AAAA,EAkB7B;AAAA,EAhBH,IAAI,mBAA2B;AAE7B,WAAO,KAAK,eAAe,0BAA0B;AAAA,EACvD;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAY,eAAwB;AAClC,WAAO,qBAAqB,KAAK,KAAK,OAAO;AAAA,EAC/C;AAAA,EAOA,MAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAEE;AApEJ;AAqEI,UAAM,WAAmC,CAAC;AAE1C,UAAM,CAAC,SAAS,OAAO,IAAI,KAAK,QAAQ,MAAM,GAAG;AAEjD,UAAM,eAAc,sBAAK,OAAO,cAAZ,mBAAuB,gBAAvB,4CAA0C,oBAAI,KAAK;AAGvE,UAAM,mBAAmB,UAAM,6CAAqB;AAAA,MAClD,UAAU;AAAA,MACV;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAGD,QAAI,cAAsC,CAAC;AAC3C,QAAI,SAAS,QAAQ,MAAM,SAAS,GAAG;AACrC,UAAI,KAAK,cAAc;AAErB,iBACM,IAAI,GACR,IAAI,KAAK,IAAI,MAAM,QAAQ,uBAAuB,GAClD,KACA;AACA,gBAAM,MAAM,MAAM,IAAI,gBAAgB,eAAe,IAAI,CAAC;AAC1D,sBAAY,GAAG,QAAI,uDAA+B,MAAM,CAAC,CAAC;AAAA,QAC5D;AACA,YAAI,MAAM,SAAS,yBAAyB;AAC1C,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SAAS,+BAA+B,uBAAuB;AAAA,UACjE,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AAEL,sBAAc,EAAE,WAAO,uDAA+B,MAAM,CAAC,CAAC,EAAE;AAChE,YAAI,MAAM,SAAS,GAAG;AACpB,mBAAS,KAAK;AAAA,YACZ,MAAM;AAAA,YACN,SACE;AAAA,UACJ,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,QAAQ,MAAM;AAChB,UAAI,KAAK,cAAc;AACrB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,SACE;AAAA,QACJ,CAAC;AAAA,MACH,OAAO;AACL,wBAAY,uDAA+B,IAAI;AAAA,MACjD;AAAA,IACF;AAGA,UAAM,EAAE,sBAAsB,GAAG,aAAa,IAAI,8CAAoB,CAAC;AAKvE,UAAM,eACJ,wBAAwB,OACpB,EAAE,QAAQ,QAAQ,oBAAoB,GAAG,IACzC,EAAE,QAAQ,OAAO;AAEvB,UAAM;AAAA,MACJ,OAAO,EAAE,OAAO;AAAA,MAChB;AAAA,IACF,IAAI,UAAM,sCAAc;AAAA,MACtB;AAAA;AAAA,QAEE,WAAW,OACP,GAAG,KAAK,OAAO,OAAO,iBACtB,GAAG,KAAK,OAAO,OAAO,WAAW,OAAO;AAAA;AAAA,MAE9C,aAAS;AAAA,QACP,UAAM,gCAAQ,KAAK,OAAO,OAAO;AAAA,QACjC;AAAA,QACA;AAAA,MACF;AAAA,MAEA,MAAM;AAAA,QACJ,OAAO;AAAA,UACL;AAAA,UACA,cAAc;AAAA,UACd;AAAA,UACA;AAAA,UACA,aAAa;AAAA,UACb,GAAG;AAAA,UACH,GAAI,aAAa,OAAO,EAAE,MAAM,UAAU,IAAI,CAAC;AAAA,UAC/C,GAAG;AAAA,QACL;AAAA;AAAA,QAEA,GAAI,WAAW,OAAO,EAAE,QAAQ,IAAI,CAAC;AAAA,MACvC;AAAA,MAEA,+BAA2B;AAAA,QACzB;AAAA,MACF;AAAA,MACA,uBAAuB;AAAA,MACvB;AAAA,MACA,OAAO,KAAK,OAAO;AAAA,IACrB,CAAC;AAGD,UAAM,cAAc,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAC5D,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B,YAAY,IAAI,OAAM,QAAO;AAC3B,cAAM,EAAE,OAAO,MAAM,IAAI,UAAM,mCAAW;AAAA,UACxC;AAAA,UACA,+BAA2B,oDAA4B;AAAA,UACvD,uBAAuB;AAAA,UACvB;AAAA,UACA,OAAO,KAAK,OAAO;AAAA,QACrB,CAAC;AACD,eAAO;AAAA,MACT,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,UAAU;AAAA,QACR,WAAW;AAAA,QACX,SAAS,KAAK;AAAA,QACd,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAM,+BAA+B,aAAE,OAAO;AAAA,EAC5C,QAAQ,aAAE,MAAM,CAAC,aAAE,MAAM,aAAE,OAAO,CAAC,GAAG,aAAE,OAAO,CAAC,CAAC;AACnD,CAAC;AASM,IAAM,0CAAsC;AAAA,EAAW,UAC5D;AAAA,IACE,aACG,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQN,sBAAsB,aAAE,OAAO,EAAE,SAAS,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,MAMpD,gBAAgB,aAAE,OAAO,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA,MAKnC,qBAAqB,aAAE,OAAO,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA,MAKxC,iBAAiB,aAAE,OAAO,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA,MAKpC,eAAe,aAAE,KAAK,CAAC,OAAO,OAAO,MAAM,CAAC,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA,MAKtD,gBAAgB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,MAMnD,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,QAAQ;AAAA,IAC7C,CAAC,EACA,YAAY;AAAA,EACjB;AACF;;;AErQO,IAAM,UACX,OACI,WACA;;;AH+CC,SAAS,gBACd,UAAqC,CAAC,GACnB;AACnB,QAAM,mBAAmB,CAAC,YAAgC;AAvD5D;AAwDI,eAAI,oBAAoB,SAAS;AAAA,MAC/B,UAAU;AAAA,MACV,UAAS,aAAQ,YAAR,YAAmB;AAAA,MAC5B,aAAS;AAAA,QACP;AAAA,UACE,eAAe,cAAU,mCAAW;AAAA,YAClC,QAAQ,QAAQ;AAAA,YAChB,yBAAyB;AAAA,YACzB,aAAa;AAAA,UACf,CAAC,CAAC;AAAA,UACF,GAAG,QAAQ;AAAA,QACb;AAAA,QACA,oBAAoB,OAAO;AAAA,MAC7B;AAAA,MACA,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA;AAEH,QAAM,iBAAiB,CAAC,YAAoB;AAC1C,UAAM,IAAI,iCAAiB;AAAA,MACzB;AAAA,MACA,WAAW;AAAA,IACb,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,sBAAsB;AAAA,IACtB,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,eAAe,CAAC,YAAoB;AAClC,YAAM,IAAI,iCAAiB;AAAA,QACzB;AAAA,QACA,WAAW;AAAA,MACb,CAAC;AAAA,IACH;AAAA,IACA;AAAA,IACA,oBAAoB;AAAA,EACtB;AACF;AAKO,IAAM,YAAY,gBAAgB;","names":["import_provider_utils","import_provider_utils","import_v4"]}
package/dist/index.mjs CHANGED
@@ -210,7 +210,7 @@ var replicateImageProviderOptionsSchema = lazySchema(
210
210
  );
211
211
 
212
212
  // src/version.ts
213
- var VERSION = true ? "2.0.9" : "0.0.0-test";
213
+ var VERSION = true ? "2.0.11" : "0.0.0-test";
214
214
 
215
215
  // src/replicate-provider.ts
216
216
  function createReplicate(options = {}) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/replicate-provider.ts","../src/replicate-image-model.ts","../src/replicate-error.ts","../src/version.ts"],"sourcesContent":["import { NoSuchModelError, ProviderV3 } from '@ai-sdk/provider';\nimport type { FetchFunction } from '@ai-sdk/provider-utils';\nimport { loadApiKey, withUserAgentSuffix } from '@ai-sdk/provider-utils';\nimport { ReplicateImageModel } from './replicate-image-model';\nimport { ReplicateImageModelId } from './replicate-image-settings';\nimport { VERSION } from './version';\n\nexport interface ReplicateProviderSettings {\n /**\nAPI token that is being send using the `Authorization` header.\nIt defaults to the `REPLICATE_API_TOKEN` environment variable.\n */\n apiToken?: string;\n\n /**\nUse a different URL prefix for API calls, e.g. to use proxy servers.\nThe default prefix is `https://api.replicate.com/v1`.\n */\n baseURL?: string;\n\n /**\nCustom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface ReplicateProvider extends ProviderV3 {\n /**\n * Creates a Replicate image generation model.\n */\n image(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * Creates a Replicate image generation model.\n */\n imageModel(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\n/**\n * Create a Replicate provider instance.\n */\nexport function createReplicate(\n options: ReplicateProviderSettings = {},\n): ReplicateProvider {\n const createImageModel = (modelId: ReplicateImageModelId) =>\n new ReplicateImageModel(modelId, {\n provider: 'replicate',\n baseURL: options.baseURL ?? 'https://api.replicate.com/v1',\n headers: withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiToken,\n environmentVariableName: 'REPLICATE_API_TOKEN',\n description: 'Replicate',\n })}`,\n ...options.headers,\n },\n `ai-sdk/replicate/${VERSION}`,\n ),\n fetch: options.fetch,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v3' as const,\n image: createImageModel,\n imageModel: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\n/**\n * Default Replicate provider instance.\n */\nexport const replicate = createReplicate();\n","import type { ImageModelV3, SharedV3Warning } from '@ai-sdk/provider';\nimport type { Resolvable } from '@ai-sdk/provider-utils';\nimport {\n combineHeaders,\n convertImageModelFileToDataUri,\n createBinaryResponseHandler,\n createJsonResponseHandler,\n FetchFunction,\n getFromApi,\n InferSchema,\n lazySchema,\n parseProviderOptions,\n postJsonToApi,\n resolve,\n zodSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { replicateFailedResponseHandler } from './replicate-error';\nimport { ReplicateImageModelId } from './replicate-image-settings';\n\ninterface ReplicateImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: Resolvable<Record<string, string | undefined>>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\n// Flux-2 models support up to 8 input images with input_image, input_image_2, etc.\nconst FLUX_2_MODEL_PATTERN = /^black-forest-labs\\/flux-2-/;\nconst MAX_FLUX_2_INPUT_IMAGES = 8;\n\nexport class ReplicateImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3';\n\n get maxImagesPerCall(): number {\n // Flux-2 models support up to 8 input images\n return this.isFlux2Model ? MAX_FLUX_2_INPUT_IMAGES : 1;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private get isFlux2Model(): boolean {\n return FLUX_2_MODEL_PATTERN.test(this.modelId);\n }\n\n constructor(\n readonly modelId: ReplicateImageModelId,\n private readonly config: ReplicateImageModelConfig,\n ) {}\n\n async doGenerate({\n prompt,\n n,\n aspectRatio,\n size,\n seed,\n providerOptions,\n headers,\n abortSignal,\n files,\n mask,\n }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV3['doGenerate']>>\n > {\n const warnings: Array<SharedV3Warning> = [];\n\n const [modelId, version] = this.modelId.split(':');\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n // Parse provider options\n const replicateOptions = await parseProviderOptions({\n provider: 'replicate',\n providerOptions,\n schema: replicateImageProviderOptionsSchema,\n });\n\n // Handle image input from files\n let imageInputs: Record<string, string> = {};\n if (files != null && files.length > 0) {\n if (this.isFlux2Model) {\n // Flux-2 models use input_image, input_image_2, input_image_3, etc.\n for (\n let i = 0;\n i < Math.min(files.length, MAX_FLUX_2_INPUT_IMAGES);\n i++\n ) {\n const key = i === 0 ? 'input_image' : `input_image_${i + 1}`;\n imageInputs[key] = convertImageModelFileToDataUri(files[i]);\n }\n if (files.length > MAX_FLUX_2_INPUT_IMAGES) {\n warnings.push({\n type: 'other',\n message: `Flux-2 models support up to ${MAX_FLUX_2_INPUT_IMAGES} input images. Additional images are ignored.`,\n });\n }\n } else {\n // Other models use single 'image' parameter\n imageInputs = { image: convertImageModelFileToDataUri(files[0]) };\n if (files.length > 1) {\n warnings.push({\n type: 'other',\n message:\n 'This Replicate model only supports a single input image. Additional images are ignored.',\n });\n }\n }\n }\n\n // Handle mask input (not supported by Flux-2 models)\n let maskInput: string | undefined;\n if (mask != null) {\n if (this.isFlux2Model) {\n warnings.push({\n type: 'other',\n message:\n 'Flux-2 models do not support mask input. The mask will be ignored.',\n });\n } else {\n maskInput = convertImageModelFileToDataUri(mask);\n }\n }\n\n // Extract maxWaitTimeInSeconds from provider options and prepare the rest for the request body\n const { maxWaitTimeInSeconds, ...inputOptions } = replicateOptions ?? {};\n\n // Build the prefer header based on maxWaitTimeInSeconds:\n // - undefined/null: use default sync wait (prefer: wait)\n // - positive number: use custom wait duration (prefer: wait=N)\n const preferHeader: Record<string, string> =\n maxWaitTimeInSeconds != null\n ? { prefer: `wait=${maxWaitTimeInSeconds}` }\n : { prefer: 'wait' };\n\n const {\n value: { output },\n responseHeaders,\n } = await postJsonToApi({\n url:\n // different endpoints for versioned vs unversioned models:\n version != null\n ? `${this.config.baseURL}/predictions`\n : `${this.config.baseURL}/models/${modelId}/predictions`,\n\n headers: combineHeaders(\n await resolve(this.config.headers),\n headers,\n preferHeader,\n ),\n\n body: {\n input: {\n prompt,\n aspect_ratio: aspectRatio,\n size,\n seed,\n num_outputs: n,\n ...imageInputs,\n ...(maskInput != null ? { mask: maskInput } : {}),\n ...inputOptions,\n },\n // for versioned models, include the version in the body:\n ...(version != null ? { version } : {}),\n },\n\n successfulResponseHandler: createJsonResponseHandler(\n replicateImageResponseSchema,\n ),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n\n // download the images:\n const outputArray = Array.isArray(output) ? output : [output];\n const images = await Promise.all(\n outputArray.map(async url => {\n const { value: image } = await getFromApi({\n url,\n successfulResponseHandler: createBinaryResponseHandler(),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n return image;\n }),\n );\n\n return {\n images,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n };\n }\n}\n\nconst replicateImageResponseSchema = z.object({\n output: z.union([z.array(z.string()), z.string()]),\n});\n\n/**\n * Provider options schema for Replicate image generation.\n *\n * Note: Different Replicate models support different parameters.\n * This schema includes common parameters, but you can pass any\n * model-specific parameters through the passthrough.\n */\nexport const replicateImageProviderOptionsSchema = lazySchema(() =>\n zodSchema(\n z\n .object({\n /**\n * Maximum time in seconds to wait for the prediction to complete in sync mode.\n * By default, Replicate uses sync mode with a 60-second timeout.\n *\n * - When not specified: Uses default 60-second sync wait (`prefer: wait`)\n * - When set to a positive number: Uses that duration (`prefer: wait=N`)\n */\n maxWaitTimeInSeconds: z.number().positive().nullish(),\n\n /**\n * Guidance scale for classifier-free guidance.\n * Higher values make the output more closely match the prompt.\n */\n guidance_scale: z.number().nullish(),\n\n /**\n * Number of denoising steps. More steps = higher quality but slower.\n */\n num_inference_steps: z.number().nullish(),\n\n /**\n * Negative prompt to guide what to avoid in the generation.\n */\n negative_prompt: z.string().nullish(),\n\n /**\n * Output image format.\n */\n output_format: z.enum(['png', 'jpg', 'webp']).nullish(),\n\n /**\n * Output image quality (1-100). Only applies to jpg and webp.\n */\n output_quality: z.number().min(1).max(100).nullish(),\n\n /**\n * Strength of the transformation for img2img (0-1).\n * Lower values keep more of the original image.\n */\n strength: z.number().min(0).max(1).nullish(),\n })\n .passthrough(),\n ),\n);\n\nexport type ReplicateImageProviderOptions = InferSchema<\n typeof replicateImageProviderOptionsSchema\n>;\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nconst replicateErrorSchema = z.object({\n detail: z.string().optional(),\n error: z.string().optional(),\n});\n\nexport const replicateFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: replicateErrorSchema,\n errorToMessage: error =>\n error.detail ?? error.error ?? 'Unknown Replicate error',\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"]}
1
+ {"version":3,"sources":["../src/replicate-provider.ts","../src/replicate-image-model.ts","../src/replicate-error.ts","../src/version.ts"],"sourcesContent":["import { NoSuchModelError, ProviderV3 } from '@ai-sdk/provider';\nimport type { FetchFunction } from '@ai-sdk/provider-utils';\nimport { loadApiKey, withUserAgentSuffix } from '@ai-sdk/provider-utils';\nimport { ReplicateImageModel } from './replicate-image-model';\nimport { ReplicateImageModelId } from './replicate-image-settings';\nimport { VERSION } from './version';\n\nexport interface ReplicateProviderSettings {\n /**\nAPI token that is being send using the `Authorization` header.\nIt defaults to the `REPLICATE_API_TOKEN` environment variable.\n */\n apiToken?: string;\n\n /**\nUse a different URL prefix for API calls, e.g. to use proxy servers.\nThe default prefix is `https://api.replicate.com/v1`.\n */\n baseURL?: string;\n\n /**\nCustom headers to include in the requests.\n */\n headers?: Record<string, string>;\n\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n */\n fetch?: FetchFunction;\n}\n\nexport interface ReplicateProvider extends ProviderV3 {\n /**\n * Creates a Replicate image generation model.\n */\n image(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * Creates a Replicate image generation model.\n */\n imageModel(modelId: ReplicateImageModelId): ReplicateImageModel;\n\n /**\n * @deprecated Use `embeddingModel` instead.\n */\n textEmbeddingModel(modelId: string): never;\n}\n\n/**\n * Create a Replicate provider instance.\n */\nexport function createReplicate(\n options: ReplicateProviderSettings = {},\n): ReplicateProvider {\n const createImageModel = (modelId: ReplicateImageModelId) =>\n new ReplicateImageModel(modelId, {\n provider: 'replicate',\n baseURL: options.baseURL ?? 'https://api.replicate.com/v1',\n headers: withUserAgentSuffix(\n {\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiToken,\n environmentVariableName: 'REPLICATE_API_TOKEN',\n description: 'Replicate',\n })}`,\n ...options.headers,\n },\n `ai-sdk/replicate/${VERSION}`,\n ),\n fetch: options.fetch,\n });\n\n const embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'embeddingModel',\n });\n };\n\n return {\n specificationVersion: 'v3' as const,\n image: createImageModel,\n imageModel: createImageModel,\n languageModel: (modelId: string) => {\n throw new NoSuchModelError({\n modelId,\n modelType: 'languageModel',\n });\n },\n embeddingModel,\n textEmbeddingModel: embeddingModel,\n };\n}\n\n/**\n * Default Replicate provider instance.\n */\nexport const replicate = createReplicate();\n","import type { ImageModelV3, SharedV3Warning } from '@ai-sdk/provider';\nimport type { Resolvable } from '@ai-sdk/provider-utils';\nimport {\n combineHeaders,\n convertImageModelFileToDataUri,\n createBinaryResponseHandler,\n createJsonResponseHandler,\n FetchFunction,\n getFromApi,\n InferSchema,\n lazySchema,\n parseProviderOptions,\n postJsonToApi,\n resolve,\n zodSchema,\n} from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\nimport { replicateFailedResponseHandler } from './replicate-error';\nimport { ReplicateImageModelId } from './replicate-image-settings';\n\ninterface ReplicateImageModelConfig {\n provider: string;\n baseURL: string;\n headers?: Resolvable<Record<string, string | undefined>>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\n// Flux-2 models support up to 8 input images with input_image, input_image_2, etc.\nconst FLUX_2_MODEL_PATTERN = /^black-forest-labs\\/flux-2-/;\nconst MAX_FLUX_2_INPUT_IMAGES = 8;\n\nexport class ReplicateImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3';\n\n get maxImagesPerCall(): number {\n // Flux-2 models support up to 8 input images\n return this.isFlux2Model ? MAX_FLUX_2_INPUT_IMAGES : 1;\n }\n\n get provider(): string {\n return this.config.provider;\n }\n\n private get isFlux2Model(): boolean {\n return FLUX_2_MODEL_PATTERN.test(this.modelId);\n }\n\n constructor(\n readonly modelId: ReplicateImageModelId,\n private readonly config: ReplicateImageModelConfig,\n ) {}\n\n async doGenerate({\n prompt,\n n,\n aspectRatio,\n size,\n seed,\n providerOptions,\n headers,\n abortSignal,\n files,\n mask,\n }: Parameters<ImageModelV3['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV3['doGenerate']>>\n > {\n const warnings: Array<SharedV3Warning> = [];\n\n const [modelId, version] = this.modelId.split(':');\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n // Parse provider options\n const replicateOptions = await parseProviderOptions({\n provider: 'replicate',\n providerOptions,\n schema: replicateImageProviderOptionsSchema,\n });\n\n // Handle image input from files\n let imageInputs: Record<string, string> = {};\n if (files != null && files.length > 0) {\n if (this.isFlux2Model) {\n // Flux-2 models use input_image, input_image_2, input_image_3, etc.\n for (\n let i = 0;\n i < Math.min(files.length, MAX_FLUX_2_INPUT_IMAGES);\n i++\n ) {\n const key = i === 0 ? 'input_image' : `input_image_${i + 1}`;\n imageInputs[key] = convertImageModelFileToDataUri(files[i]);\n }\n if (files.length > MAX_FLUX_2_INPUT_IMAGES) {\n warnings.push({\n type: 'other',\n message: `Flux-2 models support up to ${MAX_FLUX_2_INPUT_IMAGES} input images. Additional images are ignored.`,\n });\n }\n } else {\n // Other models use single 'image' parameter\n imageInputs = { image: convertImageModelFileToDataUri(files[0]) };\n if (files.length > 1) {\n warnings.push({\n type: 'other',\n message:\n 'This Replicate model only supports a single input image. Additional images are ignored.',\n });\n }\n }\n }\n\n // Handle mask input (not supported by Flux-2 models)\n let maskInput: string | undefined;\n if (mask != null) {\n if (this.isFlux2Model) {\n warnings.push({\n type: 'other',\n message:\n 'Flux-2 models do not support mask input. The mask will be ignored.',\n });\n } else {\n maskInput = convertImageModelFileToDataUri(mask);\n }\n }\n\n // Extract maxWaitTimeInSeconds from provider options and prepare the rest for the request body\n const { maxWaitTimeInSeconds, ...inputOptions } = replicateOptions ?? {};\n\n // Build the prefer header based on maxWaitTimeInSeconds:\n // - undefined/null: use default sync wait (prefer: wait)\n // - positive number: use custom wait duration (prefer: wait=N)\n const preferHeader: Record<string, string> =\n maxWaitTimeInSeconds != null\n ? { prefer: `wait=${maxWaitTimeInSeconds}` }\n : { prefer: 'wait' };\n\n const {\n value: { output },\n responseHeaders,\n } = await postJsonToApi({\n url:\n // different endpoints for versioned vs unversioned models:\n version != null\n ? `${this.config.baseURL}/predictions`\n : `${this.config.baseURL}/models/${modelId}/predictions`,\n\n headers: combineHeaders(\n await resolve(this.config.headers),\n headers,\n preferHeader,\n ),\n\n body: {\n input: {\n prompt,\n aspect_ratio: aspectRatio,\n size,\n seed,\n num_outputs: n,\n ...imageInputs,\n ...(maskInput != null ? { mask: maskInput } : {}),\n ...inputOptions,\n },\n // for versioned models, include the version in the body:\n ...(version != null ? { version } : {}),\n },\n\n successfulResponseHandler: createJsonResponseHandler(\n replicateImageResponseSchema,\n ),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n\n // download the images:\n const outputArray = Array.isArray(output) ? output : [output];\n const images = await Promise.all(\n outputArray.map(async url => {\n const { value: image } = await getFromApi({\n url,\n successfulResponseHandler: createBinaryResponseHandler(),\n failedResponseHandler: replicateFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n return image;\n }),\n );\n\n return {\n images,\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n };\n }\n}\n\nconst replicateImageResponseSchema = z.object({\n output: z.union([z.array(z.string()), z.string()]),\n});\n\n/**\n * Provider options schema for Replicate image generation.\n *\n * Note: Different Replicate models support different parameters.\n * This schema includes common parameters, but you can pass any\n * model-specific parameters through the passthrough.\n */\nexport const replicateImageProviderOptionsSchema = lazySchema(() =>\n zodSchema(\n z\n .object({\n /**\n * Maximum time in seconds to wait for the prediction to complete in sync mode.\n * By default, Replicate uses sync mode with a 60-second timeout.\n *\n * - When not specified: Uses default 60-second sync wait (`prefer: wait`)\n * - When set to a positive number: Uses that duration (`prefer: wait=N`)\n */\n maxWaitTimeInSeconds: z.number().positive().nullish(),\n\n /**\n * Guidance scale for classifier-free guidance.\n * Higher values make the output more closely match the prompt.\n */\n guidance_scale: z.number().nullish(),\n\n /**\n * Number of denoising steps. More steps = higher quality but slower.\n */\n num_inference_steps: z.number().nullish(),\n\n /**\n * Negative prompt to guide what to avoid in the generation.\n */\n negative_prompt: z.string().nullish(),\n\n /**\n * Output image format.\n */\n output_format: z.enum(['png', 'jpg', 'webp']).nullish(),\n\n /**\n * Output image quality (1-100). Only applies to jpg and webp.\n */\n output_quality: z.number().min(1).max(100).nullish(),\n\n /**\n * Strength of the transformation for img2img (0-1).\n * Lower values keep more of the original image.\n */\n strength: z.number().min(0).max(1).nullish(),\n })\n .passthrough(),\n ),\n);\n\nexport type ReplicateImageProviderOptions = InferSchema<\n typeof replicateImageProviderOptionsSchema\n>;\n","import { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\nimport { z } from 'zod/v4';\n\nconst replicateErrorSchema = z.object({\n detail: z.string().optional(),\n error: z.string().optional(),\n});\n\nexport const replicateFailedResponseHandler = createJsonErrorResponseHandler({\n errorSchema: replicateErrorSchema,\n errorToMessage: error =>\n error.detail ?? error.error ?? 'Unknown Replicate error',\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"]}
@@ -0,0 +1,241 @@
1
+ ---
2
+ title: Replicate
3
+ description: Learn how to use Replicate models with the AI SDK.
4
+ ---
5
+
6
+ # Replicate Provider
7
+
8
+ [Replicate](https://replicate.com/) is a platform for running open-source AI models.
9
+ It is a popular choice for running image generation models.
10
+
11
+ ## Setup
12
+
13
+ The Replicate provider is available via the `@ai-sdk/replicate` module. You can install it with
14
+
15
+ <Tabs items={['pnpm', 'npm', 'yarn', 'bun']}>
16
+ <Tab>
17
+ <Snippet text="pnpm add @ai-sdk/replicate" dark />
18
+ </Tab>
19
+ <Tab>
20
+ <Snippet text="npm install @ai-sdk/replicate" dark />
21
+ </Tab>
22
+ <Tab>
23
+ <Snippet text="yarn add @ai-sdk/replicate" dark />
24
+ </Tab>
25
+
26
+ <Tab>
27
+ <Snippet text="bun add @ai-sdk/replicate" dark />
28
+ </Tab>
29
+ </Tabs>
30
+
31
+ ## Provider Instance
32
+
33
+ You can import the default provider instance `replicate` from `@ai-sdk/replicate`:
34
+
35
+ ```ts
36
+ import { replicate } from '@ai-sdk/replicate';
37
+ ```
38
+
39
+ If you need a customized setup, you can import `createReplicate` from `@ai-sdk/replicate`
40
+ and create a provider instance with your settings:
41
+
42
+ ```ts
43
+ import { createReplicate } from '@ai-sdk/replicate';
44
+
45
+ const replicate = createReplicate({
46
+ apiToken: process.env.REPLICATE_API_TOKEN ?? '',
47
+ });
48
+ ```
49
+
50
+ You can use the following optional settings to customize the Replicate provider instance:
51
+
52
+ - **baseURL** _string_
53
+
54
+ Use a different URL prefix for API calls, e.g. to use proxy servers.
55
+ The default prefix is `https://api.replicate.com/v1`.
56
+
57
+ - **apiToken** _string_
58
+
59
+ API token that is being sent using the `Authorization` header. It defaults to
60
+ the `REPLICATE_API_TOKEN` environment variable.
61
+
62
+ - **headers** _Record&lt;string,string&gt;_
63
+
64
+ Custom headers to include in the requests.
65
+
66
+ - **fetch** _(input: RequestInfo, init?: RequestInit) => Promise&lt;Response&gt;_
67
+
68
+ Custom [fetch](https://developer.mozilla.org/en-US/docs/Web/API/fetch) implementation.
69
+
70
+ ## Image Models
71
+
72
+ You can create Replicate image models using the `.image()` factory method.
73
+ For more on image generation with the AI SDK see [generateImage()](/docs/reference/ai-sdk-core/generate-image).
74
+
75
+ <Note>
76
+ Model support for `size` and other parameters varies by model. Check the
77
+ model's documentation on [Replicate](https://replicate.com/explore) for
78
+ supported options and additional parameters that can be passed via
79
+ `providerOptions.replicate`.
80
+ </Note>
81
+
82
+ ### Supported Image Models
83
+
84
+ The following image models are currently supported by the Replicate provider:
85
+
86
+ - [black-forest-labs/flux-1.1-pro-ultra](https://replicate.com/black-forest-labs/flux-1.1-pro-ultra)
87
+ - [black-forest-labs/flux-1.1-pro](https://replicate.com/black-forest-labs/flux-1.1-pro)
88
+ - [black-forest-labs/flux-dev](https://replicate.com/black-forest-labs/flux-dev)
89
+ - [black-forest-labs/flux-pro](https://replicate.com/black-forest-labs/flux-pro)
90
+ - [black-forest-labs/flux-schnell](https://replicate.com/black-forest-labs/flux-schnell)
91
+ - [bytedance/sdxl-lightning-4step](https://replicate.com/bytedance/sdxl-lightning-4step)
92
+ - [fofr/aura-flow](https://replicate.com/fofr/aura-flow)
93
+ - [fofr/latent-consistency-model](https://replicate.com/fofr/latent-consistency-model)
94
+ - [fofr/realvisxl-v3-multi-controlnet-lora](https://replicate.com/fofr/realvisxl-v3-multi-controlnet-lora)
95
+ - [fofr/sdxl-emoji](https://replicate.com/fofr/sdxl-emoji)
96
+ - [fofr/sdxl-multi-controlnet-lora](https://replicate.com/fofr/sdxl-multi-controlnet-lora)
97
+ - [ideogram-ai/ideogram-v2-turbo](https://replicate.com/ideogram-ai/ideogram-v2-turbo)
98
+ - [ideogram-ai/ideogram-v2](https://replicate.com/ideogram-ai/ideogram-v2)
99
+ - [lucataco/dreamshaper-xl-turbo](https://replicate.com/lucataco/dreamshaper-xl-turbo)
100
+ - [lucataco/open-dalle-v1.1](https://replicate.com/lucataco/open-dalle-v1.1)
101
+ - [lucataco/realvisxl-v2.0](https://replicate.com/lucataco/realvisxl-v2.0)
102
+ - [lucataco/realvisxl2-lcm](https://replicate.com/lucataco/realvisxl2-lcm)
103
+ - [luma/photon-flash](https://replicate.com/luma/photon-flash)
104
+ - [luma/photon](https://replicate.com/luma/photon)
105
+ - [nvidia/sana](https://replicate.com/nvidia/sana)
106
+ - [playgroundai/playground-v2.5-1024px-aesthetic](https://replicate.com/playgroundai/playground-v2.5-1024px-aesthetic)
107
+ - [recraft-ai/recraft-v3-svg](https://replicate.com/recraft-ai/recraft-v3-svg)
108
+ - [recraft-ai/recraft-v3](https://replicate.com/recraft-ai/recraft-v3)
109
+ - [stability-ai/stable-diffusion-3.5-large-turbo](https://replicate.com/stability-ai/stable-diffusion-3.5-large-turbo)
110
+ - [stability-ai/stable-diffusion-3.5-large](https://replicate.com/stability-ai/stable-diffusion-3.5-large)
111
+ - [stability-ai/stable-diffusion-3.5-medium](https://replicate.com/stability-ai/stable-diffusion-3.5-medium)
112
+ - [tstramer/material-diffusion](https://replicate.com/tstramer/material-diffusion)
113
+
114
+ You can also use [versioned models](https://replicate.com/docs/topics/models/versions).
115
+ The id for versioned models is the Replicate model id followed by a colon and the version ID (`$modelId:$versionId`), e.g.
116
+ `bytedance/sdxl-lightning-4step:5599ed30703defd1d160a25a63321b4dec97101d98b4674bcc56e41f62f35637`.
117
+
118
+ <Note>
119
+ You can also pass any available Replicate model ID as a string if needed.
120
+ </Note>
121
+
122
+ ### Basic Usage
123
+
124
+ ```ts
125
+ import { replicate } from '@ai-sdk/replicate';
126
+ import { generateImage } from 'ai';
127
+ import { writeFile } from 'node:fs/promises';
128
+
129
+ const { image } = await generateImage({
130
+ model: replicate.image('black-forest-labs/flux-schnell'),
131
+ prompt: 'The Loch Ness Monster getting a manicure',
132
+ aspectRatio: '16:9',
133
+ });
134
+
135
+ await writeFile('image.webp', image.uint8Array);
136
+
137
+ console.log('Image saved as image.webp');
138
+ ```
139
+
140
+ ### Model-specific options
141
+
142
+ ```ts highlight="9-11"
143
+ import { replicate } from '@ai-sdk/replicate';
144
+ import { generateImage } from 'ai';
145
+
146
+ const { image } = await generateImage({
147
+ model: replicate.image('recraft-ai/recraft-v3'),
148
+ prompt: 'The Loch Ness Monster getting a manicure',
149
+ size: '1365x1024',
150
+ providerOptions: {
151
+ replicate: {
152
+ style: 'realistic_image',
153
+ },
154
+ },
155
+ });
156
+ ```
157
+
158
+ ### Versioned Models
159
+
160
+ ```ts
161
+ import { replicate } from '@ai-sdk/replicate';
162
+ import { generateImage } from 'ai';
163
+
164
+ const { image } = await generateImage({
165
+ model: replicate.image(
166
+ 'bytedance/sdxl-lightning-4step:5599ed30703defd1d160a25a63321b4dec97101d98b4674bcc56e41f62f35637',
167
+ ),
168
+ prompt: 'The Loch Ness Monster getting a manicure',
169
+ });
170
+ ```
171
+
172
+ ### Image Editing
173
+
174
+ Replicate supports image editing through various models. Pass input images via `prompt.images` to transform or edit existing images.
175
+
176
+ #### Basic Image Editing
177
+
178
+ Transform an existing image using text prompts:
179
+
180
+ ```ts
181
+ const imageBuffer = readFileSync('./input-image.png');
182
+
183
+ const { images } = await generateImage({
184
+ model: replicate.image('black-forest-labs/flux-kontext-dev'),
185
+ prompt: {
186
+ text: 'Turn the cat into a golden retriever dog',
187
+ images: [imageBuffer],
188
+ },
189
+ providerOptions: {
190
+ replicate: {
191
+ guidance_scale: 7.5,
192
+ num_inference_steps: 30,
193
+ },
194
+ },
195
+ });
196
+ ```
197
+
198
+ #### Inpainting with Mask
199
+
200
+ Edit specific parts of an image using a mask. For FLUX Fill models, white areas in the mask indicate where the image should be edited:
201
+
202
+ ```ts
203
+ const image = readFileSync('./input-image.png');
204
+ const mask = readFileSync('./mask.png'); // White = inpaint, black = keep
205
+
206
+ const { images } = await generateImage({
207
+ model: replicate.image('black-forest-labs/flux-fill-pro'),
208
+ prompt: {
209
+ text: 'A sunlit indoor lounge area with a pool containing a flamingo',
210
+ images: [image],
211
+ mask: mask,
212
+ },
213
+ providerOptions: {
214
+ replicate: {
215
+ guidance_scale: 7.5,
216
+ num_inference_steps: 30,
217
+ },
218
+ },
219
+ });
220
+ ```
221
+
222
+ <Note>
223
+ Input images can be provided as `Buffer`, `ArrayBuffer`, `Uint8Array`, or
224
+ base64-encoded strings. Different Replicate models have different parameter
225
+ names and capabilities — check the model's documentation on
226
+ [Replicate](https://replicate.com/explore) for details.
227
+ </Note>
228
+
229
+ ### Provider Options
230
+
231
+ Common provider options for image generation:
232
+
233
+ - **maxWaitTimeInSeconds** _number_ - Maximum time in seconds to wait for the prediction to complete in sync mode. By default, Replicate uses [sync mode](https://replicate.com/docs/topics/predictions/create-a-prediction#timeout-duration) with a 60-second timeout. Set to a positive number to use a custom duration (e.g., `120` for 2 minutes). When not specified, uses the default 60-second wait.
234
+ - **guidance_scale** _number_ - Guidance scale for classifier-free guidance. Higher values make the output more closely match the prompt.
235
+ - **num_inference_steps** _number_ - Number of denoising steps. More steps = higher quality but slower.
236
+ - **negative_prompt** _string_ - Negative prompt to guide what to avoid in the generation.
237
+ - **output_format** _'png' | 'jpg' | 'webp'_ - Output image format.
238
+ - **output_quality** _number (1-100)_ - Output image quality. Only applies to jpg and webp.
239
+ - **strength** _number (0-1)_ - Strength of the transformation for img2img. Lower values keep more of the original image.
240
+
241
+ For more details, see the [Replicate models page](https://replicate.com/explore).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/replicate",
3
- "version": "2.0.9",
3
+ "version": "2.0.11",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",
@@ -8,10 +8,18 @@
8
8
  "types": "./dist/index.d.ts",
9
9
  "files": [
10
10
  "dist/**/*",
11
+ "docs/**/*",
11
12
  "src",
13
+ "!src/**/*.test.ts",
14
+ "!src/**/*.test-d.ts",
15
+ "!src/**/__snapshots__",
16
+ "!src/**/__fixtures__",
12
17
  "CHANGELOG.md",
13
18
  "README.md"
14
19
  ],
20
+ "directories": {
21
+ "doc": "./docs"
22
+ },
15
23
  "exports": {
16
24
  "./package.json": "./package.json",
17
25
  ".": {
@@ -21,15 +29,15 @@
21
29
  }
22
30
  },
23
31
  "dependencies": {
24
- "@ai-sdk/provider": "3.0.4",
25
- "@ai-sdk/provider-utils": "4.0.8"
32
+ "@ai-sdk/provider": "3.0.5",
33
+ "@ai-sdk/provider-utils": "4.0.9"
26
34
  },
27
35
  "devDependencies": {
28
36
  "@types/node": "20.17.24",
29
37
  "tsup": "^8",
30
38
  "typescript": "5.8.3",
31
39
  "zod": "3.25.76",
32
- "@ai-sdk/test-server": "1.0.2",
40
+ "@ai-sdk/test-server": "1.0.3",
33
41
  "@vercel/ai-tsconfig": "0.0.0"
34
42
  },
35
43
  "peerDependencies": {
@@ -55,7 +63,7 @@
55
63
  "scripts": {
56
64
  "build": "pnpm clean && tsup --tsconfig tsconfig.build.json",
57
65
  "build:watch": "pnpm clean && tsup --watch",
58
- "clean": "del-cli dist *.tsbuildinfo",
66
+ "clean": "del-cli dist docs *.tsbuildinfo",
59
67
  "lint": "eslint \"./**/*.ts*\"",
60
68
  "type-check": "tsc --build",
61
69
  "prettier-check": "prettier --check \"./**/*.ts*\"",
@@ -1,752 +0,0 @@
1
- import { createTestServer } from '@ai-sdk/test-server/with-vitest';
2
- import { createReplicate } from './replicate-provider';
3
- import { ReplicateImageModel } from './replicate-image-model';
4
- import { describe, it, expect, vi } from 'vitest';
5
-
6
- vi.mock('./version', () => ({
7
- VERSION: '0.0.0-test',
8
- }));
9
-
10
- const prompt = 'The Loch Ness monster getting a manicure';
11
-
12
- const provider = createReplicate({ apiToken: 'test-api-token' });
13
- const model = provider.image('black-forest-labs/flux-schnell');
14
-
15
- describe('doGenerate', () => {
16
- const testDate = new Date(2024, 0, 1);
17
- const server = createTestServer({
18
- 'https://api.replicate.com/*': {},
19
- 'https://replicate.delivery/*': {
20
- response: {
21
- type: 'binary',
22
- body: Buffer.from('test-binary-content'),
23
- },
24
- },
25
- });
26
-
27
- function prepareResponse({
28
- output = ['https://replicate.delivery/xezq/abc/out-0.webp'],
29
- }: { output?: string | Array<string> } = {}) {
30
- server.urls['https://api.replicate.com/*'].response = {
31
- type: 'json-value',
32
- body: {
33
- id: 's7x1e3dcmhrmc0cm8rbatcneec',
34
- model: 'black-forest-labs/flux-schnell',
35
- version: 'dp-4d0bcc010b3049749a251855f12800be',
36
- input: {
37
- num_outputs: 1,
38
- prompt: 'The Loch Ness Monster getting a manicure',
39
- },
40
- logs: '',
41
- output,
42
- data_removed: false,
43
- error: null,
44
- status: 'processing',
45
- created_at: '2025-01-08T13:24:38.692Z',
46
- urls: {
47
- cancel:
48
- 'https://api.replicate.com/v1/predictions/s7x1e3dcmhrmc0cm8rbatcneec/cancel',
49
- get: 'https://api.replicate.com/v1/predictions/s7x1e3dcmhrmc0cm8rbatcneec',
50
- stream:
51
- 'https://stream.replicate.com/v1/files/bcwr-3okdfv3o2wehstv5f2okyftwxy57hhypqsi6osiim5iaq5k7u24a',
52
- },
53
- },
54
- };
55
- }
56
-
57
- it('should pass the model and the settings', async () => {
58
- prepareResponse();
59
-
60
- await model.doGenerate({
61
- prompt,
62
- files: undefined,
63
- mask: undefined,
64
- n: 1,
65
- size: '1024x768',
66
- aspectRatio: '3:4',
67
- seed: 123,
68
- providerOptions: {
69
- replicate: {
70
- style: 'realistic_image',
71
- },
72
- other: {
73
- something: 'else',
74
- },
75
- },
76
- });
77
-
78
- expect(await server.calls[0].requestBodyJson).toStrictEqual({
79
- input: {
80
- prompt,
81
- num_outputs: 1,
82
- aspect_ratio: '3:4',
83
- size: '1024x768',
84
- seed: 123,
85
- style: 'realistic_image',
86
- },
87
- });
88
- });
89
-
90
- it('should call the correct url', async () => {
91
- prepareResponse();
92
-
93
- await model.doGenerate({
94
- prompt,
95
- files: undefined,
96
- mask: undefined,
97
- n: 1,
98
- size: undefined,
99
- aspectRatio: undefined,
100
- seed: undefined,
101
- providerOptions: {},
102
- });
103
-
104
- expect(server.calls[0].requestMethod).toStrictEqual('POST');
105
- expect(server.calls[0].requestUrl).toStrictEqual(
106
- 'https://api.replicate.com/v1/models/black-forest-labs/flux-schnell/predictions',
107
- );
108
- });
109
-
110
- it('should pass headers and set the prefer header', async () => {
111
- prepareResponse();
112
-
113
- const provider = createReplicate({
114
- apiToken: 'test-api-token',
115
- headers: {
116
- 'Custom-Provider-Header': 'provider-header-value',
117
- },
118
- });
119
-
120
- await provider.image('black-forest-labs/flux-schnell').doGenerate({
121
- prompt,
122
- files: undefined,
123
- mask: undefined,
124
- n: 1,
125
- size: undefined,
126
- aspectRatio: undefined,
127
- seed: undefined,
128
- providerOptions: {},
129
- headers: {
130
- 'Custom-Request-Header': 'request-header-value',
131
- },
132
- });
133
-
134
- expect(server.calls[0].requestHeaders).toStrictEqual({
135
- authorization: 'Bearer test-api-token',
136
- 'content-type': 'application/json',
137
- 'custom-provider-header': 'provider-header-value',
138
- 'custom-request-header': 'request-header-value',
139
- prefer: 'wait',
140
- });
141
-
142
- expect(server.calls[0].requestUserAgent).toContain(
143
- `ai-sdk/replicate/0.0.0-test`,
144
- );
145
- });
146
-
147
- it('should set custom wait time in prefer header when maxWaitTimeInSeconds is specified', async () => {
148
- prepareResponse();
149
-
150
- await model.doGenerate({
151
- prompt,
152
- files: undefined,
153
- mask: undefined,
154
- n: 1,
155
- size: undefined,
156
- aspectRatio: undefined,
157
- seed: undefined,
158
- providerOptions: {
159
- replicate: {
160
- maxWaitTimeInSeconds: 120,
161
- },
162
- },
163
- });
164
-
165
- expect(server.calls[0].requestHeaders.prefer).toBe('wait=120');
166
- });
167
-
168
- it('should not include maxWaitTimeInSeconds in request body', async () => {
169
- prepareResponse();
170
-
171
- await model.doGenerate({
172
- prompt,
173
- files: undefined,
174
- mask: undefined,
175
- n: 1,
176
- size: undefined,
177
- aspectRatio: undefined,
178
- seed: undefined,
179
- providerOptions: {
180
- replicate: {
181
- maxWaitTimeInSeconds: 120,
182
- guidance_scale: 7.5,
183
- },
184
- },
185
- });
186
-
187
- const requestBody = await server.calls[0].requestBodyJson;
188
- expect(requestBody.input.maxWaitTimeInSeconds).toBeUndefined();
189
- expect(requestBody.input.guidance_scale).toBe(7.5);
190
- });
191
-
192
- it('should extract the generated image from array response', async () => {
193
- prepareResponse({
194
- output: ['https://replicate.delivery/xezq/abc/out-0.webp'],
195
- });
196
-
197
- const result = await model.doGenerate({
198
- prompt,
199
- files: undefined,
200
- mask: undefined,
201
- n: 1,
202
- size: undefined,
203
- aspectRatio: undefined,
204
- seed: undefined,
205
- providerOptions: {},
206
- });
207
-
208
- expect(result.images).toStrictEqual([
209
- new Uint8Array(Buffer.from('test-binary-content')),
210
- ]);
211
-
212
- expect(server.calls[1].requestMethod).toStrictEqual('GET');
213
- expect(server.calls[1].requestUrl).toStrictEqual(
214
- 'https://replicate.delivery/xezq/abc/out-0.webp',
215
- );
216
- });
217
-
218
- it('should extract the generated image from string response', async () => {
219
- prepareResponse({
220
- output: 'https://replicate.delivery/xezq/abc/out-0.webp',
221
- });
222
-
223
- const result = await model.doGenerate({
224
- prompt,
225
- files: undefined,
226
- mask: undefined,
227
- n: 1,
228
- size: undefined,
229
- aspectRatio: undefined,
230
- seed: undefined,
231
- providerOptions: {},
232
- });
233
-
234
- expect(result.images).toStrictEqual([
235
- new Uint8Array(Buffer.from('test-binary-content')),
236
- ]);
237
-
238
- expect(server.calls[1].requestMethod).toStrictEqual('GET');
239
- expect(server.calls[1].requestUrl).toStrictEqual(
240
- 'https://replicate.delivery/xezq/abc/out-0.webp',
241
- );
242
- });
243
-
244
- it('should return response metadata', async () => {
245
- const modelWithTimestamp = new ReplicateImageModel(
246
- 'black-forest-labs/flux-schnell',
247
- {
248
- provider: 'replicate',
249
- baseURL: 'https://api.replicate.com',
250
- _internal: { currentDate: () => testDate },
251
- },
252
- );
253
- prepareResponse({
254
- output: ['https://replicate.delivery/xezq/abc/out-0.webp'],
255
- });
256
-
257
- const result = await modelWithTimestamp.doGenerate({
258
- prompt,
259
- files: undefined,
260
- mask: undefined,
261
- n: 1,
262
- size: undefined,
263
- aspectRatio: undefined,
264
- seed: undefined,
265
- providerOptions: {},
266
- });
267
-
268
- expect(result.response).toStrictEqual({
269
- timestamp: testDate,
270
- modelId: 'black-forest-labs/flux-schnell',
271
- headers: expect.any(Object),
272
- });
273
- });
274
-
275
- it('should include response headers in metadata', async () => {
276
- const modelWithTimestamp = new ReplicateImageModel(
277
- 'black-forest-labs/flux-schnell',
278
- {
279
- provider: 'replicate',
280
- baseURL: 'https://api.replicate.com',
281
- _internal: {
282
- currentDate: () => testDate,
283
- },
284
- },
285
- );
286
- server.urls['https://api.replicate.com/*'].response = {
287
- type: 'json-value',
288
- headers: {
289
- 'custom-response-header': 'response-header-value',
290
- },
291
- body: {
292
- id: 's7x1e3dcmhrmc0cm8rbatcneec',
293
- model: 'black-forest-labs/flux-schnell',
294
- version: 'dp-4d0bcc010b3049749a251855f12800be',
295
- input: {
296
- num_outputs: 1,
297
- prompt: 'The Loch Ness Monster getting a manicure',
298
- },
299
- logs: '',
300
- output: ['https://replicate.delivery/xezq/abc/out-0.webp'],
301
- data_removed: false,
302
- error: null,
303
- status: 'processing',
304
- created_at: '2025-01-08T13:24:38.692Z',
305
- urls: {
306
- cancel:
307
- 'https://api.replicate.com/v1/predictions/s7x1e3dcmhrmc0cm8rbatcneec/cancel',
308
- get: 'https://api.replicate.com/v1/predictions/s7x1e3dcmhrmc0cm8rbatcneec',
309
- stream:
310
- 'https://stream.replicate.com/v1/files/bcwr-3okdfv3o2wehstv5f2okyftwxy57hhypqsi6osiim5iaq5k7u24a',
311
- },
312
- },
313
- };
314
-
315
- const result = await modelWithTimestamp.doGenerate({
316
- prompt,
317
- files: undefined,
318
- mask: undefined,
319
- n: 1,
320
- size: undefined,
321
- aspectRatio: undefined,
322
- seed: undefined,
323
- providerOptions: {},
324
- });
325
-
326
- expect(result.response).toStrictEqual({
327
- timestamp: testDate,
328
- modelId: 'black-forest-labs/flux-schnell',
329
- headers: {
330
- 'content-length': '646',
331
- 'content-type': 'application/json',
332
- 'custom-response-header': 'response-header-value',
333
- },
334
- });
335
- });
336
-
337
- it('should set version in request body for versioned models', async () => {
338
- prepareResponse();
339
-
340
- const versionedModel = provider.image(
341
- 'bytedance/sdxl-lightning-4step:5599ed30703defd1d160a25a63321b4dec97101d98b4674bcc56e41f62f35637',
342
- );
343
-
344
- await versionedModel.doGenerate({
345
- prompt,
346
- files: undefined,
347
- mask: undefined,
348
- n: 1,
349
- size: undefined,
350
- aspectRatio: undefined,
351
- seed: undefined,
352
- providerOptions: {},
353
- });
354
-
355
- expect(server.calls[0].requestMethod).toStrictEqual('POST');
356
- expect(server.calls[0].requestUrl).toStrictEqual(
357
- 'https://api.replicate.com/v1/predictions',
358
- );
359
- expect(await server.calls[0].requestBodyJson).toStrictEqual({
360
- input: {
361
- prompt,
362
- num_outputs: 1,
363
- },
364
- version:
365
- '5599ed30703defd1d160a25a63321b4dec97101d98b4674bcc56e41f62f35637',
366
- });
367
- });
368
-
369
- describe('Image Editing', () => {
370
- it('should send image when URL file is provided', async () => {
371
- prepareResponse();
372
-
373
- await model.doGenerate({
374
- prompt: 'Add a hat to the person',
375
- files: [
376
- {
377
- type: 'url',
378
- url: 'https://example.com/input.jpg',
379
- },
380
- ],
381
- mask: undefined,
382
- n: 1,
383
- size: undefined,
384
- aspectRatio: undefined,
385
- seed: undefined,
386
- providerOptions: {},
387
- });
388
-
389
- const requestBody = await server.calls[0].requestBodyJson;
390
- expect(requestBody).toMatchInlineSnapshot(`
391
- {
392
- "input": {
393
- "image": "https://example.com/input.jpg",
394
- "num_outputs": 1,
395
- "prompt": "Add a hat to the person",
396
- },
397
- }
398
- `);
399
- });
400
-
401
- it('should convert Uint8Array file to data URI', async () => {
402
- prepareResponse();
403
-
404
- const testImageData = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
405
-
406
- await model.doGenerate({
407
- prompt: 'Transform this image',
408
- files: [
409
- {
410
- type: 'file',
411
- data: testImageData,
412
- mediaType: 'image/png',
413
- },
414
- ],
415
- mask: undefined,
416
- n: 1,
417
- size: undefined,
418
- aspectRatio: undefined,
419
- seed: undefined,
420
- providerOptions: {},
421
- });
422
-
423
- const requestBody = await server.calls[0].requestBodyJson;
424
- expect(requestBody.input.image).toMatch(/^data:image\/png;base64,/);
425
- expect(requestBody.input.prompt).toBe('Transform this image');
426
- });
427
-
428
- it('should convert file with base64 string data to data URI', async () => {
429
- prepareResponse();
430
-
431
- await model.doGenerate({
432
- prompt: 'Edit this',
433
- files: [
434
- {
435
- type: 'file',
436
- data: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
437
- mediaType: 'image/png',
438
- },
439
- ],
440
- mask: undefined,
441
- n: 1,
442
- size: undefined,
443
- aspectRatio: undefined,
444
- seed: undefined,
445
- providerOptions: {},
446
- });
447
-
448
- const requestBody = await server.calls[0].requestBodyJson;
449
- expect(requestBody.input.image).toBe(
450
- 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==',
451
- );
452
- });
453
-
454
- it('should send mask for inpainting', async () => {
455
- prepareResponse();
456
-
457
- await model.doGenerate({
458
- prompt: 'Replace the masked area with a tree',
459
- files: [
460
- {
461
- type: 'url',
462
- url: 'https://example.com/input.jpg',
463
- },
464
- ],
465
- mask: {
466
- type: 'url',
467
- url: 'https://example.com/mask.png',
468
- },
469
- n: 1,
470
- size: undefined,
471
- aspectRatio: undefined,
472
- seed: undefined,
473
- providerOptions: {},
474
- });
475
-
476
- const requestBody = await server.calls[0].requestBodyJson;
477
- expect(requestBody).toMatchInlineSnapshot(`
478
- {
479
- "input": {
480
- "image": "https://example.com/input.jpg",
481
- "mask": "https://example.com/mask.png",
482
- "num_outputs": 1,
483
- "prompt": "Replace the masked area with a tree",
484
- },
485
- }
486
- `);
487
- });
488
-
489
- it('should warn when multiple files are provided', async () => {
490
- prepareResponse();
491
-
492
- const result = await model.doGenerate({
493
- prompt: 'Edit multiple images',
494
- files: [
495
- {
496
- type: 'url',
497
- url: 'https://example.com/input1.jpg',
498
- },
499
- {
500
- type: 'url',
501
- url: 'https://example.com/input2.jpg',
502
- },
503
- ],
504
- mask: undefined,
505
- n: 1,
506
- size: undefined,
507
- aspectRatio: undefined,
508
- seed: undefined,
509
- providerOptions: {},
510
- });
511
-
512
- expect(result.warnings).toMatchInlineSnapshot(`
513
- [
514
- {
515
- "message": "This Replicate model only supports a single input image. Additional images are ignored.",
516
- "type": "other",
517
- },
518
- ]
519
- `);
520
-
521
- // Should only use the first image
522
- const requestBody = await server.calls[0].requestBodyJson;
523
- expect(requestBody.input.image).toBe('https://example.com/input1.jpg');
524
- });
525
-
526
- it('should pass provider options with image editing', async () => {
527
- prepareResponse();
528
-
529
- await model.doGenerate({
530
- prompt: 'Inpaint this area',
531
- files: [
532
- {
533
- type: 'url',
534
- url: 'https://example.com/input.jpg',
535
- },
536
- ],
537
- mask: {
538
- type: 'url',
539
- url: 'https://example.com/mask.png',
540
- },
541
- n: 1,
542
- size: undefined,
543
- aspectRatio: undefined,
544
- seed: undefined,
545
- providerOptions: {
546
- replicate: {
547
- guidance_scale: 7.5,
548
- num_inference_steps: 30,
549
- negative_prompt: 'blurry, low quality',
550
- },
551
- },
552
- });
553
-
554
- const requestBody = await server.calls[0].requestBodyJson;
555
- expect(requestBody).toMatchInlineSnapshot(`
556
- {
557
- "input": {
558
- "guidance_scale": 7.5,
559
- "image": "https://example.com/input.jpg",
560
- "mask": "https://example.com/mask.png",
561
- "negative_prompt": "blurry, low quality",
562
- "num_inference_steps": 30,
563
- "num_outputs": 1,
564
- "prompt": "Inpaint this area",
565
- },
566
- }
567
- `);
568
- });
569
- });
570
-
571
- describe('Flux-2 Models', () => {
572
- const flux2Model = provider.image('black-forest-labs/flux-2-pro');
573
-
574
- it('should report maxImagesPerCall as 8 for Flux-2 models', () => {
575
- expect(flux2Model.maxImagesPerCall).toBe(8);
576
- });
577
-
578
- it('should report maxImagesPerCall as 1 for non-Flux-2 models', () => {
579
- expect(model.maxImagesPerCall).toBe(1);
580
- });
581
-
582
- it('should send single image as input_image for Flux-2 models', async () => {
583
- prepareResponse();
584
-
585
- await flux2Model.doGenerate({
586
- prompt: 'Generate image in similar style',
587
- files: [
588
- {
589
- type: 'url',
590
- url: 'https://example.com/reference.jpg',
591
- },
592
- ],
593
- mask: undefined,
594
- n: 1,
595
- size: undefined,
596
- aspectRatio: undefined,
597
- seed: undefined,
598
- providerOptions: {},
599
- });
600
-
601
- const requestBody = await server.calls[0].requestBodyJson;
602
- expect(requestBody).toMatchInlineSnapshot(`
603
- {
604
- "input": {
605
- "input_image": "https://example.com/reference.jpg",
606
- "num_outputs": 1,
607
- "prompt": "Generate image in similar style",
608
- },
609
- }
610
- `);
611
- });
612
-
613
- it('should send multiple images as input_image, input_image_2, etc. for Flux-2 models', async () => {
614
- prepareResponse();
615
-
616
- await flux2Model.doGenerate({
617
- prompt: 'Combine styles from reference images',
618
- files: [
619
- {
620
- type: 'url',
621
- url: 'https://example.com/reference1.jpg',
622
- },
623
- {
624
- type: 'url',
625
- url: 'https://example.com/reference2.jpg',
626
- },
627
- {
628
- type: 'url',
629
- url: 'https://example.com/reference3.jpg',
630
- },
631
- ],
632
- mask: undefined,
633
- n: 1,
634
- size: undefined,
635
- aspectRatio: undefined,
636
- seed: undefined,
637
- providerOptions: {},
638
- });
639
-
640
- const requestBody = await server.calls[0].requestBodyJson;
641
- expect(requestBody).toMatchInlineSnapshot(`
642
- {
643
- "input": {
644
- "input_image": "https://example.com/reference1.jpg",
645
- "input_image_2": "https://example.com/reference2.jpg",
646
- "input_image_3": "https://example.com/reference3.jpg",
647
- "num_outputs": 1,
648
- "prompt": "Combine styles from reference images",
649
- },
650
- }
651
- `);
652
- });
653
-
654
- it('should warn when more than 8 images are provided for Flux-2 models', async () => {
655
- prepareResponse();
656
-
657
- const result = await flux2Model.doGenerate({
658
- prompt: 'Too many images',
659
- files: [
660
- { type: 'url', url: 'https://example.com/img1.jpg' },
661
- { type: 'url', url: 'https://example.com/img2.jpg' },
662
- { type: 'url', url: 'https://example.com/img3.jpg' },
663
- { type: 'url', url: 'https://example.com/img4.jpg' },
664
- { type: 'url', url: 'https://example.com/img5.jpg' },
665
- { type: 'url', url: 'https://example.com/img6.jpg' },
666
- { type: 'url', url: 'https://example.com/img7.jpg' },
667
- { type: 'url', url: 'https://example.com/img8.jpg' },
668
- { type: 'url', url: 'https://example.com/img9.jpg' },
669
- ],
670
- mask: undefined,
671
- n: 1,
672
- size: undefined,
673
- aspectRatio: undefined,
674
- seed: undefined,
675
- providerOptions: {},
676
- });
677
-
678
- expect(result.warnings).toMatchInlineSnapshot(`
679
- [
680
- {
681
- "message": "Flux-2 models support up to 8 input images. Additional images are ignored.",
682
- "type": "other",
683
- },
684
- ]
685
- `);
686
-
687
- // Should only include 8 images
688
- const requestBody = await server.calls[0].requestBodyJson;
689
- expect(requestBody.input.input_image).toBe(
690
- 'https://example.com/img1.jpg',
691
- );
692
- expect(requestBody.input.input_image_8).toBe(
693
- 'https://example.com/img8.jpg',
694
- );
695
- expect(requestBody.input.input_image_9).toBeUndefined();
696
- });
697
-
698
- it('should warn and ignore mask for Flux-2 models', async () => {
699
- prepareResponse();
700
-
701
- const result = await flux2Model.doGenerate({
702
- prompt: 'Edit with mask',
703
- files: [
704
- {
705
- type: 'url',
706
- url: 'https://example.com/input.jpg',
707
- },
708
- ],
709
- mask: {
710
- type: 'url',
711
- url: 'https://example.com/mask.png',
712
- },
713
- n: 1,
714
- size: undefined,
715
- aspectRatio: undefined,
716
- seed: undefined,
717
- providerOptions: {},
718
- });
719
-
720
- expect(result.warnings).toMatchInlineSnapshot(`
721
- [
722
- {
723
- "message": "Flux-2 models do not support mask input. The mask will be ignored.",
724
- "type": "other",
725
- },
726
- ]
727
- `);
728
-
729
- const requestBody = await server.calls[0].requestBodyJson;
730
- expect(requestBody.input.mask).toBeUndefined();
731
- });
732
-
733
- it('should call correct URL for Flux-2 models', async () => {
734
- prepareResponse();
735
-
736
- await flux2Model.doGenerate({
737
- prompt: 'Generate something',
738
- files: undefined,
739
- mask: undefined,
740
- n: 1,
741
- size: undefined,
742
- aspectRatio: undefined,
743
- seed: undefined,
744
- providerOptions: {},
745
- });
746
-
747
- expect(server.calls[0].requestUrl).toStrictEqual(
748
- 'https://api.replicate.com/v1/models/black-forest-labs/flux-2-pro/predictions',
749
- );
750
- });
751
- });
752
- });
@@ -1,24 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { createReplicate } from './replicate-provider';
3
- import { ReplicateImageModel } from './replicate-image-model';
4
-
5
- describe('createReplicate', () => {
6
- it('creates a provider with required settings', () => {
7
- const provider = createReplicate({ apiToken: 'test-token' });
8
- expect(provider.image).toBeDefined();
9
- });
10
-
11
- it('creates a provider with custom settings', () => {
12
- const provider = createReplicate({
13
- apiToken: 'test-token',
14
- baseURL: 'https://custom.replicate.com',
15
- });
16
- expect(provider.image).toBeDefined();
17
- });
18
-
19
- it('creates an image model instance', () => {
20
- const provider = createReplicate({ apiToken: 'test-token' });
21
- const model = provider.image('black-forest-labs/flux-schnell');
22
- expect(model).toBeInstanceOf(ReplicateImageModel);
23
- });
24
- });