@runpod/ai-sdk-provider 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +10 -8
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -221,14 +221,16 @@ writeFileSync('landscape.jpg', image.uint8Array);
|
|
|
221
221
|
|
|
222
222
|
### Model Capabilities
|
|
223
223
|
|
|
224
|
-
| Model ID | Description | Supported Aspect Ratios
|
|
225
|
-
| -------------------------------------- | ------------------------------- |
|
|
226
|
-
| `
|
|
227
|
-
| `bytedance/seedream-
|
|
228
|
-
| `
|
|
229
|
-
| `black-forest-labs/flux-1-
|
|
230
|
-
| `black-forest-labs/flux-1-
|
|
231
|
-
| `
|
|
224
|
+
| Model ID | Description | Supported Aspect Ratios |
|
|
225
|
+
| -------------------------------------- | ------------------------------- | ------------------------------------- |
|
|
226
|
+
| `bytedance/seedream-3.0` | Advanced text-to-image model | 1:1, 4:3, 3:4 |
|
|
227
|
+
| `bytedance/seedream-4.0` | Text-to-image (v4) | 1:1 (supports 1024, 2048, 4096) |
|
|
228
|
+
| `bytedance/seedream-4.0-edit` | Image editing (v4, multi-image) | 1:1 (supports 1024, 1536, 2048, 4096) |
|
|
229
|
+
| `black-forest-labs/flux-1-schnell` | Fast image generation (4 steps) | 1:1, 4:3, 3:4 |
|
|
230
|
+
| `black-forest-labs/flux-1-dev` | High-quality image generation | 1:1, 4:3, 3:4 |
|
|
231
|
+
| `black-forest-labs/flux-1-kontext-dev` | Context-aware image generation | 1:1, 4:3, 3:4 |
|
|
232
|
+
| `qwen/qwen-image` | Text-to-image generation | 1:1, 4:3, 3:4 |
|
|
233
|
+
| `qwen/qwen-image-edit` | Image editing (prompt-guided) | 1:1, 4:3, 3:4 |
|
|
232
234
|
|
|
233
235
|
**Note**: The provider uses strict validation for image parameters. Unsupported aspect ratios (like `16:9`, `9:16`, `3:2`, `2:3`) will throw an `InvalidArgumentError` with a clear message about supported alternatives.
|
|
234
236
|
|
package/dist/index.d.mts
CHANGED
|
@@ -6,7 +6,7 @@ type RunpodChatModelId = 'deep-cogito/deep-cogito-v2-llama-70b' | 'qwen/qwen3-32
|
|
|
6
6
|
|
|
7
7
|
type RunpodCompletionModelId = 'deep-cogito/deep-cogito-v2-llama-70b' | 'qwen/qwen3-32b-awq' | (string & {});
|
|
8
8
|
|
|
9
|
-
type RunpodImageModelId = 'qwen/qwen-image' | 'bytedance/seedream-3.0' | 'black-forest-labs/flux-1-kontext-dev' | 'black-forest-labs/flux-1-schnell' | 'black-forest-labs/flux-1-dev';
|
|
9
|
+
type RunpodImageModelId = 'qwen/qwen-image' | 'qwen/qwen-image-edit' | 'bytedance/seedream-3.0' | 'bytedance/seedream-4.0' | 'bytedance/seedream-4.0-edit' | 'black-forest-labs/flux-1-kontext-dev' | 'black-forest-labs/flux-1-schnell' | 'black-forest-labs/flux-1-dev';
|
|
10
10
|
|
|
11
11
|
interface RunpodProviderSettings {
|
|
12
12
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ type RunpodChatModelId = 'deep-cogito/deep-cogito-v2-llama-70b' | 'qwen/qwen3-32
|
|
|
6
6
|
|
|
7
7
|
type RunpodCompletionModelId = 'deep-cogito/deep-cogito-v2-llama-70b' | 'qwen/qwen3-32b-awq' | (string & {});
|
|
8
8
|
|
|
9
|
-
type RunpodImageModelId = 'qwen/qwen-image' | 'bytedance/seedream-3.0' | 'black-forest-labs/flux-1-kontext-dev' | 'black-forest-labs/flux-1-schnell' | 'black-forest-labs/flux-1-dev';
|
|
9
|
+
type RunpodImageModelId = 'qwen/qwen-image' | 'qwen/qwen-image-edit' | 'bytedance/seedream-3.0' | 'bytedance/seedream-4.0' | 'bytedance/seedream-4.0-edit' | 'black-forest-labs/flux-1-kontext-dev' | 'black-forest-labs/flux-1-schnell' | 'black-forest-labs/flux-1-dev';
|
|
10
10
|
|
|
11
11
|
interface RunpodProviderSettings {
|
|
12
12
|
/**
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,9 @@ var SUPPORTED_SIZES = /* @__PURE__ */ new Set([
|
|
|
53
53
|
"512*512",
|
|
54
54
|
"768*768",
|
|
55
55
|
"1024*1024",
|
|
56
|
+
"1536*1536",
|
|
57
|
+
"2048*2048",
|
|
58
|
+
"4096*4096",
|
|
56
59
|
"512*768",
|
|
57
60
|
"768*512",
|
|
58
61
|
"1024*768",
|
|
@@ -318,6 +321,9 @@ var IMAGE_MODEL_ID_TO_ENDPOINT_URL = {
|
|
|
318
321
|
"qwen/qwen-image": "https://api.runpod.ai/v2/qwen-image-t2i",
|
|
319
322
|
"qwen/qwen-image-edit": "https://api.runpod.ai/v2/qwen-image-edit",
|
|
320
323
|
"bytedance/seedream-3.0": "https://api.runpod.ai/v2/seedream-3-0-t2i",
|
|
324
|
+
// Seadream v4 (t2i and edit)
|
|
325
|
+
"bytedance/seedream-4.0": "https://api.runpod.ai/v2/seedream-v4-t2i",
|
|
326
|
+
"bytedance/seedream-4.0-edit": "https://api.runpod.ai/v2/seedream-v4-edit",
|
|
321
327
|
"black-forest-labs/flux-1-kontext-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev",
|
|
322
328
|
"black-forest-labs/flux-1-schnell": "https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell",
|
|
323
329
|
"black-forest-labs/flux-1-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-dev"
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/runpod-provider.ts","../src/runpod-image-model.ts"],"sourcesContent":["export { createRunpod, runpod } from './runpod-provider';\nexport type { RunpodProvider, RunpodProviderSettings } from './runpod-provider';\nexport type { RunpodChatModelId } from './runpod-chat-options';\nexport type { RunpodCompletionModelId } from './runpod-completion-options';\nexport type { RunpodImageModelId } from './runpod-image-options';\nexport type { OpenAICompatibleErrorData as RunpodErrorData } from '@ai-sdk/openai-compatible';\n","import { LanguageModelV2, ImageModelV2 } from '@ai-sdk/provider';\nimport {\n OpenAICompatibleChatLanguageModel,\n OpenAICompatibleCompletionLanguageModel,\n} from '@ai-sdk/openai-compatible';\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n} from '@ai-sdk/provider-utils';\nimport { RunpodChatModelId } from './runpod-chat-options';\nimport { RunpodCompletionModelId } from './runpod-completion-options';\nimport { RunpodImageModelId } from './runpod-image-options';\nimport { RunpodImageModel } from './runpod-image-model';\n\nexport interface RunpodProviderSettings {\n /**\nRunpod API key.\n*/\n apiKey?: string;\n /**\nCustom base URL for Runpod API. Use this to point to custom endpoints or different Runpod deployments.\nExample: 'https://api.runpod.ai/v2/your-endpoint-id/openai/v1'\n*/\n baseURL?: string;\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\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 RunpodProvider {\n /**\nCreates a model for text generation.\n*/\n (modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n chatModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n languageModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a completion model for text generation.\n*/\n completionModel(modelId: RunpodCompletionModelId): LanguageModelV2;\n\n /**\nCreates an image model for image generation.\n*/\n imageModel(modelId: RunpodImageModelId): ImageModelV2;\n}\n\n// Mapping of Runpod model IDs to their endpoint URLs\nconst MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'https://api.runpod.ai/v2/deep-cogito-v2-llama-70b/openai/v1',\n 'qwen/qwen3-32b-awq': 'https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1',\n};\n\n// Mapping of Runpod image model IDs to their endpoint URLs\nconst IMAGE_MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'qwen/qwen-image': 'https://api.runpod.ai/v2/qwen-image-t2i',\n 'qwen/qwen-image-edit': 'https://api.runpod.ai/v2/qwen-image-edit',\n 'bytedance/seedream-3.0': 'https://api.runpod.ai/v2/seedream-3-0-t2i',\n 'black-forest-labs/flux-1-kontext-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev',\n 'black-forest-labs/flux-1-schnell':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell',\n 'black-forest-labs/flux-1-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-dev',\n};\n\n// Mapping of Runpod model IDs to their OpenAI model names\nconst MODEL_ID_TO_OPENAI_NAME: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'deepcogito/cogito-v2-preview-llama-70B',\n 'qwen/qwen3-32b-awq': 'Qwen/Qwen3-32B-AWQ',\n};\n\nexport function createRunpod(\n options: RunpodProviderSettings = {}\n): RunpodProvider {\n const getHeaders = () => ({\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'RUNPOD_API_KEY',\n description: 'Runpod',\n })}`,\n ...options.headers,\n });\n\n const runpodFetch: FetchFunction = async (url, requestInit) => {\n if (requestInit?.body) {\n try {\n const body = JSON.parse(requestInit.body as string);\n if (body.stream === true && !body.stream_options) {\n body.stream_options = { include_usage: true };\n requestInit.body = JSON.stringify(body);\n }\n } catch {}\n }\n const fetchFn = options.fetch || fetch;\n return fetchFn(url, requestInit);\n };\n\n interface CommonModelConfig {\n provider: string;\n url: ({ path }: { path: string }) => string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n }\n\n const getModelConfig = (\n modelId: string,\n modelType: string\n ): CommonModelConfig => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod model: ${modelId}. Supported models: ${Object.keys(\n MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: runpodFetch,\n };\n };\n\n const createChatModel = (modelId: RunpodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'chat'),\n includeUsage: true,\n });\n };\n\n const createCompletionModel = (modelId: RunpodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'completion'),\n includeUsage: true,\n });\n };\n\n const createImageModel = (modelId: RunpodImageModelId) => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod image model: ${modelId}. Supported models: ${Object.keys(\n IMAGE_MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return new RunpodImageModel(modelId, {\n provider: 'runpod.image',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n };\n\n const provider = (modelId: RunpodChatModelId) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n provider.imageModel = createImageModel;\n\n return provider;\n}\n\nexport const runpod = createRunpod();\n","import { ImageModelV2, ImageModelV2CallWarning } from '@ai-sdk/provider';\r\nimport {\r\n combineHeaders,\r\n createJsonResponseHandler,\r\n createJsonErrorResponseHandler,\r\n createBinaryResponseHandler,\r\n FetchFunction,\r\n postJsonToApi,\r\n getFromApi,\r\n} from '@ai-sdk/provider-utils';\r\nimport { InvalidArgumentError } from '@ai-sdk/provider';\r\nimport { z } from 'zod';\r\nimport { RunpodImageModelId } from './runpod-image-options';\r\n\r\ninterface RunpodImageModelConfig {\r\n provider: string;\r\n baseURL: string;\r\n headers: () => Record<string, string>;\r\n fetch?: FetchFunction;\r\n _internal?: {\r\n currentDate?: () => Date;\r\n };\r\n}\r\n\r\n// Runpod supported aspect ratios (only validated working sizes)\r\nconst SUPPORTED_ASPECT_RATIOS: Record<string, string> = {\r\n '1:1': '1328*1328', // ✅ Native support\r\n '4:3': '1472*1140', // ✅ Native support\r\n '3:4': '1140*1472', // ✅ Native support\r\n};\r\n\r\n// Runpod supported sizes (validated working sizes)\r\nconst SUPPORTED_SIZES = new Set([\r\n // Native aspect ratio sizes\r\n '1328*1328', // 1:1\r\n '1472*1140', // 4:3\r\n '1140*1472', // 3:4\r\n // Additional validated sizes\r\n '512*512',\r\n '768*768',\r\n '1024*1024',\r\n '512*768',\r\n '768*512',\r\n '1024*768',\r\n '768*1024',\r\n]);\r\n\r\nexport class RunpodImageModel implements ImageModelV2 {\r\n readonly specificationVersion = 'v2';\r\n readonly maxImagesPerCall = 1;\r\n\r\n get provider(): string {\r\n return this.config.provider;\r\n }\r\n\r\n constructor(\r\n readonly modelId: RunpodImageModelId,\r\n private config: RunpodImageModelConfig\r\n ) {}\r\n\r\n async doGenerate({\r\n prompt,\r\n n = 1,\r\n size,\r\n aspectRatio,\r\n seed,\r\n providerOptions,\r\n headers,\r\n abortSignal,\r\n }: Parameters<ImageModelV2['doGenerate']>[0]): Promise<\r\n Awaited<ReturnType<ImageModelV2['doGenerate']>>\r\n > {\r\n const warnings: Array<ImageModelV2CallWarning> = [];\r\n\r\n // Determine the size to use\r\n let runpodSize: string;\r\n\r\n if (size) {\r\n // Convert AI SDK format \"1328x1328\" to Runpod format \"1328*1328\"\r\n const runpodSizeCandidate = size.replace('x', '*');\r\n\r\n // Validate size is supported\r\n if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {\r\n throw new InvalidArgumentError({\r\n argument: 'size',\r\n message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(\r\n SUPPORTED_SIZES\r\n )\r\n .map((s) => s.replace('*', 'x'))\r\n .join(', ')}`,\r\n });\r\n }\r\n\r\n runpodSize = runpodSizeCandidate;\r\n } else if (aspectRatio) {\r\n // Validate aspect ratio is supported\r\n if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {\r\n throw new InvalidArgumentError({\r\n argument: 'aspectRatio',\r\n message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(', ')}`,\r\n });\r\n }\r\n\r\n // Use supported aspect ratio mapping\r\n runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];\r\n } else {\r\n // Default to square format\r\n runpodSize = '1328*1328';\r\n }\r\n\r\n // Handle multiple images warning\r\n if (n > 1) {\r\n warnings.push({\r\n type: 'unsupported-setting',\r\n setting: 'n',\r\n details:\r\n 'Runpod image models only support generating 1 image at a time. Using n=1.',\r\n });\r\n }\r\n\r\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\r\n\r\n // Runpod uses a different request format - /runsync endpoint with input wrapper\r\n const inputPayload = this.buildInputPayload(\r\n prompt,\r\n runpodSize,\r\n seed,\r\n providerOptions.runpod\r\n );\r\n\r\n const { value: response, responseHeaders } = await postJsonToApi({\r\n url: `${this.config.baseURL}/runsync`,\r\n headers: combineHeaders(this.config.headers(), headers),\r\n body: {\r\n input: inputPayload,\r\n },\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Unknown error',\r\n }),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageResponseSchema as any\r\n ),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n // Handle both sync and async responses from Runpod\r\n const typedResponse = response as any;\r\n if (\r\n typedResponse.status === 'COMPLETED' &&\r\n (typedResponse.output?.result || typedResponse.output?.image_url)\r\n ) {\r\n // Sync response - image is ready\r\n // Different models use different response formats: result vs image_url\r\n const imageUrl =\r\n typedResponse.output.result || typedResponse.output.image_url;\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n cost: typedResponse.output?.cost,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else if (\r\n typedResponse.status === 'IN_QUEUE' ||\r\n typedResponse.status === 'IN_PROGRESS'\r\n ) {\r\n // Async response - need to poll for completion\r\n const pollOptions = {\r\n maxAttempts: providerOptions.runpod?.maxPollAttempts as number,\r\n pollIntervalMillis: providerOptions.runpod\r\n ?.pollIntervalMillis as number,\r\n };\r\n const imageUrl = await this.pollForCompletion(\r\n typedResponse.id,\r\n abortSignal,\r\n pollOptions\r\n );\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n jobId: typedResponse.id,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else {\r\n throw new Error(`Unexpected response status: ${typedResponse.status}`);\r\n }\r\n }\r\n\r\n private async downloadImage(\r\n imageUrl: string,\r\n abortSignal?: AbortSignal\r\n ): Promise<Uint8Array> {\r\n const { value: imageData } = await getFromApi({\r\n url: imageUrl,\r\n successfulResponseHandler: createBinaryResponseHandler(),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Failed to download image',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n return imageData;\r\n }\r\n\r\n private async pollForCompletion(\r\n jobId: string,\r\n abortSignal?: AbortSignal,\r\n pollOptions?: { maxAttempts?: number; pollIntervalMillis?: number }\r\n ): Promise<string> {\r\n const maxAttempts = pollOptions?.maxAttempts ?? 60; // 5 minutes with 5-second intervals\r\n const pollInterval = pollOptions?.pollIntervalMillis ?? 5000; // 5 seconds\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n if (abortSignal?.aborted) {\r\n throw new Error('Image generation was aborted');\r\n }\r\n\r\n const { value: statusResponse } = await getFromApi({\r\n url: `${this.config.baseURL}/status/${jobId}`,\r\n headers: this.config.headers(),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageStatusSchema as any\r\n ),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) =>\r\n data.error ?? 'Failed to check job status',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n const typedStatusResponse = statusResponse as any;\r\n if (\r\n typedStatusResponse.status === 'COMPLETED' &&\r\n (typedStatusResponse.output?.result ||\r\n typedStatusResponse.output?.image_url)\r\n ) {\r\n return (\r\n typedStatusResponse.output.result ||\r\n typedStatusResponse.output.image_url\r\n );\r\n }\r\n\r\n if (typedStatusResponse.status === 'FAILED') {\r\n throw new Error(\r\n `Image generation failed: ${typedStatusResponse.error || 'Unknown error'}`\r\n );\r\n }\r\n\r\n // Wait before next poll\r\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\r\n }\r\n\r\n throw new Error(\r\n `Image generation timed out after ${maxAttempts} attempts (${(maxAttempts * pollInterval) / 1000}s)`\r\n );\r\n }\r\n\r\n private buildInputPayload(\r\n prompt: string,\r\n runpodSize: string,\r\n seed?: number,\r\n runpodOptions?: Record<string, unknown>\r\n ): Record<string, unknown> {\r\n // Check if this is a Flux model that uses different parameters\r\n const isFluxModel =\r\n this.modelId.includes('flux') ||\r\n this.modelId.includes('black-forest-labs');\r\n\r\n if (isFluxModel) {\r\n // Check if this is Flux Kontext (uses different parameters)\r\n const isKontext = this.modelId.includes('kontext');\r\n\r\n if (isKontext) {\r\n // Flux Kontext uses size format and has image input\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: 28,\r\n guidance: 2,\r\n size: runpodSize,\r\n output_format: 'png',\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions, // This will include the 'image' parameter if provided\r\n };\r\n } else {\r\n // Regular Flux models use width/height\r\n const [width, height] = runpodSize.split('*').map(Number);\r\n\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: this.modelId.includes('schnell') ? 4 : 28,\r\n guidance: this.modelId.includes('schnell') ? 7 : 2,\r\n width,\r\n height,\r\n image_format: 'png',\r\n ...runpodOptions,\r\n };\r\n }\r\n }\r\n\r\n // Default format for Qwen and other models\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n size: runpodSize,\r\n seed: seed ?? -1,\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions,\r\n };\r\n }\r\n}\r\n\r\n// Runpod image API response schema (handles both sync and async responses)\r\nconst runpodImageResponseSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n delayTime: z.number().optional(),\r\n executionTime: z.number().optional(),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(), // URL to the generated image (Qwen format)\r\n image_url: z.string().optional(), // URL to the generated image (Flux format)\r\n })\r\n .optional(), // Optional for IN_QUEUE/IN_PROGRESS responses\r\n});\r\n\r\n// Schema for polling status endpoint\r\nconst runpodImageStatusSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(),\r\n image_url: z.string().optional(),\r\n })\r\n .optional(),\r\n error: z.string().optional(), // Error message if FAILED\r\n});\r\n\r\n// Runpod image API error schema\r\nconst runpodImageErrorSchema = z.object({\r\n error: z.string(),\r\n message: z.string().optional(),\r\n});\r\n"],"mappings":"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","names":["import_provider_utils"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/runpod-provider.ts","../src/runpod-image-model.ts"],"sourcesContent":["export { createRunpod, runpod } from './runpod-provider';\nexport type { RunpodProvider, RunpodProviderSettings } from './runpod-provider';\nexport type { RunpodChatModelId } from './runpod-chat-options';\nexport type { RunpodCompletionModelId } from './runpod-completion-options';\nexport type { RunpodImageModelId } from './runpod-image-options';\nexport type { OpenAICompatibleErrorData as RunpodErrorData } from '@ai-sdk/openai-compatible';\n","import { LanguageModelV2, ImageModelV2 } from '@ai-sdk/provider';\nimport {\n OpenAICompatibleChatLanguageModel,\n OpenAICompatibleCompletionLanguageModel,\n} from '@ai-sdk/openai-compatible';\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n} from '@ai-sdk/provider-utils';\nimport { RunpodChatModelId } from './runpod-chat-options';\nimport { RunpodCompletionModelId } from './runpod-completion-options';\nimport { RunpodImageModelId } from './runpod-image-options';\nimport { RunpodImageModel } from './runpod-image-model';\n\nexport interface RunpodProviderSettings {\n /**\nRunpod API key.\n*/\n apiKey?: string;\n /**\nCustom base URL for Runpod API. Use this to point to custom endpoints or different Runpod deployments.\nExample: 'https://api.runpod.ai/v2/your-endpoint-id/openai/v1'\n*/\n baseURL?: string;\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\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 RunpodProvider {\n /**\nCreates a model for text generation.\n*/\n (modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n chatModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n languageModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a completion model for text generation.\n*/\n completionModel(modelId: RunpodCompletionModelId): LanguageModelV2;\n\n /**\nCreates an image model for image generation.\n*/\n imageModel(modelId: RunpodImageModelId): ImageModelV2;\n}\n\n// Mapping of Runpod model IDs to their endpoint URLs\nconst MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'https://api.runpod.ai/v2/deep-cogito-v2-llama-70b/openai/v1',\n 'qwen/qwen3-32b-awq': 'https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1',\n};\n\n// Mapping of Runpod image model IDs to their endpoint URLs\nconst IMAGE_MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'qwen/qwen-image': 'https://api.runpod.ai/v2/qwen-image-t2i',\n 'qwen/qwen-image-edit': 'https://api.runpod.ai/v2/qwen-image-edit',\n 'bytedance/seedream-3.0': 'https://api.runpod.ai/v2/seedream-3-0-t2i',\n // Seadream v4 (t2i and edit)\n 'bytedance/seedream-4.0': 'https://api.runpod.ai/v2/seedream-v4-t2i',\n 'bytedance/seedream-4.0-edit': 'https://api.runpod.ai/v2/seedream-v4-edit',\n 'black-forest-labs/flux-1-kontext-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev',\n 'black-forest-labs/flux-1-schnell':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell',\n 'black-forest-labs/flux-1-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-dev',\n};\n\n// Mapping of Runpod model IDs to their OpenAI model names\nconst MODEL_ID_TO_OPENAI_NAME: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'deepcogito/cogito-v2-preview-llama-70B',\n 'qwen/qwen3-32b-awq': 'Qwen/Qwen3-32B-AWQ',\n};\n\nexport function createRunpod(\n options: RunpodProviderSettings = {}\n): RunpodProvider {\n const getHeaders = () => ({\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'RUNPOD_API_KEY',\n description: 'Runpod',\n })}`,\n ...options.headers,\n });\n\n const runpodFetch: FetchFunction = async (url, requestInit) => {\n if (requestInit?.body) {\n try {\n const body = JSON.parse(requestInit.body as string);\n if (body.stream === true && !body.stream_options) {\n body.stream_options = { include_usage: true };\n requestInit.body = JSON.stringify(body);\n }\n } catch {}\n }\n const fetchFn = options.fetch || fetch;\n return fetchFn(url, requestInit);\n };\n\n interface CommonModelConfig {\n provider: string;\n url: ({ path }: { path: string }) => string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n }\n\n const getModelConfig = (\n modelId: string,\n modelType: string\n ): CommonModelConfig => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod model: ${modelId}. Supported models: ${Object.keys(\n MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: runpodFetch,\n };\n };\n\n const createChatModel = (modelId: RunpodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'chat'),\n includeUsage: true,\n });\n };\n\n const createCompletionModel = (modelId: RunpodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'completion'),\n includeUsage: true,\n });\n };\n\n const createImageModel = (modelId: RunpodImageModelId) => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod image model: ${modelId}. Supported models: ${Object.keys(\n IMAGE_MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return new RunpodImageModel(modelId, {\n provider: 'runpod.image',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n };\n\n const provider = (modelId: RunpodChatModelId) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n provider.imageModel = createImageModel;\n\n return provider;\n}\n\nexport const runpod = createRunpod();\n","import { ImageModelV2, ImageModelV2CallWarning } from '@ai-sdk/provider';\r\nimport {\r\n combineHeaders,\r\n createJsonResponseHandler,\r\n createJsonErrorResponseHandler,\r\n createBinaryResponseHandler,\r\n FetchFunction,\r\n postJsonToApi,\r\n getFromApi,\r\n} from '@ai-sdk/provider-utils';\r\nimport { InvalidArgumentError } from '@ai-sdk/provider';\r\nimport { z } from 'zod';\r\nimport { RunpodImageModelId } from './runpod-image-options';\r\n\r\ninterface RunpodImageModelConfig {\r\n provider: string;\r\n baseURL: string;\r\n headers: () => Record<string, string>;\r\n fetch?: FetchFunction;\r\n _internal?: {\r\n currentDate?: () => Date;\r\n };\r\n}\r\n\r\n// Runpod supported aspect ratios (only validated working sizes)\r\nconst SUPPORTED_ASPECT_RATIOS: Record<string, string> = {\r\n '1:1': '1328*1328', // ✅ Native support\r\n '4:3': '1472*1140', // ✅ Native support\r\n '3:4': '1140*1472', // ✅ Native support\r\n};\r\n\r\n// Runpod supported sizes (validated working sizes)\r\nconst SUPPORTED_SIZES = new Set([\r\n // Native aspect ratio sizes\r\n '1328*1328', // 1:1\r\n '1472*1140', // 4:3\r\n '1140*1472', // 3:4\r\n // Additional validated sizes\r\n '512*512',\r\n '768*768',\r\n '1024*1024',\r\n '1536*1536',\r\n '2048*2048',\r\n '4096*4096',\r\n '512*768',\r\n '768*512',\r\n '1024*768',\r\n '768*1024',\r\n]);\r\n\r\nexport class RunpodImageModel implements ImageModelV2 {\r\n readonly specificationVersion = 'v2';\r\n readonly maxImagesPerCall = 1;\r\n\r\n get provider(): string {\r\n return this.config.provider;\r\n }\r\n\r\n constructor(\r\n readonly modelId: RunpodImageModelId,\r\n private config: RunpodImageModelConfig\r\n ) {}\r\n\r\n async doGenerate({\r\n prompt,\r\n n = 1,\r\n size,\r\n aspectRatio,\r\n seed,\r\n providerOptions,\r\n headers,\r\n abortSignal,\r\n }: Parameters<ImageModelV2['doGenerate']>[0]): Promise<\r\n Awaited<ReturnType<ImageModelV2['doGenerate']>>\r\n > {\r\n const warnings: Array<ImageModelV2CallWarning> = [];\r\n\r\n // Determine the size to use\r\n let runpodSize: string;\r\n\r\n if (size) {\r\n // Convert AI SDK format \"1328x1328\" to Runpod format \"1328*1328\"\r\n const runpodSizeCandidate = size.replace('x', '*');\r\n\r\n // Validate size is supported\r\n if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {\r\n throw new InvalidArgumentError({\r\n argument: 'size',\r\n message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(\r\n SUPPORTED_SIZES\r\n )\r\n .map((s) => s.replace('*', 'x'))\r\n .join(', ')}`,\r\n });\r\n }\r\n\r\n runpodSize = runpodSizeCandidate;\r\n } else if (aspectRatio) {\r\n // Validate aspect ratio is supported\r\n if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {\r\n throw new InvalidArgumentError({\r\n argument: 'aspectRatio',\r\n message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(', ')}`,\r\n });\r\n }\r\n\r\n // Use supported aspect ratio mapping\r\n runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];\r\n } else {\r\n // Default to square format\r\n runpodSize = '1328*1328';\r\n }\r\n\r\n // Handle multiple images warning\r\n if (n > 1) {\r\n warnings.push({\r\n type: 'unsupported-setting',\r\n setting: 'n',\r\n details:\r\n 'Runpod image models only support generating 1 image at a time. Using n=1.',\r\n });\r\n }\r\n\r\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\r\n\r\n // Runpod uses a different request format - /runsync endpoint with input wrapper\r\n const inputPayload = this.buildInputPayload(\r\n prompt,\r\n runpodSize,\r\n seed,\r\n providerOptions.runpod\r\n );\r\n\r\n const { value: response, responseHeaders } = await postJsonToApi({\r\n url: `${this.config.baseURL}/runsync`,\r\n headers: combineHeaders(this.config.headers(), headers),\r\n body: {\r\n input: inputPayload,\r\n },\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Unknown error',\r\n }),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageResponseSchema as any\r\n ),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n // Handle both sync and async responses from Runpod\r\n const typedResponse = response as any;\r\n if (\r\n typedResponse.status === 'COMPLETED' &&\r\n (typedResponse.output?.result || typedResponse.output?.image_url)\r\n ) {\r\n // Sync response - image is ready\r\n // Different models use different response formats: result vs image_url\r\n const imageUrl =\r\n typedResponse.output.result || typedResponse.output.image_url;\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n cost: typedResponse.output?.cost,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else if (\r\n typedResponse.status === 'IN_QUEUE' ||\r\n typedResponse.status === 'IN_PROGRESS'\r\n ) {\r\n // Async response - need to poll for completion\r\n const pollOptions = {\r\n maxAttempts: providerOptions.runpod?.maxPollAttempts as number,\r\n pollIntervalMillis: providerOptions.runpod\r\n ?.pollIntervalMillis as number,\r\n };\r\n const imageUrl = await this.pollForCompletion(\r\n typedResponse.id,\r\n abortSignal,\r\n pollOptions\r\n );\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n jobId: typedResponse.id,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else {\r\n throw new Error(`Unexpected response status: ${typedResponse.status}`);\r\n }\r\n }\r\n\r\n private async downloadImage(\r\n imageUrl: string,\r\n abortSignal?: AbortSignal\r\n ): Promise<Uint8Array> {\r\n const { value: imageData } = await getFromApi({\r\n url: imageUrl,\r\n successfulResponseHandler: createBinaryResponseHandler(),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Failed to download image',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n return imageData;\r\n }\r\n\r\n private async pollForCompletion(\r\n jobId: string,\r\n abortSignal?: AbortSignal,\r\n pollOptions?: { maxAttempts?: number; pollIntervalMillis?: number }\r\n ): Promise<string> {\r\n const maxAttempts = pollOptions?.maxAttempts ?? 60; // 5 minutes with 5-second intervals\r\n const pollInterval = pollOptions?.pollIntervalMillis ?? 5000; // 5 seconds\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n if (abortSignal?.aborted) {\r\n throw new Error('Image generation was aborted');\r\n }\r\n\r\n const { value: statusResponse } = await getFromApi({\r\n url: `${this.config.baseURL}/status/${jobId}`,\r\n headers: this.config.headers(),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageStatusSchema as any\r\n ),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) =>\r\n data.error ?? 'Failed to check job status',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n const typedStatusResponse = statusResponse as any;\r\n if (\r\n typedStatusResponse.status === 'COMPLETED' &&\r\n (typedStatusResponse.output?.result ||\r\n typedStatusResponse.output?.image_url)\r\n ) {\r\n return (\r\n typedStatusResponse.output.result ||\r\n typedStatusResponse.output.image_url\r\n );\r\n }\r\n\r\n if (typedStatusResponse.status === 'FAILED') {\r\n throw new Error(\r\n `Image generation failed: ${typedStatusResponse.error || 'Unknown error'}`\r\n );\r\n }\r\n\r\n // Wait before next poll\r\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\r\n }\r\n\r\n throw new Error(\r\n `Image generation timed out after ${maxAttempts} attempts (${(maxAttempts * pollInterval) / 1000}s)`\r\n );\r\n }\r\n\r\n private buildInputPayload(\r\n prompt: string,\r\n runpodSize: string,\r\n seed?: number,\r\n runpodOptions?: Record<string, unknown>\r\n ): Record<string, unknown> {\r\n // Check if this is a Flux model that uses different parameters\r\n const isFluxModel =\r\n this.modelId.includes('flux') ||\r\n this.modelId.includes('black-forest-labs');\r\n\r\n if (isFluxModel) {\r\n // Check if this is Flux Kontext (uses different parameters)\r\n const isKontext = this.modelId.includes('kontext');\r\n\r\n if (isKontext) {\r\n // Flux Kontext uses size format and has image input\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: 28,\r\n guidance: 2,\r\n size: runpodSize,\r\n output_format: 'png',\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions, // This will include the 'image' parameter if provided\r\n };\r\n } else {\r\n // Regular Flux models use width/height\r\n const [width, height] = runpodSize.split('*').map(Number);\r\n\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: this.modelId.includes('schnell') ? 4 : 28,\r\n guidance: this.modelId.includes('schnell') ? 7 : 2,\r\n width,\r\n height,\r\n image_format: 'png',\r\n ...runpodOptions,\r\n };\r\n }\r\n }\r\n\r\n // Default format for Qwen and other models\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n size: runpodSize,\r\n seed: seed ?? -1,\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions,\r\n };\r\n }\r\n}\r\n\r\n// Runpod image API response schema (handles both sync and async responses)\r\nconst runpodImageResponseSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n delayTime: z.number().optional(),\r\n executionTime: z.number().optional(),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(), // URL to the generated image (Qwen format)\r\n image_url: z.string().optional(), // URL to the generated image (Flux format)\r\n })\r\n .optional(), // Optional for IN_QUEUE/IN_PROGRESS responses\r\n});\r\n\r\n// Schema for polling status endpoint\r\nconst runpodImageStatusSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(),\r\n image_url: z.string().optional(),\r\n })\r\n .optional(),\r\n error: z.string().optional(), // Error message if FAILED\r\n});\r\n\r\n// Runpod image API error schema\r\nconst runpodImageErrorSchema = z.object({\r\n error: z.string(),\r\n message: z.string().optional(),\r\n});\r\n"],"mappings":"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","names":["import_provider_utils"]}
|
package/dist/index.mjs
CHANGED
|
@@ -39,6 +39,9 @@ var SUPPORTED_SIZES = /* @__PURE__ */ new Set([
|
|
|
39
39
|
"512*512",
|
|
40
40
|
"768*768",
|
|
41
41
|
"1024*1024",
|
|
42
|
+
"1536*1536",
|
|
43
|
+
"2048*2048",
|
|
44
|
+
"4096*4096",
|
|
42
45
|
"512*768",
|
|
43
46
|
"768*512",
|
|
44
47
|
"1024*768",
|
|
@@ -304,6 +307,9 @@ var IMAGE_MODEL_ID_TO_ENDPOINT_URL = {
|
|
|
304
307
|
"qwen/qwen-image": "https://api.runpod.ai/v2/qwen-image-t2i",
|
|
305
308
|
"qwen/qwen-image-edit": "https://api.runpod.ai/v2/qwen-image-edit",
|
|
306
309
|
"bytedance/seedream-3.0": "https://api.runpod.ai/v2/seedream-3-0-t2i",
|
|
310
|
+
// Seadream v4 (t2i and edit)
|
|
311
|
+
"bytedance/seedream-4.0": "https://api.runpod.ai/v2/seedream-v4-t2i",
|
|
312
|
+
"bytedance/seedream-4.0-edit": "https://api.runpod.ai/v2/seedream-v4-edit",
|
|
307
313
|
"black-forest-labs/flux-1-kontext-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev",
|
|
308
314
|
"black-forest-labs/flux-1-schnell": "https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell",
|
|
309
315
|
"black-forest-labs/flux-1-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-dev"
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runpod-provider.ts","../src/runpod-image-model.ts"],"sourcesContent":["import { LanguageModelV2, ImageModelV2 } from '@ai-sdk/provider';\nimport {\n OpenAICompatibleChatLanguageModel,\n OpenAICompatibleCompletionLanguageModel,\n} from '@ai-sdk/openai-compatible';\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n} from '@ai-sdk/provider-utils';\nimport { RunpodChatModelId } from './runpod-chat-options';\nimport { RunpodCompletionModelId } from './runpod-completion-options';\nimport { RunpodImageModelId } from './runpod-image-options';\nimport { RunpodImageModel } from './runpod-image-model';\n\nexport interface RunpodProviderSettings {\n /**\nRunpod API key.\n*/\n apiKey?: string;\n /**\nCustom base URL for Runpod API. Use this to point to custom endpoints or different Runpod deployments.\nExample: 'https://api.runpod.ai/v2/your-endpoint-id/openai/v1'\n*/\n baseURL?: string;\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\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 RunpodProvider {\n /**\nCreates a model for text generation.\n*/\n (modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n chatModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n languageModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a completion model for text generation.\n*/\n completionModel(modelId: RunpodCompletionModelId): LanguageModelV2;\n\n /**\nCreates an image model for image generation.\n*/\n imageModel(modelId: RunpodImageModelId): ImageModelV2;\n}\n\n// Mapping of Runpod model IDs to their endpoint URLs\nconst MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'https://api.runpod.ai/v2/deep-cogito-v2-llama-70b/openai/v1',\n 'qwen/qwen3-32b-awq': 'https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1',\n};\n\n// Mapping of Runpod image model IDs to their endpoint URLs\nconst IMAGE_MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'qwen/qwen-image': 'https://api.runpod.ai/v2/qwen-image-t2i',\n 'qwen/qwen-image-edit': 'https://api.runpod.ai/v2/qwen-image-edit',\n 'bytedance/seedream-3.0': 'https://api.runpod.ai/v2/seedream-3-0-t2i',\n 'black-forest-labs/flux-1-kontext-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev',\n 'black-forest-labs/flux-1-schnell':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell',\n 'black-forest-labs/flux-1-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-dev',\n};\n\n// Mapping of Runpod model IDs to their OpenAI model names\nconst MODEL_ID_TO_OPENAI_NAME: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'deepcogito/cogito-v2-preview-llama-70B',\n 'qwen/qwen3-32b-awq': 'Qwen/Qwen3-32B-AWQ',\n};\n\nexport function createRunpod(\n options: RunpodProviderSettings = {}\n): RunpodProvider {\n const getHeaders = () => ({\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'RUNPOD_API_KEY',\n description: 'Runpod',\n })}`,\n ...options.headers,\n });\n\n const runpodFetch: FetchFunction = async (url, requestInit) => {\n if (requestInit?.body) {\n try {\n const body = JSON.parse(requestInit.body as string);\n if (body.stream === true && !body.stream_options) {\n body.stream_options = { include_usage: true };\n requestInit.body = JSON.stringify(body);\n }\n } catch {}\n }\n const fetchFn = options.fetch || fetch;\n return fetchFn(url, requestInit);\n };\n\n interface CommonModelConfig {\n provider: string;\n url: ({ path }: { path: string }) => string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n }\n\n const getModelConfig = (\n modelId: string,\n modelType: string\n ): CommonModelConfig => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod model: ${modelId}. Supported models: ${Object.keys(\n MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: runpodFetch,\n };\n };\n\n const createChatModel = (modelId: RunpodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'chat'),\n includeUsage: true,\n });\n };\n\n const createCompletionModel = (modelId: RunpodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'completion'),\n includeUsage: true,\n });\n };\n\n const createImageModel = (modelId: RunpodImageModelId) => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod image model: ${modelId}. Supported models: ${Object.keys(\n IMAGE_MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return new RunpodImageModel(modelId, {\n provider: 'runpod.image',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n };\n\n const provider = (modelId: RunpodChatModelId) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n provider.imageModel = createImageModel;\n\n return provider;\n}\n\nexport const runpod = createRunpod();\n","import { ImageModelV2, ImageModelV2CallWarning } from '@ai-sdk/provider';\r\nimport {\r\n combineHeaders,\r\n createJsonResponseHandler,\r\n createJsonErrorResponseHandler,\r\n createBinaryResponseHandler,\r\n FetchFunction,\r\n postJsonToApi,\r\n getFromApi,\r\n} from '@ai-sdk/provider-utils';\r\nimport { InvalidArgumentError } from '@ai-sdk/provider';\r\nimport { z } from 'zod';\r\nimport { RunpodImageModelId } from './runpod-image-options';\r\n\r\ninterface RunpodImageModelConfig {\r\n provider: string;\r\n baseURL: string;\r\n headers: () => Record<string, string>;\r\n fetch?: FetchFunction;\r\n _internal?: {\r\n currentDate?: () => Date;\r\n };\r\n}\r\n\r\n// Runpod supported aspect ratios (only validated working sizes)\r\nconst SUPPORTED_ASPECT_RATIOS: Record<string, string> = {\r\n '1:1': '1328*1328', // ✅ Native support\r\n '4:3': '1472*1140', // ✅ Native support\r\n '3:4': '1140*1472', // ✅ Native support\r\n};\r\n\r\n// Runpod supported sizes (validated working sizes)\r\nconst SUPPORTED_SIZES = new Set([\r\n // Native aspect ratio sizes\r\n '1328*1328', // 1:1\r\n '1472*1140', // 4:3\r\n '1140*1472', // 3:4\r\n // Additional validated sizes\r\n '512*512',\r\n '768*768',\r\n '1024*1024',\r\n '512*768',\r\n '768*512',\r\n '1024*768',\r\n '768*1024',\r\n]);\r\n\r\nexport class RunpodImageModel implements ImageModelV2 {\r\n readonly specificationVersion = 'v2';\r\n readonly maxImagesPerCall = 1;\r\n\r\n get provider(): string {\r\n return this.config.provider;\r\n }\r\n\r\n constructor(\r\n readonly modelId: RunpodImageModelId,\r\n private config: RunpodImageModelConfig\r\n ) {}\r\n\r\n async doGenerate({\r\n prompt,\r\n n = 1,\r\n size,\r\n aspectRatio,\r\n seed,\r\n providerOptions,\r\n headers,\r\n abortSignal,\r\n }: Parameters<ImageModelV2['doGenerate']>[0]): Promise<\r\n Awaited<ReturnType<ImageModelV2['doGenerate']>>\r\n > {\r\n const warnings: Array<ImageModelV2CallWarning> = [];\r\n\r\n // Determine the size to use\r\n let runpodSize: string;\r\n\r\n if (size) {\r\n // Convert AI SDK format \"1328x1328\" to Runpod format \"1328*1328\"\r\n const runpodSizeCandidate = size.replace('x', '*');\r\n\r\n // Validate size is supported\r\n if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {\r\n throw new InvalidArgumentError({\r\n argument: 'size',\r\n message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(\r\n SUPPORTED_SIZES\r\n )\r\n .map((s) => s.replace('*', 'x'))\r\n .join(', ')}`,\r\n });\r\n }\r\n\r\n runpodSize = runpodSizeCandidate;\r\n } else if (aspectRatio) {\r\n // Validate aspect ratio is supported\r\n if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {\r\n throw new InvalidArgumentError({\r\n argument: 'aspectRatio',\r\n message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(', ')}`,\r\n });\r\n }\r\n\r\n // Use supported aspect ratio mapping\r\n runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];\r\n } else {\r\n // Default to square format\r\n runpodSize = '1328*1328';\r\n }\r\n\r\n // Handle multiple images warning\r\n if (n > 1) {\r\n warnings.push({\r\n type: 'unsupported-setting',\r\n setting: 'n',\r\n details:\r\n 'Runpod image models only support generating 1 image at a time. Using n=1.',\r\n });\r\n }\r\n\r\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\r\n\r\n // Runpod uses a different request format - /runsync endpoint with input wrapper\r\n const inputPayload = this.buildInputPayload(\r\n prompt,\r\n runpodSize,\r\n seed,\r\n providerOptions.runpod\r\n );\r\n\r\n const { value: response, responseHeaders } = await postJsonToApi({\r\n url: `${this.config.baseURL}/runsync`,\r\n headers: combineHeaders(this.config.headers(), headers),\r\n body: {\r\n input: inputPayload,\r\n },\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Unknown error',\r\n }),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageResponseSchema as any\r\n ),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n // Handle both sync and async responses from Runpod\r\n const typedResponse = response as any;\r\n if (\r\n typedResponse.status === 'COMPLETED' &&\r\n (typedResponse.output?.result || typedResponse.output?.image_url)\r\n ) {\r\n // Sync response - image is ready\r\n // Different models use different response formats: result vs image_url\r\n const imageUrl =\r\n typedResponse.output.result || typedResponse.output.image_url;\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n cost: typedResponse.output?.cost,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else if (\r\n typedResponse.status === 'IN_QUEUE' ||\r\n typedResponse.status === 'IN_PROGRESS'\r\n ) {\r\n // Async response - need to poll for completion\r\n const pollOptions = {\r\n maxAttempts: providerOptions.runpod?.maxPollAttempts as number,\r\n pollIntervalMillis: providerOptions.runpod\r\n ?.pollIntervalMillis as number,\r\n };\r\n const imageUrl = await this.pollForCompletion(\r\n typedResponse.id,\r\n abortSignal,\r\n pollOptions\r\n );\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n jobId: typedResponse.id,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else {\r\n throw new Error(`Unexpected response status: ${typedResponse.status}`);\r\n }\r\n }\r\n\r\n private async downloadImage(\r\n imageUrl: string,\r\n abortSignal?: AbortSignal\r\n ): Promise<Uint8Array> {\r\n const { value: imageData } = await getFromApi({\r\n url: imageUrl,\r\n successfulResponseHandler: createBinaryResponseHandler(),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Failed to download image',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n return imageData;\r\n }\r\n\r\n private async pollForCompletion(\r\n jobId: string,\r\n abortSignal?: AbortSignal,\r\n pollOptions?: { maxAttempts?: number; pollIntervalMillis?: number }\r\n ): Promise<string> {\r\n const maxAttempts = pollOptions?.maxAttempts ?? 60; // 5 minutes with 5-second intervals\r\n const pollInterval = pollOptions?.pollIntervalMillis ?? 5000; // 5 seconds\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n if (abortSignal?.aborted) {\r\n throw new Error('Image generation was aborted');\r\n }\r\n\r\n const { value: statusResponse } = await getFromApi({\r\n url: `${this.config.baseURL}/status/${jobId}`,\r\n headers: this.config.headers(),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageStatusSchema as any\r\n ),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) =>\r\n data.error ?? 'Failed to check job status',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n const typedStatusResponse = statusResponse as any;\r\n if (\r\n typedStatusResponse.status === 'COMPLETED' &&\r\n (typedStatusResponse.output?.result ||\r\n typedStatusResponse.output?.image_url)\r\n ) {\r\n return (\r\n typedStatusResponse.output.result ||\r\n typedStatusResponse.output.image_url\r\n );\r\n }\r\n\r\n if (typedStatusResponse.status === 'FAILED') {\r\n throw new Error(\r\n `Image generation failed: ${typedStatusResponse.error || 'Unknown error'}`\r\n );\r\n }\r\n\r\n // Wait before next poll\r\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\r\n }\r\n\r\n throw new Error(\r\n `Image generation timed out after ${maxAttempts} attempts (${(maxAttempts * pollInterval) / 1000}s)`\r\n );\r\n }\r\n\r\n private buildInputPayload(\r\n prompt: string,\r\n runpodSize: string,\r\n seed?: number,\r\n runpodOptions?: Record<string, unknown>\r\n ): Record<string, unknown> {\r\n // Check if this is a Flux model that uses different parameters\r\n const isFluxModel =\r\n this.modelId.includes('flux') ||\r\n this.modelId.includes('black-forest-labs');\r\n\r\n if (isFluxModel) {\r\n // Check if this is Flux Kontext (uses different parameters)\r\n const isKontext = this.modelId.includes('kontext');\r\n\r\n if (isKontext) {\r\n // Flux Kontext uses size format and has image input\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: 28,\r\n guidance: 2,\r\n size: runpodSize,\r\n output_format: 'png',\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions, // This will include the 'image' parameter if provided\r\n };\r\n } else {\r\n // Regular Flux models use width/height\r\n const [width, height] = runpodSize.split('*').map(Number);\r\n\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: this.modelId.includes('schnell') ? 4 : 28,\r\n guidance: this.modelId.includes('schnell') ? 7 : 2,\r\n width,\r\n height,\r\n image_format: 'png',\r\n ...runpodOptions,\r\n };\r\n }\r\n }\r\n\r\n // Default format for Qwen and other models\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n size: runpodSize,\r\n seed: seed ?? -1,\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions,\r\n };\r\n }\r\n}\r\n\r\n// Runpod image API response schema (handles both sync and async responses)\r\nconst runpodImageResponseSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n delayTime: z.number().optional(),\r\n executionTime: z.number().optional(),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(), // URL to the generated image (Qwen format)\r\n image_url: z.string().optional(), // URL to the generated image (Flux format)\r\n })\r\n .optional(), // Optional for IN_QUEUE/IN_PROGRESS responses\r\n});\r\n\r\n// Schema for polling status endpoint\r\nconst runpodImageStatusSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(),\r\n image_url: z.string().optional(),\r\n })\r\n .optional(),\r\n error: z.string().optional(), // Error message if FAILED\r\n});\r\n\r\n// Runpod image API error schema\r\nconst runpodImageErrorSchema = z.object({\r\n error: z.string(),\r\n message: z.string().optional(),\r\n});\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/runpod-provider.ts","../src/runpod-image-model.ts"],"sourcesContent":["import { LanguageModelV2, ImageModelV2 } from '@ai-sdk/provider';\nimport {\n OpenAICompatibleChatLanguageModel,\n OpenAICompatibleCompletionLanguageModel,\n} from '@ai-sdk/openai-compatible';\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n} from '@ai-sdk/provider-utils';\nimport { RunpodChatModelId } from './runpod-chat-options';\nimport { RunpodCompletionModelId } from './runpod-completion-options';\nimport { RunpodImageModelId } from './runpod-image-options';\nimport { RunpodImageModel } from './runpod-image-model';\n\nexport interface RunpodProviderSettings {\n /**\nRunpod API key.\n*/\n apiKey?: string;\n /**\nCustom base URL for Runpod API. Use this to point to custom endpoints or different Runpod deployments.\nExample: 'https://api.runpod.ai/v2/your-endpoint-id/openai/v1'\n*/\n baseURL?: string;\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\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 RunpodProvider {\n /**\nCreates a model for text generation.\n*/\n (modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n chatModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n languageModel(modelId: RunpodChatModelId): LanguageModelV2;\n\n /**\nCreates a completion model for text generation.\n*/\n completionModel(modelId: RunpodCompletionModelId): LanguageModelV2;\n\n /**\nCreates an image model for image generation.\n*/\n imageModel(modelId: RunpodImageModelId): ImageModelV2;\n}\n\n// Mapping of Runpod model IDs to their endpoint URLs\nconst MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'https://api.runpod.ai/v2/deep-cogito-v2-llama-70b/openai/v1',\n 'qwen/qwen3-32b-awq': 'https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1',\n};\n\n// Mapping of Runpod image model IDs to their endpoint URLs\nconst IMAGE_MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'qwen/qwen-image': 'https://api.runpod.ai/v2/qwen-image-t2i',\n 'qwen/qwen-image-edit': 'https://api.runpod.ai/v2/qwen-image-edit',\n 'bytedance/seedream-3.0': 'https://api.runpod.ai/v2/seedream-3-0-t2i',\n // Seadream v4 (t2i and edit)\n 'bytedance/seedream-4.0': 'https://api.runpod.ai/v2/seedream-v4-t2i',\n 'bytedance/seedream-4.0-edit': 'https://api.runpod.ai/v2/seedream-v4-edit',\n 'black-forest-labs/flux-1-kontext-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev',\n 'black-forest-labs/flux-1-schnell':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell',\n 'black-forest-labs/flux-1-dev':\n 'https://api.runpod.ai/v2/black-forest-labs-flux-1-dev',\n};\n\n// Mapping of Runpod model IDs to their OpenAI model names\nconst MODEL_ID_TO_OPENAI_NAME: Record<string, string> = {\n 'deep-cogito/deep-cogito-v2-llama-70b':\n 'deepcogito/cogito-v2-preview-llama-70B',\n 'qwen/qwen3-32b-awq': 'Qwen/Qwen3-32B-AWQ',\n};\n\nexport function createRunpod(\n options: RunpodProviderSettings = {}\n): RunpodProvider {\n const getHeaders = () => ({\n Authorization: `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'RUNPOD_API_KEY',\n description: 'Runpod',\n })}`,\n ...options.headers,\n });\n\n const runpodFetch: FetchFunction = async (url, requestInit) => {\n if (requestInit?.body) {\n try {\n const body = JSON.parse(requestInit.body as string);\n if (body.stream === true && !body.stream_options) {\n body.stream_options = { include_usage: true };\n requestInit.body = JSON.stringify(body);\n }\n } catch {}\n }\n const fetchFn = options.fetch || fetch;\n return fetchFn(url, requestInit);\n };\n\n interface CommonModelConfig {\n provider: string;\n url: ({ path }: { path: string }) => string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n }\n\n const getModelConfig = (\n modelId: string,\n modelType: string\n ): CommonModelConfig => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod model: ${modelId}. Supported models: ${Object.keys(\n MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: runpodFetch,\n };\n };\n\n const createChatModel = (modelId: RunpodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'chat'),\n includeUsage: true,\n });\n };\n\n const createCompletionModel = (modelId: RunpodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(openaiModelName, {\n ...getModelConfig(modelId, 'completion'),\n includeUsage: true,\n });\n };\n\n const createImageModel = (modelId: RunpodImageModelId) => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n baseURL = IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId];\n if (!baseURL) {\n throw new Error(\n `Unsupported Runpod image model: ${modelId}. Supported models: ${Object.keys(\n IMAGE_MODEL_ID_TO_ENDPOINT_URL\n ).join(', ')}. Or provide a custom baseURL.`\n );\n }\n }\n\n return new RunpodImageModel(modelId, {\n provider: 'runpod.image',\n baseURL,\n headers: getHeaders,\n fetch: options.fetch,\n });\n };\n\n const provider = (modelId: RunpodChatModelId) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n provider.imageModel = createImageModel;\n\n return provider;\n}\n\nexport const runpod = createRunpod();\n","import { ImageModelV2, ImageModelV2CallWarning } from '@ai-sdk/provider';\r\nimport {\r\n combineHeaders,\r\n createJsonResponseHandler,\r\n createJsonErrorResponseHandler,\r\n createBinaryResponseHandler,\r\n FetchFunction,\r\n postJsonToApi,\r\n getFromApi,\r\n} from '@ai-sdk/provider-utils';\r\nimport { InvalidArgumentError } from '@ai-sdk/provider';\r\nimport { z } from 'zod';\r\nimport { RunpodImageModelId } from './runpod-image-options';\r\n\r\ninterface RunpodImageModelConfig {\r\n provider: string;\r\n baseURL: string;\r\n headers: () => Record<string, string>;\r\n fetch?: FetchFunction;\r\n _internal?: {\r\n currentDate?: () => Date;\r\n };\r\n}\r\n\r\n// Runpod supported aspect ratios (only validated working sizes)\r\nconst SUPPORTED_ASPECT_RATIOS: Record<string, string> = {\r\n '1:1': '1328*1328', // ✅ Native support\r\n '4:3': '1472*1140', // ✅ Native support\r\n '3:4': '1140*1472', // ✅ Native support\r\n};\r\n\r\n// Runpod supported sizes (validated working sizes)\r\nconst SUPPORTED_SIZES = new Set([\r\n // Native aspect ratio sizes\r\n '1328*1328', // 1:1\r\n '1472*1140', // 4:3\r\n '1140*1472', // 3:4\r\n // Additional validated sizes\r\n '512*512',\r\n '768*768',\r\n '1024*1024',\r\n '1536*1536',\r\n '2048*2048',\r\n '4096*4096',\r\n '512*768',\r\n '768*512',\r\n '1024*768',\r\n '768*1024',\r\n]);\r\n\r\nexport class RunpodImageModel implements ImageModelV2 {\r\n readonly specificationVersion = 'v2';\r\n readonly maxImagesPerCall = 1;\r\n\r\n get provider(): string {\r\n return this.config.provider;\r\n }\r\n\r\n constructor(\r\n readonly modelId: RunpodImageModelId,\r\n private config: RunpodImageModelConfig\r\n ) {}\r\n\r\n async doGenerate({\r\n prompt,\r\n n = 1,\r\n size,\r\n aspectRatio,\r\n seed,\r\n providerOptions,\r\n headers,\r\n abortSignal,\r\n }: Parameters<ImageModelV2['doGenerate']>[0]): Promise<\r\n Awaited<ReturnType<ImageModelV2['doGenerate']>>\r\n > {\r\n const warnings: Array<ImageModelV2CallWarning> = [];\r\n\r\n // Determine the size to use\r\n let runpodSize: string;\r\n\r\n if (size) {\r\n // Convert AI SDK format \"1328x1328\" to Runpod format \"1328*1328\"\r\n const runpodSizeCandidate = size.replace('x', '*');\r\n\r\n // Validate size is supported\r\n if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {\r\n throw new InvalidArgumentError({\r\n argument: 'size',\r\n message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(\r\n SUPPORTED_SIZES\r\n )\r\n .map((s) => s.replace('*', 'x'))\r\n .join(', ')}`,\r\n });\r\n }\r\n\r\n runpodSize = runpodSizeCandidate;\r\n } else if (aspectRatio) {\r\n // Validate aspect ratio is supported\r\n if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {\r\n throw new InvalidArgumentError({\r\n argument: 'aspectRatio',\r\n message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(', ')}`,\r\n });\r\n }\r\n\r\n // Use supported aspect ratio mapping\r\n runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];\r\n } else {\r\n // Default to square format\r\n runpodSize = '1328*1328';\r\n }\r\n\r\n // Handle multiple images warning\r\n if (n > 1) {\r\n warnings.push({\r\n type: 'unsupported-setting',\r\n setting: 'n',\r\n details:\r\n 'Runpod image models only support generating 1 image at a time. Using n=1.',\r\n });\r\n }\r\n\r\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\r\n\r\n // Runpod uses a different request format - /runsync endpoint with input wrapper\r\n const inputPayload = this.buildInputPayload(\r\n prompt,\r\n runpodSize,\r\n seed,\r\n providerOptions.runpod\r\n );\r\n\r\n const { value: response, responseHeaders } = await postJsonToApi({\r\n url: `${this.config.baseURL}/runsync`,\r\n headers: combineHeaders(this.config.headers(), headers),\r\n body: {\r\n input: inputPayload,\r\n },\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Unknown error',\r\n }),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageResponseSchema as any\r\n ),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n // Handle both sync and async responses from Runpod\r\n const typedResponse = response as any;\r\n if (\r\n typedResponse.status === 'COMPLETED' &&\r\n (typedResponse.output?.result || typedResponse.output?.image_url)\r\n ) {\r\n // Sync response - image is ready\r\n // Different models use different response formats: result vs image_url\r\n const imageUrl =\r\n typedResponse.output.result || typedResponse.output.image_url;\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n cost: typedResponse.output?.cost,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else if (\r\n typedResponse.status === 'IN_QUEUE' ||\r\n typedResponse.status === 'IN_PROGRESS'\r\n ) {\r\n // Async response - need to poll for completion\r\n const pollOptions = {\r\n maxAttempts: providerOptions.runpod?.maxPollAttempts as number,\r\n pollIntervalMillis: providerOptions.runpod\r\n ?.pollIntervalMillis as number,\r\n };\r\n const imageUrl = await this.pollForCompletion(\r\n typedResponse.id,\r\n abortSignal,\r\n pollOptions\r\n );\r\n const imageData = await this.downloadImage(imageUrl, abortSignal);\r\n\r\n return {\r\n images: [imageData],\r\n warnings,\r\n response: {\r\n timestamp: currentDate,\r\n modelId: this.modelId,\r\n headers: responseHeaders,\r\n },\r\n providerMetadata: {\r\n runpod: {\r\n images: [\r\n {\r\n url: imageUrl,\r\n jobId: typedResponse.id,\r\n },\r\n ],\r\n },\r\n },\r\n };\r\n } else {\r\n throw new Error(`Unexpected response status: ${typedResponse.status}`);\r\n }\r\n }\r\n\r\n private async downloadImage(\r\n imageUrl: string,\r\n abortSignal?: AbortSignal\r\n ): Promise<Uint8Array> {\r\n const { value: imageData } = await getFromApi({\r\n url: imageUrl,\r\n successfulResponseHandler: createBinaryResponseHandler(),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) => data.error ?? 'Failed to download image',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n return imageData;\r\n }\r\n\r\n private async pollForCompletion(\r\n jobId: string,\r\n abortSignal?: AbortSignal,\r\n pollOptions?: { maxAttempts?: number; pollIntervalMillis?: number }\r\n ): Promise<string> {\r\n const maxAttempts = pollOptions?.maxAttempts ?? 60; // 5 minutes with 5-second intervals\r\n const pollInterval = pollOptions?.pollIntervalMillis ?? 5000; // 5 seconds\r\n\r\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\r\n if (abortSignal?.aborted) {\r\n throw new Error('Image generation was aborted');\r\n }\r\n\r\n const { value: statusResponse } = await getFromApi({\r\n url: `${this.config.baseURL}/status/${jobId}`,\r\n headers: this.config.headers(),\r\n successfulResponseHandler: createJsonResponseHandler(\r\n runpodImageStatusSchema as any\r\n ),\r\n failedResponseHandler: createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: any) =>\r\n data.error ?? 'Failed to check job status',\r\n }),\r\n abortSignal,\r\n fetch: this.config.fetch,\r\n });\r\n\r\n const typedStatusResponse = statusResponse as any;\r\n if (\r\n typedStatusResponse.status === 'COMPLETED' &&\r\n (typedStatusResponse.output?.result ||\r\n typedStatusResponse.output?.image_url)\r\n ) {\r\n return (\r\n typedStatusResponse.output.result ||\r\n typedStatusResponse.output.image_url\r\n );\r\n }\r\n\r\n if (typedStatusResponse.status === 'FAILED') {\r\n throw new Error(\r\n `Image generation failed: ${typedStatusResponse.error || 'Unknown error'}`\r\n );\r\n }\r\n\r\n // Wait before next poll\r\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\r\n }\r\n\r\n throw new Error(\r\n `Image generation timed out after ${maxAttempts} attempts (${(maxAttempts * pollInterval) / 1000}s)`\r\n );\r\n }\r\n\r\n private buildInputPayload(\r\n prompt: string,\r\n runpodSize: string,\r\n seed?: number,\r\n runpodOptions?: Record<string, unknown>\r\n ): Record<string, unknown> {\r\n // Check if this is a Flux model that uses different parameters\r\n const isFluxModel =\r\n this.modelId.includes('flux') ||\r\n this.modelId.includes('black-forest-labs');\r\n\r\n if (isFluxModel) {\r\n // Check if this is Flux Kontext (uses different parameters)\r\n const isKontext = this.modelId.includes('kontext');\r\n\r\n if (isKontext) {\r\n // Flux Kontext uses size format and has image input\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: 28,\r\n guidance: 2,\r\n size: runpodSize,\r\n output_format: 'png',\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions, // This will include the 'image' parameter if provided\r\n };\r\n } else {\r\n // Regular Flux models use width/height\r\n const [width, height] = runpodSize.split('*').map(Number);\r\n\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n seed: seed ?? -1,\r\n num_inference_steps: this.modelId.includes('schnell') ? 4 : 28,\r\n guidance: this.modelId.includes('schnell') ? 7 : 2,\r\n width,\r\n height,\r\n image_format: 'png',\r\n ...runpodOptions,\r\n };\r\n }\r\n }\r\n\r\n // Default format for Qwen and other models\r\n return {\r\n prompt,\r\n negative_prompt: runpodOptions?.negative_prompt ?? '',\r\n size: runpodSize,\r\n seed: seed ?? -1,\r\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\r\n ...runpodOptions,\r\n };\r\n }\r\n}\r\n\r\n// Runpod image API response schema (handles both sync and async responses)\r\nconst runpodImageResponseSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n delayTime: z.number().optional(),\r\n executionTime: z.number().optional(),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(), // URL to the generated image (Qwen format)\r\n image_url: z.string().optional(), // URL to the generated image (Flux format)\r\n })\r\n .optional(), // Optional for IN_QUEUE/IN_PROGRESS responses\r\n});\r\n\r\n// Schema for polling status endpoint\r\nconst runpodImageStatusSchema = z.object({\r\n id: z.string(),\r\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\r\n output: z\r\n .object({\r\n cost: z.number().optional(),\r\n result: z.string().optional(),\r\n image_url: z.string().optional(),\r\n })\r\n .optional(),\r\n error: z.string().optional(), // Error message if FAILED\r\n});\r\n\r\n// Runpod image API error schema\r\nconst runpodImageErrorSchema = z.object({\r\n error: z.string(),\r\n message: z.string().optional(),\r\n});\r\n"],"mappings":"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","names":[]}
|