@runpod/ai-sdk-provider 0.12.0 → 1.0.1

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/dist/index.js CHANGED
@@ -98,7 +98,7 @@ var RunpodImageModel = class {
98
98
  constructor(modelId, config) {
99
99
  this.modelId = modelId;
100
100
  this.config = config;
101
- this.specificationVersion = "v2";
101
+ this.specificationVersion = "v3";
102
102
  this.maxImagesPerCall = 1;
103
103
  }
104
104
  get provider() {
@@ -106,15 +106,25 @@ var RunpodImageModel = class {
106
106
  }
107
107
  async doGenerate({
108
108
  prompt,
109
- n = 1,
109
+ n,
110
110
  size,
111
111
  aspectRatio,
112
112
  seed,
113
+ files,
114
+ mask,
113
115
  providerOptions,
114
116
  headers,
115
117
  abortSignal
116
118
  }) {
117
119
  const warnings = [];
120
+ const standardizedImages = this.convertFilesToRunpodFormat(files);
121
+ if (mask) {
122
+ warnings.push({
123
+ type: "unsupported",
124
+ feature: "mask",
125
+ details: "Mask input for inpainting is not yet supported."
126
+ });
127
+ }
118
128
  const isPrunaModel = this.modelId.includes("pruna") || this.modelId.includes("p-image");
119
129
  const isNanoBananaProModel = this.modelId.includes("nano-banana-pro");
120
130
  let runpodSize;
@@ -144,18 +154,19 @@ var RunpodImageModel = class {
144
154
  }
145
155
  if (n > 1) {
146
156
  warnings.push({
147
- type: "unsupported-setting",
148
- setting: "n",
157
+ type: "unsupported",
158
+ feature: "multiple images (n > 1)",
149
159
  details: "Runpod image models only support generating 1 image at a time. Using n=1."
150
160
  });
151
161
  }
152
162
  const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
153
163
  const inputPayload = this.buildInputPayload(
154
- prompt,
164
+ prompt ?? "",
155
165
  runpodSize,
156
166
  seed,
157
167
  providerOptions.runpod,
158
- aspectRatio
168
+ aspectRatio,
169
+ standardizedImages
159
170
  );
160
171
  const { value: response, responseHeaders } = await (0, import_provider_utils2.postJsonToApi)({
161
172
  url: `${this.config.baseURL}/runsync`,
@@ -269,12 +280,44 @@ var RunpodImageModel = class {
269
280
  `Image generation timed out after ${maxAttempts} attempts (${maxAttempts * pollInterval / 1e3}s)`
270
281
  );
271
282
  }
272
- buildInputPayload(prompt, runpodSize, seed, runpodOptions, aspectRatio) {
283
+ /**
284
+ * Converts standardized ImageModelV3File[] to Runpod-compatible format.
285
+ * Returns URLs or base64 data URLs that Runpod API accepts.
286
+ */
287
+ convertFilesToRunpodFormat(files) {
288
+ if (!files || files.length === 0) {
289
+ return void 0;
290
+ }
291
+ return files.map((file) => {
292
+ if (file.type === "url") {
293
+ return file.url;
294
+ }
295
+ if (typeof file.data === "string") {
296
+ if (file.data.startsWith("data:")) {
297
+ return file.data;
298
+ }
299
+ return `data:${file.mediaType};base64,${file.data}`;
300
+ }
301
+ const base64 = this.uint8ArrayToBase64(file.data);
302
+ return `data:${file.mediaType};base64,${base64}`;
303
+ });
304
+ }
305
+ /**
306
+ * Converts Uint8Array to base64 string.
307
+ */
308
+ uint8ArrayToBase64(data) {
309
+ let binary = "";
310
+ for (let i = 0; i < data.length; i++) {
311
+ binary += String.fromCharCode(data[i]);
312
+ }
313
+ return btoa(binary);
314
+ }
315
+ buildInputPayload(prompt, runpodSize, seed, runpodOptions, aspectRatio, standardizedImages) {
273
316
  const isFluxModel = this.modelId.includes("flux") || this.modelId.includes("black-forest-labs");
274
317
  if (isFluxModel) {
275
318
  const isKontext = this.modelId.includes("kontext");
276
319
  if (isKontext) {
277
- return {
320
+ const kontextPayload = {
278
321
  prompt,
279
322
  negative_prompt: runpodOptions?.negative_prompt ?? "",
280
323
  seed: seed ?? -1,
@@ -284,8 +327,11 @@ var RunpodImageModel = class {
284
327
  output_format: "png",
285
328
  enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
286
329
  ...runpodOptions
287
- // This will include the 'image' parameter if provided
288
330
  };
331
+ if (standardizedImages && standardizedImages.length > 0) {
332
+ kontextPayload.image = standardizedImages[0];
333
+ }
334
+ return kontextPayload;
289
335
  } else {
290
336
  const [width, height] = runpodSize.split("*").map(Number);
291
337
  return {
@@ -315,7 +361,9 @@ var RunpodImageModel = class {
315
361
  } else if (runpodOptions?.seed !== void 0) {
316
362
  editPayload.seed = runpodOptions.seed;
317
363
  }
318
- if (runpodOptions?.images) {
364
+ if (standardizedImages && standardizedImages.length > 0) {
365
+ editPayload.images = standardizedImages;
366
+ } else if (runpodOptions?.images) {
319
367
  editPayload.images = runpodOptions.images;
320
368
  }
321
369
  return editPayload;
@@ -351,12 +399,14 @@ var RunpodImageModel = class {
351
399
  enable_base64_output: runpodOptions?.enable_base64_output ?? false,
352
400
  enable_sync_mode: runpodOptions?.enable_sync_mode ?? false
353
401
  };
354
- if (runpodOptions?.images) {
402
+ if (standardizedImages && standardizedImages.length > 0) {
403
+ nanoBananaPayload.images = standardizedImages;
404
+ } else if (runpodOptions?.images) {
355
405
  nanoBananaPayload.images = runpodOptions.images;
356
406
  }
357
407
  return nanoBananaPayload;
358
408
  }
359
- return {
409
+ const defaultPayload = {
360
410
  prompt,
361
411
  negative_prompt: runpodOptions?.negative_prompt ?? "",
362
412
  size: runpodSize,
@@ -364,6 +414,14 @@ var RunpodImageModel = class {
364
414
  enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
365
415
  ...runpodOptions
366
416
  };
417
+ if (standardizedImages && standardizedImages.length > 0) {
418
+ if (standardizedImages.length === 1) {
419
+ defaultPayload.image = standardizedImages[0];
420
+ } else {
421
+ defaultPayload.images = standardizedImages;
422
+ }
423
+ }
424
+ return defaultPayload;
367
425
  }
368
426
  };
369
427
  var runpodImageResponseSchema = import_zod2.z.object({
@@ -404,7 +462,7 @@ var RunpodSpeechModel = class {
404
462
  constructor(modelId, config) {
405
463
  this.modelId = modelId;
406
464
  this.config = config;
407
- this.specificationVersion = "v2";
465
+ this.specificationVersion = "v3";
408
466
  }
409
467
  get provider() {
410
468
  return this.config.provider;
@@ -432,29 +490,29 @@ var RunpodSpeechModel = class {
432
490
  } = options;
433
491
  if (outputFormat != null && outputFormat !== "wav") {
434
492
  warnings.push({
435
- type: "unsupported-setting",
436
- setting: "outputFormat",
493
+ type: "unsupported",
494
+ feature: "outputFormat",
437
495
  details: `Unsupported outputFormat: ${outputFormat}. This endpoint returns 'wav'.`
438
496
  });
439
497
  }
440
498
  if (instructions != null) {
441
499
  warnings.push({
442
- type: "unsupported-setting",
443
- setting: "instructions",
500
+ type: "unsupported",
501
+ feature: "instructions",
444
502
  details: `Instructions are not supported by this speech endpoint.`
445
503
  });
446
504
  }
447
505
  if (speed != null) {
448
506
  warnings.push({
449
- type: "unsupported-setting",
450
- setting: "speed",
507
+ type: "unsupported",
508
+ feature: "speed",
451
509
  details: `Speed is not supported by this speech endpoint.`
452
510
  });
453
511
  }
454
512
  if (language != null) {
455
513
  warnings.push({
456
- type: "unsupported-setting",
457
- setting: "language",
514
+ type: "unsupported",
515
+ feature: "language",
458
516
  details: `Language selection is not supported by this speech endpoint.`
459
517
  });
460
518
  }
@@ -672,6 +730,7 @@ function createRunpod(options = {}) {
672
730
  provider.languageModel = createChatModel;
673
731
  provider.chatModel = createChatModel;
674
732
  provider.imageModel = createImageModel;
733
+ provider.image = createImageModel;
675
734
  provider.speechModel = createSpeechModel;
676
735
  provider.speech = createSpeechModel;
677
736
  return provider;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/runpod-provider.ts","../src/runpod-image-model.ts","../src/runpod-error.ts","../src/runpod-speech-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';\nexport type { RunpodImageErrorData } from './runpod-error';\n","import { ImageModelV2, LanguageModelV2, SpeechModelV2 } 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 { RunpodImageModel } from './runpod-image-model';\nimport { RunpodSpeechModel } from './runpod-speech-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: string): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n chatModel(modelId: string): LanguageModelV2;\n\n /**\nCreates a chat model for text generation.\n*/\n languageModel(modelId: string): LanguageModelV2;\n\n /**\nCreates a completion model for text generation.\n*/\n completionModel(modelId: string): LanguageModelV2;\n\n /**\nCreates an image model for image generation.\n*/\n imageModel(modelId: string): ImageModelV2;\n\n /**\nCreates a speech model for speech generation.\n*/\n speechModel(modelId: string): SpeechModelV2;\n\n /**\nCreates a speech model for speech generation.\n*/\n speech(modelId: string): SpeechModelV2;\n}\n\n// Mapping of Runpod model IDs to their endpoint URLs\nconst MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'qwen/qwen3-32b-awq': 'https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1',\n 'ibm-granite/granite-4.0-h-small':\n 'https://api.runpod.ai/v2/granite-4-0-h-small/openai/v1',\n 'gpt-oss-120b': 'https://api.runpod.ai/v2/gpt-oss-120b/openai/v1',\n 'openai/gpt-oss-120b': 'https://api.runpod.ai/v2/gpt-oss-120b/openai/v1',\n 'deepcogito/cogito-671b-v2.1-fp8':\n 'https://api.runpod.ai/v2/cogito-671b-v2-1-fp8-dynamic/openai/v1',\n 'deepcogito/cogito-671b-v2.1-FP8':\n 'https://api.runpod.ai/v2/cogito-671b-v2-1-fp8-dynamic/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 // Nano Banana (edit only)\n 'nano-banana-edit': 'https://api.runpod.ai/v2/nano-banana-edit',\n // Nano Banana Pro (edit only)\n 'google/nano-banana-pro-edit':\n 'https://api.runpod.ai/v2/nano-banana-pro-edit',\n // Pruna (t2i and edit)\n 'pruna/p-image-t2i': 'https://api.runpod.ai/v2/p-image-t2i',\n 'pruna/p-image-edit': 'https://api.runpod.ai/v2/p-image-edit',\n};\n\n// Mapping of Runpod speech model IDs to their serverless endpoint URLs\n// Note: This is intentionally a temporary mapping for a stealth release.\nconst SPEECH_MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'resembleai/chatterbox-turbo': 'https://api.runpod.ai/v2/chatterbox-turbo/',\n};\n\n// Mapping of Runpod model IDs to their OpenAI model names\nconst MODEL_ID_TO_OPENAI_NAME: Record<string, string> = {\n 'qwen/qwen3-32b-awq': 'Qwen/Qwen3-32B-AWQ',\n 'deepcogito/cogito-671b-v2.1-fp8': 'deepcogito/cogito-671b-v2.1-FP8',\n 'deepcogito/cogito-671b-v2.1-FP8': 'deepcogito/cogito-671b-v2.1-FP8',\n};\n\n/**\n * Derives the endpoint URL for a model by replacing slashes with hyphens.\n * Example: 'ibm-granite/granite-4.0-h-small' -> 'https://api.runpod.ai/v2/ibm-granite-granite-4.0-h-small/openai/v1'\n */\nfunction deriveEndpointURL(modelId: string): string {\n const normalized = modelId.replace(/\\//g, '-');\n return `https://api.runpod.ai/v2/${normalized}/openai/v1`;\n}\n\nfunction parseRunpodConsoleEndpointId(modelIdOrUrl: string): string | null {\n if (!modelIdOrUrl.startsWith('http')) {\n return null;\n }\n\n try {\n const url = new URL(modelIdOrUrl);\n if (url.hostname !== 'console.runpod.io') {\n return null;\n }\n\n // Example:\n // https://console.runpod.io/serverless/user/endpoint/<ENDPOINT_ID>\n const parts = url.pathname.split('/').filter(Boolean);\n const idx = parts.lastIndexOf('endpoint');\n const endpointId = idx !== -1 ? parts[idx + 1] : undefined;\n\n return endpointId || null;\n } catch {\n return null;\n }\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 // Use hardcoded mapping if available, otherwise derive endpoint\n baseURL = MODEL_ID_TO_ENDPOINT_URL[modelId] || deriveEndpointURL(modelId);\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: string) => {\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: string) => {\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: string) => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n // Use hardcoded mapping if available, otherwise derive endpoint\n baseURL =\n IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId] || deriveEndpointURL(modelId);\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 createSpeechModel = (modelId: string) => {\n const endpointIdFromConsole = parseRunpodConsoleEndpointId(modelId);\n const normalizedModelId = endpointIdFromConsole ?? modelId;\n\n // Prefer explicit mapping for known speech model IDs.\n const mappedBaseURL = SPEECH_MODEL_ID_TO_ENDPOINT_URL[normalizedModelId];\n\n const baseURL =\n mappedBaseURL ??\n (normalizedModelId.startsWith('http')\n ? normalizedModelId\n : `https://api.runpod.ai/v2/${normalizedModelId}`);\n\n return new RunpodSpeechModel(normalizedModelId, {\n provider: 'runpod.speech',\n baseURL,\n headers: getHeaders,\n fetch: runpodFetch,\n });\n };\n\n const provider = (modelId: string) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n provider.imageModel = createImageModel;\n provider.speechModel = createSpeechModel;\n provider.speech = createSpeechModel;\n\n return provider;\n}\n\nexport const runpod = createRunpod();\n","import { ImageModelV2, ImageModelV2CallWarning } from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createJsonResponseHandler,\n createBinaryResponseHandler,\n FetchFunction,\n postJsonToApi,\n getFromApi,\n} from '@ai-sdk/provider-utils';\nimport { InvalidArgumentError } from '@ai-sdk/provider';\nimport { z } from 'zod';\nimport { runpodImageFailedResponseHandler } from './runpod-error';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ninterface RunpodImageModelConfig {\n provider: string;\n baseURL: string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\n// Runpod supported aspect ratios (only validated working sizes)\nconst SUPPORTED_ASPECT_RATIOS: Record<string, string> = {\n '1:1': '1328*1328', // ✅ Native support\n '4:3': '1472*1140', // ✅ Native support\n '3:4': '1140*1472', // ✅ Native support\n};\n\n// Runpod supported sizes (validated working sizes)\nconst SUPPORTED_SIZES = new Set([\n // Native aspect ratio sizes\n '1328*1328', // 1:1\n '1472*1140', // 4:3\n '1140*1472', // 3:4\n // Additional validated sizes\n '512*512',\n '768*768',\n '1024*1024',\n '1536*1536',\n '2048*2048',\n '4096*4096',\n '512*768',\n '768*512',\n '1024*768',\n '768*1024',\n]);\n\nexport class RunpodImageModel implements ImageModelV2 {\n readonly specificationVersion = 'v2';\n readonly maxImagesPerCall = 1;\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: string,\n private config: RunpodImageModelConfig\n ) {}\n\n async doGenerate({\n prompt,\n n = 1,\n size,\n aspectRatio,\n seed,\n providerOptions,\n headers,\n abortSignal,\n }: Parameters<ImageModelV2['doGenerate']>[0]): Promise<\n Awaited<ReturnType<ImageModelV2['doGenerate']>>\n > {\n const warnings: Array<ImageModelV2CallWarning> = [];\n\n // Check if this is a Pruna model (skip standard size/aspectRatio validation)\n const isPrunaModel =\n this.modelId.includes('pruna') || this.modelId.includes('p-image');\n\n // Check if this is a Nano Banana Pro model (skip standard size/aspectRatio validation)\n const isNanoBananaProModel = this.modelId.includes('nano-banana-pro');\n\n // Determine the size to use\n let runpodSize: string;\n\n if (isPrunaModel || isNanoBananaProModel) {\n // These models use aspect_ratio string directly, skip size validation\n // Pass through the aspectRatio or use default, validation happens at API level\n runpodSize = aspectRatio || '1:1';\n } else if (size) {\n // Convert AI SDK format \"1328x1328\" to Runpod format \"1328*1328\"\n const runpodSizeCandidate = size.replace('x', '*');\n\n // Validate size is supported\n if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {\n throw new InvalidArgumentError({\n argument: 'size',\n message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(\n SUPPORTED_SIZES\n )\n .map((s) => s.replace('*', 'x'))\n .join(', ')}`,\n });\n }\n\n runpodSize = runpodSizeCandidate;\n } else if (aspectRatio) {\n // Validate aspect ratio is supported\n if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {\n throw new InvalidArgumentError({\n argument: 'aspectRatio',\n message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(', ')}`,\n });\n }\n\n // Use supported aspect ratio mapping\n runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];\n } else {\n // Default to square format\n runpodSize = '1328*1328';\n }\n\n // Handle multiple images warning\n if (n > 1) {\n warnings.push({\n type: 'unsupported-setting',\n setting: 'n',\n details:\n 'Runpod image models only support generating 1 image at a time. Using n=1.',\n });\n }\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n // Runpod uses a different request format - /runsync endpoint with input wrapper\n const inputPayload = this.buildInputPayload(\n prompt,\n runpodSize,\n seed,\n providerOptions.runpod,\n aspectRatio\n );\n\n const { value: response, responseHeaders } = await postJsonToApi({\n url: `${this.config.baseURL}/runsync`,\n headers: combineHeaders(this.config.headers(), headers),\n body: {\n input: inputPayload,\n },\n failedResponseHandler: runpodImageFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n runpodImageResponseSchema as any\n ),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n // Handle both sync and async responses from Runpod\n const typedResponse = response as any;\n if (\n typedResponse.status === 'COMPLETED' &&\n (typedResponse.output?.result || typedResponse.output?.image_url)\n ) {\n // Sync response - image is ready\n // Different models use different response formats: result vs image_url\n const imageUrl =\n typedResponse.output.result || typedResponse.output.image_url;\n const imageData = await this.downloadImage(imageUrl, abortSignal);\n\n return {\n images: [imageData],\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n providerMetadata: {\n runpod: {\n images: [\n {\n url: imageUrl,\n cost: typedResponse.output?.cost,\n },\n ],\n },\n },\n };\n } else if (\n typedResponse.status === 'IN_QUEUE' ||\n typedResponse.status === 'IN_PROGRESS'\n ) {\n // Async response - need to poll for completion\n const pollOptions = {\n maxAttempts: providerOptions.runpod?.maxPollAttempts as number,\n pollIntervalMillis: providerOptions.runpod\n ?.pollIntervalMillis as number,\n };\n const imageUrl = await this.pollForCompletion(\n typedResponse.id,\n abortSignal,\n pollOptions\n );\n const imageData = await this.downloadImage(imageUrl, abortSignal);\n\n return {\n images: [imageData],\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n providerMetadata: {\n runpod: {\n images: [\n {\n url: imageUrl,\n jobId: typedResponse.id,\n },\n ],\n },\n },\n };\n } else {\n throw new Error(`Unexpected response status: ${typedResponse.status}`);\n }\n }\n\n private async downloadImage(\n imageUrl: string,\n abortSignal?: AbortSignal\n ): Promise<Uint8Array> {\n const { value: imageData } = await getFromApi({\n url: imageUrl,\n successfulResponseHandler: createBinaryResponseHandler(),\n failedResponseHandler: runpodImageFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n return imageData;\n }\n\n private async pollForCompletion(\n jobId: string,\n abortSignal?: AbortSignal,\n pollOptions?: { maxAttempts?: number; pollIntervalMillis?: number }\n ): Promise<string> {\n const maxAttempts = pollOptions?.maxAttempts ?? 60; // 5 minutes with 5-second intervals\n const pollInterval = pollOptions?.pollIntervalMillis ?? 5000; // 5 seconds\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (abortSignal?.aborted) {\n throw new Error('Image generation was aborted');\n }\n\n const { value: statusResponse } = await getFromApi({\n url: `${this.config.baseURL}/status/${jobId}`,\n headers: this.config.headers(),\n successfulResponseHandler: createJsonResponseHandler(\n runpodImageStatusSchema as any\n ),\n failedResponseHandler: runpodImageFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const typedStatusResponse = statusResponse as any;\n if (\n typedStatusResponse.status === 'COMPLETED' &&\n (typedStatusResponse.output?.result ||\n typedStatusResponse.output?.image_url)\n ) {\n return (\n typedStatusResponse.output.result ||\n typedStatusResponse.output.image_url\n );\n }\n\n if (typedStatusResponse.status === 'FAILED') {\n throw new Error(\n `Image generation failed: ${typedStatusResponse.error || 'Unknown error'}`\n );\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(\n `Image generation timed out after ${maxAttempts} attempts (${(maxAttempts * pollInterval) / 1000}s)`\n );\n }\n\n private buildInputPayload(\n prompt: string,\n runpodSize: string,\n seed?: number,\n runpodOptions?: Record<string, unknown>,\n aspectRatio?: string\n ): Record<string, unknown> {\n // Check if this is a Flux model that uses different parameters\n const isFluxModel =\n this.modelId.includes('flux') ||\n this.modelId.includes('black-forest-labs');\n\n if (isFluxModel) {\n // Check if this is Flux Kontext (uses different parameters)\n const isKontext = this.modelId.includes('kontext');\n\n if (isKontext) {\n // Flux Kontext uses size format and has image input\n return {\n prompt,\n negative_prompt: runpodOptions?.negative_prompt ?? '',\n seed: seed ?? -1,\n num_inference_steps: 28,\n guidance: 2,\n size: runpodSize,\n output_format: 'png',\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\n ...runpodOptions, // This will include the 'image' parameter if provided\n };\n } else {\n // Regular Flux models use width/height\n const [width, height] = runpodSize.split('*').map(Number);\n\n return {\n prompt,\n negative_prompt: runpodOptions?.negative_prompt ?? '',\n seed: seed ?? -1,\n num_inference_steps: this.modelId.includes('schnell') ? 4 : 28,\n guidance: this.modelId.includes('schnell') ? 7 : 2,\n width,\n height,\n image_format: 'png',\n ...runpodOptions,\n };\n }\n }\n\n // Check if this is a Pruna model\n const isPrunaModel =\n this.modelId.includes('pruna') || this.modelId.includes('p-image');\n if (isPrunaModel) {\n const isPrunaEdit = this.modelId.includes('edit');\n\n if (isPrunaEdit) {\n // Pruna image edit\n // Supported aspect_ratio: \"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\"\n // Supports 1-5 images via providerOptions.runpod.images\n const editPayload: Record<string, unknown> = {\n prompt,\n aspect_ratio:\n (runpodOptions?.aspect_ratio as string) ?? aspectRatio ?? '1:1',\n disable_safety_checker:\n (runpodOptions?.disable_safety_checker as boolean) ?? false,\n };\n\n // Add seed if provided\n if (seed !== undefined) {\n editPayload.seed = seed;\n } else if (runpodOptions?.seed !== undefined) {\n editPayload.seed = runpodOptions.seed;\n }\n\n // Add images array (required, 1-5 images)\n if (runpodOptions?.images) {\n editPayload.images = runpodOptions.images;\n }\n\n return editPayload;\n } else {\n // Pruna text-to-image\n // Supported aspect_ratio: \"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\", \"custom\"\n // For custom: width/height 256-1440, must be multiple of 16\n const t2iPayload: Record<string, unknown> = {\n prompt,\n aspect_ratio:\n (runpodOptions?.aspect_ratio as string) ?? aspectRatio ?? '1:1',\n disable_safety_checker:\n (runpodOptions?.disable_safety_checker as boolean) ?? false,\n };\n\n // Add seed if provided\n if (seed !== undefined) {\n t2iPayload.seed = seed;\n } else if (runpodOptions?.seed !== undefined) {\n t2iPayload.seed = runpodOptions.seed;\n }\n\n // Handle custom aspect ratio with width/height\n if (t2iPayload.aspect_ratio === 'custom') {\n if (runpodOptions?.width) {\n t2iPayload.width = runpodOptions.width;\n }\n if (runpodOptions?.height) {\n t2iPayload.height = runpodOptions.height;\n }\n }\n\n return t2iPayload;\n }\n }\n\n // Check if this is a Nano Banana Pro model (google/nano-banana-pro-edit)\n const isNanaBananaProModel = this.modelId.includes('nano-banana-pro');\n if (isNanaBananaProModel) {\n // Nano Banana Pro image edit\n // Supported aspect_ratio: \"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\", \"21:9\", \"9:21\"\n // Supported resolution: \"1k\", \"2k\", \"4k\"\n // Supported output_format: \"jpeg\", \"png\", \"webp\"\n const nanoBananaPayload: Record<string, unknown> = {\n prompt,\n aspect_ratio:\n (runpodOptions?.aspect_ratio as string) ?? aspectRatio ?? '1:1',\n resolution: (runpodOptions?.resolution as string) ?? '1k',\n output_format: (runpodOptions?.output_format as string) ?? 'jpeg',\n enable_base64_output:\n (runpodOptions?.enable_base64_output as boolean) ?? false,\n enable_sync_mode:\n (runpodOptions?.enable_sync_mode as boolean) ?? false,\n };\n\n // Add images array (required)\n if (runpodOptions?.images) {\n nanoBananaPayload.images = runpodOptions.images;\n }\n\n return nanoBananaPayload;\n }\n\n // Default format for Qwen and other models\n return {\n prompt,\n negative_prompt: runpodOptions?.negative_prompt ?? '',\n size: runpodSize,\n seed: seed ?? -1,\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\n ...runpodOptions,\n };\n }\n}\n\n// Runpod image API response schema (handles both sync and async responses)\nconst runpodImageResponseSchema = z.object({\n id: z.string(),\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\n delayTime: z.number().optional(),\n executionTime: z.number().optional(),\n output: z\n .object({\n cost: z.number().optional(),\n result: z.string().optional(), // URL to the generated image (Qwen format)\n image_url: z.string().optional(), // URL to the generated image (Flux format)\n })\n .optional(), // Optional for IN_QUEUE/IN_PROGRESS responses\n});\n\n// Schema for polling status endpoint\nconst runpodImageStatusSchema = z.object({\n id: z.string(),\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\n output: z\n .object({\n cost: z.number().optional(),\n result: z.string().optional(),\n image_url: z.string().optional(),\n })\n .optional(),\n error: z.string().optional(), // Error message if FAILED\n});\n","import { z } from 'zod';\r\nimport { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\r\n\r\n// Runpod image API error schema (supports both error formats)\r\nexport const runpodImageErrorSchema = z.object({\r\n error: z.string().optional(),\r\n message: z.string().optional(),\r\n});\r\n\r\nexport type RunpodImageErrorData = z.infer<typeof runpodImageErrorSchema>;\r\n\r\nexport const runpodImageFailedResponseHandler = createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: RunpodImageErrorData) => {\r\n // Prefer message if available (more descriptive)\r\n if (data.message) {\r\n return data.message;\r\n }\r\n \r\n // If error field exists, try to extract nested JSON message\r\n if (data.error) {\r\n // Runpod sometimes returns nested JSON in the error field like:\r\n // \"Error submitting task: 400, {\\\"code\\\":400,\\\"message\\\":\\\"...\\\"}\"\r\n // Try to extract the inner message for cleaner error messages\r\n // Find the last occurrence of { which likely starts the JSON object\r\n const lastBraceIndex = data.error.lastIndexOf('{');\r\n if (lastBraceIndex !== -1) {\r\n try {\r\n const jsonStr = data.error.substring(lastBraceIndex);\r\n const nestedError = JSON.parse(jsonStr);\r\n if (nestedError.message && typeof nestedError.message === 'string') {\r\n return nestedError.message;\r\n }\r\n } catch {\r\n // If parsing fails, fall back to the original error string\r\n }\r\n }\r\n return data.error;\r\n }\r\n \r\n return 'Unknown Runpod error';\r\n },\r\n});\r\n\r\n","import {\n JSONValue,\n SpeechModelV2,\n SpeechModelV2CallWarning,\n} from '@ai-sdk/provider';\nimport { FetchFunction, withoutTrailingSlash } from '@ai-sdk/provider-utils';\n\nexport interface RunpodSpeechModelConfig {\n provider: string;\n baseURL: string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction replaceNewlinesWithSpaces(value: string): string {\n return value.replace(/[\\r\\n]+/g, ' ');\n}\n\nexport class RunpodSpeechModel implements SpeechModelV2 {\n readonly specificationVersion = 'v2';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: string,\n private readonly config: RunpodSpeechModelConfig\n ) {}\n\n private getRunpodRunSyncUrl(): string {\n // `withoutTrailingSlash` is typed to potentially return undefined, but in our\n // case `config.baseURL` is always a string.\n const baseURL =\n withoutTrailingSlash(this.config.baseURL) ?? this.config.baseURL;\n\n // Allow users to pass /run or /runsync directly.\n if (baseURL.endsWith('/run') || baseURL.endsWith('/runsync')) {\n return baseURL;\n }\n\n return `${baseURL}/runsync`;\n }\n\n async doGenerate(\n options: Parameters<SpeechModelV2['doGenerate']>[0]\n ): Promise<Awaited<ReturnType<SpeechModelV2['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n const warnings: SpeechModelV2CallWarning[] = [];\n\n const {\n text,\n voice,\n outputFormat,\n instructions,\n speed,\n language,\n providerOptions,\n abortSignal,\n headers,\n } = options;\n\n // This endpoint currently returns wav. Warn and ignore other formats.\n if (outputFormat != null && outputFormat !== 'wav') {\n warnings.push({\n type: 'unsupported-setting',\n setting: 'outputFormat',\n details: `Unsupported outputFormat: ${outputFormat}. This endpoint returns 'wav'.`,\n });\n }\n\n if (instructions != null) {\n warnings.push({\n type: 'unsupported-setting',\n setting: 'instructions',\n details: `Instructions are not supported by this speech endpoint.`,\n });\n }\n\n if (speed != null) {\n warnings.push({\n type: 'unsupported-setting',\n setting: 'speed',\n details: `Speed is not supported by this speech endpoint.`,\n });\n }\n\n if (language != null) {\n warnings.push({\n type: 'unsupported-setting',\n setting: 'language',\n details: `Language selection is not supported by this speech endpoint.`,\n });\n }\n\n const runpodProviderOptions = isRecord(providerOptions)\n ? (providerOptions as any).runpod\n : undefined;\n\n const voiceUrl =\n isRecord(runpodProviderOptions) &&\n (typeof runpodProviderOptions.voice_url === 'string' ||\n typeof runpodProviderOptions.voiceUrl === 'string')\n ? (runpodProviderOptions.voice_url ??\n runpodProviderOptions.voiceUrl ??\n undefined)\n : undefined;\n\n const input: Record<string, unknown> = {\n prompt: replaceNewlinesWithSpaces(text),\n };\n\n // The endpoint supports either a built-in voice name or a voice_url prompt.\n if (voiceUrl) {\n input.voice_url = voiceUrl;\n } else if (voice) {\n input.voice = voice;\n }\n\n const requestBody = { input };\n const url = this.getRunpodRunSyncUrl();\n\n const fetchFn = this.config.fetch ?? fetch;\n\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.config.headers(),\n };\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (value != null) {\n requestHeaders[key] = value;\n }\n }\n }\n\n const response = await fetchFn(url, {\n method: 'POST',\n headers: requestHeaders,\n body: JSON.stringify(requestBody),\n signal: abortSignal,\n });\n\n const responseHeaders = Object.fromEntries(response.headers.entries());\n const rawBodyText = await response.text();\n\n let parsed: any = undefined;\n try {\n parsed = rawBodyText ? JSON.parse(rawBodyText) : undefined;\n } catch {\n // ignore - we'll surface the raw body in the error below\n }\n\n if (!response.ok) {\n const message =\n (parsed && typeof parsed.error === 'string' && parsed.error) ||\n rawBodyText ||\n `HTTP ${response.status}`;\n throw new Error(`Runpod speech request failed: ${message}`);\n }\n\n const output = parsed?.output ?? parsed;\n\n const audioUrl = output?.audio_url;\n if (typeof audioUrl !== 'string' || audioUrl.length === 0) {\n throw new Error('Runpod speech response did not include an audio_url.');\n }\n\n const audioResponse = await fetchFn(audioUrl, { signal: abortSignal });\n if (!audioResponse.ok) {\n throw new Error(\n `Failed to download generated audio (${audioResponse.status}).`\n );\n }\n\n const audio = new Uint8Array(await audioResponse.arrayBuffer());\n\n const providerMetadata: Record<string, Record<string, JSONValue>> = {\n runpod: {\n audioUrl,\n ...(typeof output?.cost === 'number' ? { cost: output.cost } : {}),\n },\n };\n\n return {\n audio,\n warnings,\n request: {\n body: JSON.stringify(requestBody),\n },\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders as any,\n body: rawBodyText,\n },\n providerMetadata,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,+BAGO;AACP,IAAAA,yBAIO;;;ACRP,IAAAC,yBAOO;AACP,sBAAqC;AACrC,IAAAC,cAAkB;;;ACVlB,iBAAkB;AAClB,4BAA+C;AAGxC,IAAM,yBAAyB,aAAE,OAAO;AAAA,EAC7C,OAAO,aAAE,OAAO,EAAE,SAAS;AAAA,EAC3B,SAAS,aAAE,OAAO,EAAE,SAAS;AAC/B,CAAC;AAIM,IAAM,uCAAmC,sDAA+B;AAAA,EAC7E,aAAa;AAAA,EACb,gBAAgB,CAAC,SAA+B;AAE9C,QAAI,KAAK,SAAS;AAChB,aAAO,KAAK;AAAA,IACd;AAGA,QAAI,KAAK,OAAO;AAKd,YAAM,iBAAiB,KAAK,MAAM,YAAY,GAAG;AACjD,UAAI,mBAAmB,IAAI;AACzB,YAAI;AACF,gBAAM,UAAU,KAAK,MAAM,UAAU,cAAc;AACnD,gBAAM,cAAc,KAAK,MAAM,OAAO;AACtC,cAAI,YAAY,WAAW,OAAO,YAAY,YAAY,UAAU;AAClE,mBAAO,YAAY;AAAA,UACrB;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AACA,aAAO,KAAK;AAAA,IACd;AAEA,WAAO;AAAA,EACT;AACF,CAAC;;;ADjBD,IAAM,0BAAkD;AAAA,EACtD,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AAAA,EACP,OAAO;AAAA;AACT;AAGA,IAAM,kBAAkB,oBAAI,IAAI;AAAA;AAAA,EAE9B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAEM,IAAM,mBAAN,MAA+C;AAAA,EAQpD,YACW,SACD,QACR;AAFS;AACD;AATV,SAAS,uBAAuB;AAChC,SAAS,mBAAmB;AAAA,EASzB;AAAA,EAPH,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAOA,MAAM,WAAW;AAAA,IACf;AAAA,IACA,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,GAEE;AACA,UAAM,WAA2C,CAAC;AAGlD,UAAM,eACJ,KAAK,QAAQ,SAAS,OAAO,KAAK,KAAK,QAAQ,SAAS,SAAS;AAGnE,UAAM,uBAAuB,KAAK,QAAQ,SAAS,iBAAiB;AAGpE,QAAI;AAEJ,QAAI,gBAAgB,sBAAsB;AAGxC,mBAAa,eAAe;AAAA,IAC9B,WAAW,MAAM;AAEf,YAAM,sBAAsB,KAAK,QAAQ,KAAK,GAAG;AAGjD,UAAI,CAAC,gBAAgB,IAAI,mBAAmB,GAAG;AAC7C,cAAM,IAAI,qCAAqB;AAAA,UAC7B,UAAU;AAAA,UACV,SAAS,QAAQ,IAAI,iDAAiD,MAAM;AAAA,YAC1E;AAAA,UACF,EACG,IAAI,CAAC,MAAM,EAAE,QAAQ,KAAK,GAAG,CAAC,EAC9B,KAAK,IAAI,CAAC;AAAA,QACf,CAAC;AAAA,MACH;AAEA,mBAAa;AAAA,IACf,WAAW,aAAa;AAEtB,UAAI,CAAC,wBAAwB,WAAW,GAAG;AACzC,cAAM,IAAI,qCAAqB;AAAA,UAC7B,UAAU;AAAA,UACV,SAAS,gBAAgB,WAAW,yDAAyD,OAAO,KAAK,uBAAuB,EAAE,KAAK,IAAI,CAAC;AAAA,QAC9I,CAAC;AAAA,MACH;AAGA,mBAAa,wBAAwB,WAAW;AAAA,IAClD,OAAO;AAEL,mBAAa;AAAA,IACf;AAGA,QAAI,IAAI,GAAG;AACT,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SACE;AAAA,MACJ,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,KAAK,OAAO,WAAW,cAAc,KAAK,oBAAI,KAAK;AAGvE,UAAM,eAAe,KAAK;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA,gBAAgB;AAAA,MAChB;AAAA,IACF;AAEA,UAAM,EAAE,OAAO,UAAU,gBAAgB,IAAI,UAAM,sCAAc;AAAA,MAC/D,KAAK,GAAG,KAAK,OAAO,OAAO;AAAA,MAC3B,aAAS,uCAAe,KAAK,OAAO,QAAQ,GAAG,OAAO;AAAA,MACtD,MAAM;AAAA,QACJ,OAAO;AAAA,MACT;AAAA,MACA,uBAAuB;AAAA,MACvB,+BAA2B;AAAA,QACzB;AAAA,MACF;AAAA,MACA;AAAA,MACA,OAAO,KAAK,OAAO;AAAA,IACrB,CAAC;AAGD,UAAM,gBAAgB;AACtB,QACE,cAAc,WAAW,gBACxB,cAAc,QAAQ,UAAU,cAAc,QAAQ,YACvD;AAGA,YAAM,WACJ,cAAc,OAAO,UAAU,cAAc,OAAO;AACtD,YAAM,YAAY,MAAM,KAAK,cAAc,UAAU,WAAW;AAEhE,aAAO;AAAA,QACL,QAAQ,CAAC,SAAS;AAAA,QAClB;AAAA,QACA,UAAU;AAAA,UACR,WAAW;AAAA,UACX,SAAS,KAAK;AAAA,UACd,SAAS;AAAA,QACX;AAAA,QACA,kBAAkB;AAAA,UAChB,QAAQ;AAAA,YACN,QAAQ;AAAA,cACN;AAAA,gBACE,KAAK;AAAA,gBACL,MAAM,cAAc,QAAQ;AAAA,cAC9B;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,WACE,cAAc,WAAW,cACzB,cAAc,WAAW,eACzB;AAEA,YAAM,cAAc;AAAA,QAClB,aAAa,gBAAgB,QAAQ;AAAA,QACrC,oBAAoB,gBAAgB,QAChC;AAAA,MACN;AACA,YAAM,WAAW,MAAM,KAAK;AAAA,QAC1B,cAAc;AAAA,QACd;AAAA,QACA;AAAA,MACF;AACA,YAAM,YAAY,MAAM,KAAK,cAAc,UAAU,WAAW;AAEhE,aAAO;AAAA,QACL,QAAQ,CAAC,SAAS;AAAA,QAClB;AAAA,QACA,UAAU;AAAA,UACR,WAAW;AAAA,UACX,SAAS,KAAK;AAAA,UACd,SAAS;AAAA,QACX;AAAA,QACA,kBAAkB;AAAA,UAChB,QAAQ;AAAA,YACN,QAAQ;AAAA,cACN;AAAA,gBACE,KAAK;AAAA,gBACL,OAAO,cAAc;AAAA,cACvB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,OAAO;AACL,YAAM,IAAI,MAAM,+BAA+B,cAAc,MAAM,EAAE;AAAA,IACvE;AAAA,EACF;AAAA,EAEA,MAAc,cACZ,UACA,aACqB;AACrB,UAAM,EAAE,OAAO,UAAU,IAAI,UAAM,mCAAW;AAAA,MAC5C,KAAK;AAAA,MACL,+BAA2B,oDAA4B;AAAA,MACvD,uBAAuB;AAAA,MACvB;AAAA,MACA,OAAO,KAAK,OAAO;AAAA,IACrB,CAAC;AACD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,kBACZ,OACA,aACA,aACiB;AACjB,UAAM,cAAc,aAAa,eAAe;AAChD,UAAM,eAAe,aAAa,sBAAsB;AAExD,aAAS,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,UAAI,aAAa,SAAS;AACxB,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAChD;AAEA,YAAM,EAAE,OAAO,eAAe,IAAI,UAAM,mCAAW;AAAA,QACjD,KAAK,GAAG,KAAK,OAAO,OAAO,WAAW,KAAK;AAAA,QAC3C,SAAS,KAAK,OAAO,QAAQ;AAAA,QAC7B,+BAA2B;AAAA,UACzB;AAAA,QACF;AAAA,QACA,uBAAuB;AAAA,QACvB;AAAA,QACA,OAAO,KAAK,OAAO;AAAA,MACrB,CAAC;AAED,YAAM,sBAAsB;AAC5B,UACE,oBAAoB,WAAW,gBAC9B,oBAAoB,QAAQ,UAC3B,oBAAoB,QAAQ,YAC9B;AACA,eACE,oBAAoB,OAAO,UAC3B,oBAAoB,OAAO;AAAA,MAE/B;AAEA,UAAI,oBAAoB,WAAW,UAAU;AAC3C,cAAM,IAAI;AAAA,UACR,4BAA4B,oBAAoB,SAAS,eAAe;AAAA,QAC1E;AAAA,MACF;AAGA,YAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,YAAY,CAAC;AAAA,IAClE;AAEA,UAAM,IAAI;AAAA,MACR,oCAAoC,WAAW,cAAe,cAAc,eAAgB,GAAI;AAAA,IAClG;AAAA,EACF;AAAA,EAEQ,kBACN,QACA,YACA,MACA,eACA,aACyB;AAEzB,UAAM,cACJ,KAAK,QAAQ,SAAS,MAAM,KAC5B,KAAK,QAAQ,SAAS,mBAAmB;AAE3C,QAAI,aAAa;AAEf,YAAM,YAAY,KAAK,QAAQ,SAAS,SAAS;AAEjD,UAAI,WAAW;AAEb,eAAO;AAAA,UACL;AAAA,UACA,iBAAiB,eAAe,mBAAmB;AAAA,UACnD,MAAM,QAAQ;AAAA,UACd,qBAAqB;AAAA,UACrB,UAAU;AAAA,UACV,MAAM;AAAA,UACN,eAAe;AAAA,UACf,uBAAuB,eAAe,yBAAyB;AAAA,UAC/D,GAAG;AAAA;AAAA,QACL;AAAA,MACF,OAAO;AAEL,cAAM,CAAC,OAAO,MAAM,IAAI,WAAW,MAAM,GAAG,EAAE,IAAI,MAAM;AAExD,eAAO;AAAA,UACL;AAAA,UACA,iBAAiB,eAAe,mBAAmB;AAAA,UACnD,MAAM,QAAQ;AAAA,UACd,qBAAqB,KAAK,QAAQ,SAAS,SAAS,IAAI,IAAI;AAAA,UAC5D,UAAU,KAAK,QAAQ,SAAS,SAAS,IAAI,IAAI;AAAA,UACjD;AAAA,UACA;AAAA,UACA,cAAc;AAAA,UACd,GAAG;AAAA,QACL;AAAA,MACF;AAAA,IACF;AAGA,UAAM,eACJ,KAAK,QAAQ,SAAS,OAAO,KAAK,KAAK,QAAQ,SAAS,SAAS;AACnE,QAAI,cAAc;AAChB,YAAM,cAAc,KAAK,QAAQ,SAAS,MAAM;AAEhD,UAAI,aAAa;AAIf,cAAM,cAAuC;AAAA,UAC3C;AAAA,UACA,cACG,eAAe,gBAA2B,eAAe;AAAA,UAC5D,wBACG,eAAe,0BAAsC;AAAA,QAC1D;AAGA,YAAI,SAAS,QAAW;AACtB,sBAAY,OAAO;AAAA,QACrB,WAAW,eAAe,SAAS,QAAW;AAC5C,sBAAY,OAAO,cAAc;AAAA,QACnC;AAGA,YAAI,eAAe,QAAQ;AACzB,sBAAY,SAAS,cAAc;AAAA,QACrC;AAEA,eAAO;AAAA,MACT,OAAO;AAIL,cAAM,aAAsC;AAAA,UAC1C;AAAA,UACA,cACG,eAAe,gBAA2B,eAAe;AAAA,UAC5D,wBACG,eAAe,0BAAsC;AAAA,QAC1D;AAGA,YAAI,SAAS,QAAW;AACtB,qBAAW,OAAO;AAAA,QACpB,WAAW,eAAe,SAAS,QAAW;AAC5C,qBAAW,OAAO,cAAc;AAAA,QAClC;AAGA,YAAI,WAAW,iBAAiB,UAAU;AACxC,cAAI,eAAe,OAAO;AACxB,uBAAW,QAAQ,cAAc;AAAA,UACnC;AACA,cAAI,eAAe,QAAQ;AACzB,uBAAW,SAAS,cAAc;AAAA,UACpC;AAAA,QACF;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAGA,UAAM,uBAAuB,KAAK,QAAQ,SAAS,iBAAiB;AACpE,QAAI,sBAAsB;AAKxB,YAAM,oBAA6C;AAAA,QACjD;AAAA,QACA,cACG,eAAe,gBAA2B,eAAe;AAAA,QAC5D,YAAa,eAAe,cAAyB;AAAA,QACrD,eAAgB,eAAe,iBAA4B;AAAA,QAC3D,sBACG,eAAe,wBAAoC;AAAA,QACtD,kBACG,eAAe,oBAAgC;AAAA,MACpD;AAGA,UAAI,eAAe,QAAQ;AACzB,0BAAkB,SAAS,cAAc;AAAA,MAC3C;AAEA,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,MACL;AAAA,MACA,iBAAiB,eAAe,mBAAmB;AAAA,MACnD,MAAM;AAAA,MACN,MAAM,QAAQ;AAAA,MACd,uBAAuB,eAAe,yBAAyB;AAAA,MAC/D,GAAG;AAAA,IACL;AAAA,EACF;AACF;AAGA,IAAM,4BAA4B,cAAE,OAAO;AAAA,EACzC,IAAI,cAAE,OAAO;AAAA,EACb,QAAQ,cAAE,KAAK,CAAC,aAAa,YAAY,eAAe,QAAQ,CAAC;AAAA,EACjE,WAAW,cAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,eAAe,cAAE,OAAO,EAAE,SAAS;AAAA,EACnC,QAAQ,cACL,OAAO;AAAA,IACN,MAAM,cAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,QAAQ,cAAE,OAAO,EAAE,SAAS;AAAA;AAAA,IAC5B,WAAW,cAAE,OAAO,EAAE,SAAS;AAAA;AAAA,EACjC,CAAC,EACA,SAAS;AAAA;AACd,CAAC;AAGD,IAAM,0BAA0B,cAAE,OAAO;AAAA,EACvC,IAAI,cAAE,OAAO;AAAA,EACb,QAAQ,cAAE,KAAK,CAAC,aAAa,YAAY,eAAe,QAAQ,CAAC;AAAA,EACjE,QAAQ,cACL,OAAO;AAAA,IACN,MAAM,cAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,QAAQ,cAAE,OAAO,EAAE,SAAS;AAAA,IAC5B,WAAW,cAAE,OAAO,EAAE,SAAS;AAAA,EACjC,CAAC,EACA,SAAS;AAAA,EACZ,OAAO,cAAE,OAAO,EAAE,SAAS;AAAA;AAC7B,CAAC;;;AEpdD,IAAAC,yBAAoD;AAYpD,SAAS,SAAS,OAAkD;AAClE,SAAO,OAAO,UAAU,YAAY,UAAU;AAChD;AAEA,SAAS,0BAA0B,OAAuB;AACxD,SAAO,MAAM,QAAQ,YAAY,GAAG;AACtC;AAEO,IAAM,oBAAN,MAAiD;AAAA,EAOtD,YACW,SACQ,QACjB;AAFS;AACQ;AARnB,SAAS,uBAAuB;AAAA,EAS7B;AAAA,EAPH,IAAI,WAAmB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAOQ,sBAA8B;AAGpC,UAAM,cACJ,6CAAqB,KAAK,OAAO,OAAO,KAAK,KAAK,OAAO;AAG3D,QAAI,QAAQ,SAAS,MAAM,KAAK,QAAQ,SAAS,UAAU,GAAG;AAC5D,aAAO;AAAA,IACT;AAEA,WAAO,GAAG,OAAO;AAAA,EACnB;AAAA,EAEA,MAAM,WACJ,SAC2D;AAC3D,UAAM,cAAc,KAAK,OAAO,WAAW,cAAc,KAAK,oBAAI,KAAK;AAEvE,UAAM,WAAuC,CAAC;AAE9C,UAAM;AAAA,MACJ;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,IAAI;AAGJ,QAAI,gBAAgB,QAAQ,iBAAiB,OAAO;AAClD,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS,6BAA6B,YAAY;AAAA,MACpD,CAAC;AAAA,IACH;AAEA,QAAI,gBAAgB,MAAM;AACxB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI,SAAS,MAAM;AACjB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,QAAI,YAAY,MAAM;AACpB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAAS;AAAA,QACT,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,UAAM,wBAAwB,SAAS,eAAe,IACjD,gBAAwB,SACzB;AAEJ,UAAM,WACJ,SAAS,qBAAqB,MAC7B,OAAO,sBAAsB,cAAc,YAC1C,OAAO,sBAAsB,aAAa,YACvC,sBAAsB,aACvB,sBAAsB,YACtB,SACA;AAEN,UAAM,QAAiC;AAAA,MACrC,QAAQ,0BAA0B,IAAI;AAAA,IACxC;AAGA,QAAI,UAAU;AACZ,YAAM,YAAY;AAAA,IACpB,WAAW,OAAO;AAChB,YAAM,QAAQ;AAAA,IAChB;AAEA,UAAM,cAAc,EAAE,MAAM;AAC5B,UAAM,MAAM,KAAK,oBAAoB;AAErC,UAAM,UAAU,KAAK,OAAO,SAAS;AAErC,UAAM,iBAAyC;AAAA,MAC7C,gBAAgB;AAAA,MAChB,GAAG,KAAK,OAAO,QAAQ;AAAA,IACzB;AAEA,QAAI,SAAS;AACX,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,YAAI,SAAS,MAAM;AACjB,yBAAe,GAAG,IAAI;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAQ,KAAK;AAAA,MAClC,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,MAAM,KAAK,UAAU,WAAW;AAAA,MAChC,QAAQ;AAAA,IACV,CAAC;AAED,UAAM,kBAAkB,OAAO,YAAY,SAAS,QAAQ,QAAQ,CAAC;AACrE,UAAM,cAAc,MAAM,SAAS,KAAK;AAExC,QAAI,SAAc;AAClB,QAAI;AACF,eAAS,cAAc,KAAK,MAAM,WAAW,IAAI;AAAA,IACnD,QAAQ;AAAA,IAER;AAEA,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,UACH,UAAU,OAAO,OAAO,UAAU,YAAY,OAAO,SACtD,eACA,QAAQ,SAAS,MAAM;AACzB,YAAM,IAAI,MAAM,iCAAiC,OAAO,EAAE;AAAA,IAC5D;AAEA,UAAM,SAAS,QAAQ,UAAU;AAEjC,UAAM,WAAW,QAAQ;AACzB,QAAI,OAAO,aAAa,YAAY,SAAS,WAAW,GAAG;AACzD,YAAM,IAAI,MAAM,sDAAsD;AAAA,IACxE;AAEA,UAAM,gBAAgB,MAAM,QAAQ,UAAU,EAAE,QAAQ,YAAY,CAAC;AACrE,QAAI,CAAC,cAAc,IAAI;AACrB,YAAM,IAAI;AAAA,QACR,uCAAuC,cAAc,MAAM;AAAA,MAC7D;AAAA,IACF;AAEA,UAAM,QAAQ,IAAI,WAAW,MAAM,cAAc,YAAY,CAAC;AAE9D,UAAM,mBAA8D;AAAA,MAClE,QAAQ;AAAA,QACN;AAAA,QACA,GAAI,OAAO,QAAQ,SAAS,WAAW,EAAE,MAAM,OAAO,KAAK,IAAI,CAAC;AAAA,MAClE;AAAA,IACF;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,SAAS;AAAA,QACP,MAAM,KAAK,UAAU,WAAW;AAAA,MAClC;AAAA,MACA,UAAU;AAAA,QACR,WAAW;AAAA,QACX,SAAS,KAAK;AAAA,QACd,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AHxIA,IAAM,2BAAmD;AAAA,EACvD,sBAAsB;AAAA,EACtB,mCACE;AAAA,EACF,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,mCACE;AAAA,EACF,mCACE;AACJ;AAGA,IAAM,iCAAyD;AAAA,EAC7D,mBAAmB;AAAA,EACnB,wBAAwB;AAAA,EACxB,0BAA0B;AAAA;AAAA,EAE1B,0BAA0B;AAAA,EAC1B,+BAA+B;AAAA,EAC/B,wCACE;AAAA,EACF,oCACE;AAAA,EACF,gCACE;AAAA;AAAA,EAEF,oBAAoB;AAAA;AAAA,EAEpB,+BACE;AAAA;AAAA,EAEF,qBAAqB;AAAA,EACrB,sBAAsB;AACxB;AAIA,IAAM,kCAA0D;AAAA,EAC9D,+BAA+B;AACjC;AAGA,IAAM,0BAAkD;AAAA,EACtD,sBAAsB;AAAA,EACtB,mCAAmC;AAAA,EACnC,mCAAmC;AACrC;AAMA,SAAS,kBAAkB,SAAyB;AAClD,QAAM,aAAa,QAAQ,QAAQ,OAAO,GAAG;AAC7C,SAAO,4BAA4B,UAAU;AAC/C;AAEA,SAAS,6BAA6B,cAAqC;AACzE,MAAI,CAAC,aAAa,WAAW,MAAM,GAAG;AACpC,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,YAAY;AAChC,QAAI,IAAI,aAAa,qBAAqB;AACxC,aAAO;AAAA,IACT;AAIA,UAAM,QAAQ,IAAI,SAAS,MAAM,GAAG,EAAE,OAAO,OAAO;AACpD,UAAM,MAAM,MAAM,YAAY,UAAU;AACxC,UAAM,aAAa,QAAQ,KAAK,MAAM,MAAM,CAAC,IAAI;AAEjD,WAAO,cAAc;AAAA,EACvB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,aACd,UAAkC,CAAC,GACnB;AAChB,QAAM,aAAa,OAAO;AAAA,IACxB,eAAe,cAAU,mCAAW;AAAA,MAClC,QAAQ,QAAQ;AAAA,MAChB,yBAAyB;AAAA,MACzB,aAAa;AAAA,IACf,CAAC,CAAC;AAAA,IACF,GAAG,QAAQ;AAAA,EACb;AAEA,QAAM,cAA6B,OAAO,KAAK,gBAAgB;AAC7D,QAAI,aAAa,MAAM;AACrB,UAAI;AACF,cAAM,OAAO,KAAK,MAAM,YAAY,IAAc;AAClD,YAAI,KAAK,WAAW,QAAQ,CAAC,KAAK,gBAAgB;AAChD,eAAK,iBAAiB,EAAE,eAAe,KAAK;AAC5C,sBAAY,OAAO,KAAK,UAAU,IAAI;AAAA,QACxC;AAAA,MACF,QAAQ;AAAA,MAAC;AAAA,IACX;AACA,UAAM,UAAU,QAAQ,SAAS;AACjC,WAAO,QAAQ,KAAK,WAAW;AAAA,EACjC;AASA,QAAM,iBAAiB,CACrB,SACA,cACsB;AACtB,QAAI;AAEJ,QAAI,QAAQ,SAAS;AACnB,gBAAU,QAAQ;AAAA,IACpB,OAAO;AAEL,gBAAU,yBAAyB,OAAO,KAAK,kBAAkB,OAAO;AAAA,IAC1E;AAEA,WAAO;AAAA,MACL,UAAU,UAAU,SAAS;AAAA,MAC7B,KAAK,CAAC,EAAE,KAAK,MAAM,OAAG,6CAAqB,OAAO,CAAC,GAAG,IAAI;AAAA,MAC1D,SAAS;AAAA,MACT,OAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,kBAAkB,CAAC,YAAoB;AAC3C,UAAM,kBAAkB,wBAAwB,OAAO,KAAK;AAC5D,WAAO,IAAI,2DAAkC,iBAAiB;AAAA,MAC5D,GAAG,eAAe,SAAS,MAAM;AAAA,MACjC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,wBAAwB,CAAC,YAAoB;AACjD,UAAM,kBAAkB,wBAAwB,OAAO,KAAK;AAC5D,WAAO,IAAI,iEAAwC,iBAAiB;AAAA,MAClE,GAAG,eAAe,SAAS,YAAY;AAAA,MACvC,cAAc;AAAA,IAChB,CAAC;AAAA,EACH;AAEA,QAAM,mBAAmB,CAAC,YAAoB;AAC5C,QAAI;AAEJ,QAAI,QAAQ,SAAS;AACnB,gBAAU,QAAQ;AAAA,IACpB,OAAO;AAEL,gBACE,+BAA+B,OAAO,KAAK,kBAAkB,OAAO;AAAA,IACxE;AAEA,WAAO,IAAI,iBAAiB,SAAS;AAAA,MACnC,UAAU;AAAA,MACV;AAAA,MACA,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAEA,QAAM,oBAAoB,CAAC,YAAoB;AAC7C,UAAM,wBAAwB,6BAA6B,OAAO;AAClE,UAAM,oBAAoB,yBAAyB;AAGnD,UAAM,gBAAgB,gCAAgC,iBAAiB;AAEvE,UAAM,UACJ,kBACC,kBAAkB,WAAW,MAAM,IAChC,oBACA,4BAA4B,iBAAiB;AAEnD,WAAO,IAAI,kBAAkB,mBAAmB;AAAA,MAC9C,UAAU;AAAA,MACV;AAAA,MACA,SAAS;AAAA,MACT,OAAO;AAAA,IACT,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,CAAC,YAAoB,gBAAgB,OAAO;AAE7D,WAAS,kBAAkB;AAC3B,WAAS,gBAAgB;AACzB,WAAS,YAAY;AACrB,WAAS,aAAa;AACtB,WAAS,cAAc;AACvB,WAAS,SAAS;AAElB,SAAO;AACT;AAEO,IAAM,SAAS,aAAa;","names":["import_provider_utils","import_provider_utils","import_zod","import_provider_utils"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/runpod-provider.ts","../src/runpod-image-model.ts","../src/runpod-error.ts","../src/runpod-speech-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';\nexport type { RunpodImageErrorData } from './runpod-error';\n","import { ImageModelV3, LanguageModelV3, SpeechModelV3 } 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 { RunpodImageModel } from './runpod-image-model';\nimport { RunpodSpeechModel } from './runpod-speech-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: string): LanguageModelV3;\n\n /**\nCreates a chat model for text generation.\n*/\n chatModel(modelId: string): LanguageModelV3;\n\n /**\nCreates a chat model for text generation.\n*/\n languageModel(modelId: string): LanguageModelV3;\n\n /**\nCreates a completion model for text generation.\n*/\n completionModel(modelId: string): LanguageModelV3;\n\n /**\nCreates an image model for image generation.\n*/\n imageModel(modelId: string): ImageModelV3;\n\n /**\nCreates an image model for image generation.\n*/\n image(modelId: string): ImageModelV3;\n\n /**\nCreates a speech model for speech generation.\n*/\n speechModel(modelId: string): SpeechModelV3;\n\n /**\nCreates a speech model for speech generation.\n*/\n speech(modelId: string): SpeechModelV3;\n}\n\n// Mapping of Runpod model IDs to their endpoint URLs\nconst MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'qwen/qwen3-32b-awq': 'https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1',\n 'ibm-granite/granite-4.0-h-small':\n 'https://api.runpod.ai/v2/granite-4-0-h-small/openai/v1',\n 'gpt-oss-120b': 'https://api.runpod.ai/v2/gpt-oss-120b/openai/v1',\n 'openai/gpt-oss-120b': 'https://api.runpod.ai/v2/gpt-oss-120b/openai/v1',\n 'deepcogito/cogito-671b-v2.1-fp8':\n 'https://api.runpod.ai/v2/cogito-671b-v2-1-fp8-dynamic/openai/v1',\n 'deepcogito/cogito-671b-v2.1-FP8':\n 'https://api.runpod.ai/v2/cogito-671b-v2-1-fp8-dynamic/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 // Nano Banana (edit only)\n 'nano-banana-edit': 'https://api.runpod.ai/v2/nano-banana-edit',\n // Nano Banana Pro (edit only)\n 'google/nano-banana-pro-edit':\n 'https://api.runpod.ai/v2/nano-banana-pro-edit',\n // Pruna (t2i and edit)\n 'pruna/p-image-t2i': 'https://api.runpod.ai/v2/p-image-t2i',\n 'pruna/p-image-edit': 'https://api.runpod.ai/v2/p-image-edit',\n};\n\n// Mapping of Runpod speech model IDs to their serverless endpoint URLs\n// Note: This is intentionally a temporary mapping for a stealth release.\nconst SPEECH_MODEL_ID_TO_ENDPOINT_URL: Record<string, string> = {\n 'resembleai/chatterbox-turbo': 'https://api.runpod.ai/v2/chatterbox-turbo/',\n};\n\n// Mapping of Runpod model IDs to their OpenAI model names\nconst MODEL_ID_TO_OPENAI_NAME: Record<string, string> = {\n 'qwen/qwen3-32b-awq': 'Qwen/Qwen3-32B-AWQ',\n 'deepcogito/cogito-671b-v2.1-fp8': 'deepcogito/cogito-671b-v2.1-FP8',\n 'deepcogito/cogito-671b-v2.1-FP8': 'deepcogito/cogito-671b-v2.1-FP8',\n};\n\n/**\n * Derives the endpoint URL for a model by replacing slashes with hyphens.\n * Example: 'ibm-granite/granite-4.0-h-small' -> 'https://api.runpod.ai/v2/ibm-granite-granite-4.0-h-small/openai/v1'\n */\nfunction deriveEndpointURL(modelId: string): string {\n const normalized = modelId.replace(/\\//g, '-');\n return `https://api.runpod.ai/v2/${normalized}/openai/v1`;\n}\n\nfunction parseRunpodConsoleEndpointId(modelIdOrUrl: string): string | null {\n if (!modelIdOrUrl.startsWith('http')) {\n return null;\n }\n\n try {\n const url = new URL(modelIdOrUrl);\n if (url.hostname !== 'console.runpod.io') {\n return null;\n }\n\n // Example:\n // https://console.runpod.io/serverless/user/endpoint/<ENDPOINT_ID>\n const parts = url.pathname.split('/').filter(Boolean);\n const idx = parts.lastIndexOf('endpoint');\n const endpointId = idx !== -1 ? parts[idx + 1] : undefined;\n\n return endpointId || null;\n } catch {\n return null;\n }\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 // Use hardcoded mapping if available, otherwise derive endpoint\n baseURL = MODEL_ID_TO_ENDPOINT_URL[modelId] || deriveEndpointURL(modelId);\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: string) => {\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: string) => {\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: string) => {\n let baseURL: string;\n\n if (options.baseURL) {\n baseURL = options.baseURL;\n } else {\n // Use hardcoded mapping if available, otherwise derive endpoint\n baseURL =\n IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId] || deriveEndpointURL(modelId);\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 createSpeechModel = (modelId: string) => {\n const endpointIdFromConsole = parseRunpodConsoleEndpointId(modelId);\n const normalizedModelId = endpointIdFromConsole ?? modelId;\n\n // Prefer explicit mapping for known speech model IDs.\n const mappedBaseURL = SPEECH_MODEL_ID_TO_ENDPOINT_URL[normalizedModelId];\n\n const baseURL =\n mappedBaseURL ??\n (normalizedModelId.startsWith('http')\n ? normalizedModelId\n : `https://api.runpod.ai/v2/${normalizedModelId}`);\n\n return new RunpodSpeechModel(normalizedModelId, {\n provider: 'runpod.speech',\n baseURL,\n headers: getHeaders,\n fetch: runpodFetch,\n });\n };\n\n const provider = (modelId: string) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n provider.imageModel = createImageModel;\n provider.image = createImageModel;\n provider.speechModel = createSpeechModel;\n provider.speech = createSpeechModel;\n\n return provider;\n}\n\nexport const runpod = createRunpod();\n","import {\n ImageModelV3,\n ImageModelV3CallOptions,\n ImageModelV3File,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport {\n combineHeaders,\n createJsonResponseHandler,\n createBinaryResponseHandler,\n FetchFunction,\n postJsonToApi,\n getFromApi,\n} from '@ai-sdk/provider-utils';\nimport { InvalidArgumentError } from '@ai-sdk/provider';\nimport { z } from 'zod';\nimport { runpodImageFailedResponseHandler } from './runpod-error';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\ninterface RunpodImageModelConfig {\n provider: string;\n baseURL: string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\n// Runpod supported aspect ratios (only validated working sizes)\nconst SUPPORTED_ASPECT_RATIOS: Record<string, string> = {\n '1:1': '1328*1328', // ✅ Native support\n '4:3': '1472*1140', // ✅ Native support\n '3:4': '1140*1472', // ✅ Native support\n};\n\n// Runpod supported sizes (validated working sizes)\nconst SUPPORTED_SIZES = new Set([\n // Native aspect ratio sizes\n '1328*1328', // 1:1\n '1472*1140', // 4:3\n '1140*1472', // 3:4\n // Additional validated sizes\n '512*512',\n '768*768',\n '1024*1024',\n '1536*1536',\n '2048*2048',\n '4096*4096',\n '512*768',\n '768*512',\n '1024*768',\n '768*1024',\n]);\n\nexport class RunpodImageModel implements ImageModelV3 {\n readonly specificationVersion = 'v3';\n readonly maxImagesPerCall = 1;\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: string,\n private config: RunpodImageModelConfig\n ) {}\n\n async doGenerate({\n prompt,\n n,\n size,\n aspectRatio,\n seed,\n files,\n mask,\n providerOptions,\n headers,\n abortSignal,\n }: ImageModelV3CallOptions): Promise<\n Awaited<ReturnType<ImageModelV3['doGenerate']>>\n > {\n const warnings: Array<SharedV3Warning> = [];\n\n // Convert standardized files to Runpod format (base64 data URLs or raw base64)\n const standardizedImages = this.convertFilesToRunpodFormat(files);\n\n if (mask) {\n warnings.push({\n type: 'unsupported',\n feature: 'mask',\n details: 'Mask input for inpainting is not yet supported.',\n });\n }\n\n // Check if this is a Pruna model (skip standard size/aspectRatio validation)\n const isPrunaModel =\n this.modelId.includes('pruna') || this.modelId.includes('p-image');\n\n // Check if this is a Nano Banana Pro model (skip standard size/aspectRatio validation)\n const isNanoBananaProModel = this.modelId.includes('nano-banana-pro');\n\n // Determine the size to use\n let runpodSize: string;\n\n if (isPrunaModel || isNanoBananaProModel) {\n // These models use aspect_ratio string directly, skip size validation\n // Pass through the aspectRatio or use default, validation happens at API level\n runpodSize = aspectRatio || '1:1';\n } else if (size) {\n // Convert AI SDK format \"1328x1328\" to Runpod format \"1328*1328\"\n const runpodSizeCandidate = size.replace('x', '*');\n\n // Validate size is supported\n if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {\n throw new InvalidArgumentError({\n argument: 'size',\n message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(\n SUPPORTED_SIZES\n )\n .map((s) => s.replace('*', 'x'))\n .join(', ')}`,\n });\n }\n\n runpodSize = runpodSizeCandidate;\n } else if (aspectRatio) {\n // Validate aspect ratio is supported\n if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {\n throw new InvalidArgumentError({\n argument: 'aspectRatio',\n message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(', ')}`,\n });\n }\n\n // Use supported aspect ratio mapping\n runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];\n } else {\n // Default to square format\n runpodSize = '1328*1328';\n }\n\n // Handle multiple images warning\n if (n > 1) {\n warnings.push({\n type: 'unsupported',\n feature: 'multiple images (n > 1)',\n details:\n 'Runpod image models only support generating 1 image at a time. Using n=1.',\n });\n }\n\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n // Runpod uses a different request format - /runsync endpoint with input wrapper\n const inputPayload = this.buildInputPayload(\n prompt ?? '',\n runpodSize,\n seed,\n providerOptions.runpod as Record<string, unknown> | undefined,\n aspectRatio,\n standardizedImages\n );\n\n const { value: response, responseHeaders } = await postJsonToApi({\n url: `${this.config.baseURL}/runsync`,\n headers: combineHeaders(this.config.headers(), headers),\n body: {\n input: inputPayload,\n },\n failedResponseHandler: runpodImageFailedResponseHandler,\n successfulResponseHandler: createJsonResponseHandler(\n runpodImageResponseSchema as any\n ),\n abortSignal,\n fetch: this.config.fetch,\n });\n\n // Handle both sync and async responses from Runpod\n const typedResponse = response as any;\n if (\n typedResponse.status === 'COMPLETED' &&\n (typedResponse.output?.result || typedResponse.output?.image_url)\n ) {\n // Sync response - image is ready\n // Different models use different response formats: result vs image_url\n const imageUrl =\n typedResponse.output.result || typedResponse.output.image_url;\n const imageData = await this.downloadImage(imageUrl, abortSignal);\n\n return {\n images: [imageData],\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n providerMetadata: {\n runpod: {\n images: [\n {\n url: imageUrl,\n cost: typedResponse.output?.cost,\n },\n ],\n },\n },\n };\n } else if (\n typedResponse.status === 'IN_QUEUE' ||\n typedResponse.status === 'IN_PROGRESS'\n ) {\n // Async response - need to poll for completion\n const pollOptions = {\n maxAttempts: providerOptions.runpod?.maxPollAttempts as number,\n pollIntervalMillis: providerOptions.runpod\n ?.pollIntervalMillis as number,\n };\n const imageUrl = await this.pollForCompletion(\n typedResponse.id,\n abortSignal,\n pollOptions\n );\n const imageData = await this.downloadImage(imageUrl, abortSignal);\n\n return {\n images: [imageData],\n warnings,\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders,\n },\n providerMetadata: {\n runpod: {\n images: [\n {\n url: imageUrl,\n jobId: typedResponse.id,\n },\n ],\n },\n },\n };\n } else {\n throw new Error(`Unexpected response status: ${typedResponse.status}`);\n }\n }\n\n private async downloadImage(\n imageUrl: string,\n abortSignal?: AbortSignal\n ): Promise<Uint8Array> {\n const { value: imageData } = await getFromApi({\n url: imageUrl,\n successfulResponseHandler: createBinaryResponseHandler(),\n failedResponseHandler: runpodImageFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n return imageData;\n }\n\n private async pollForCompletion(\n jobId: string,\n abortSignal?: AbortSignal,\n pollOptions?: { maxAttempts?: number; pollIntervalMillis?: number }\n ): Promise<string> {\n const maxAttempts = pollOptions?.maxAttempts ?? 60; // 5 minutes with 5-second intervals\n const pollInterval = pollOptions?.pollIntervalMillis ?? 5000; // 5 seconds\n\n for (let attempt = 0; attempt < maxAttempts; attempt++) {\n if (abortSignal?.aborted) {\n throw new Error('Image generation was aborted');\n }\n\n const { value: statusResponse } = await getFromApi({\n url: `${this.config.baseURL}/status/${jobId}`,\n headers: this.config.headers(),\n successfulResponseHandler: createJsonResponseHandler(\n runpodImageStatusSchema as any\n ),\n failedResponseHandler: runpodImageFailedResponseHandler,\n abortSignal,\n fetch: this.config.fetch,\n });\n\n const typedStatusResponse = statusResponse as any;\n if (\n typedStatusResponse.status === 'COMPLETED' &&\n (typedStatusResponse.output?.result ||\n typedStatusResponse.output?.image_url)\n ) {\n return (\n typedStatusResponse.output.result ||\n typedStatusResponse.output.image_url\n );\n }\n\n if (typedStatusResponse.status === 'FAILED') {\n throw new Error(\n `Image generation failed: ${typedStatusResponse.error || 'Unknown error'}`\n );\n }\n\n // Wait before next poll\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new Error(\n `Image generation timed out after ${maxAttempts} attempts (${(maxAttempts * pollInterval) / 1000}s)`\n );\n }\n\n /**\n * Converts standardized ImageModelV3File[] to Runpod-compatible format.\n * Returns URLs or base64 data URLs that Runpod API accepts.\n */\n private convertFilesToRunpodFormat(\n files: ImageModelV3File[] | undefined\n ): string[] | undefined {\n if (!files || files.length === 0) {\n return undefined;\n }\n\n return files.map((file) => {\n // Handle URL type - return URL directly\n if (file.type === 'url') {\n return file.url;\n }\n\n // Handle file type with data\n if (typeof file.data === 'string') {\n // If it's already a data URL, return as-is\n if (file.data.startsWith('data:')) {\n return file.data;\n }\n // Otherwise, wrap as data URL with media type\n return `data:${file.mediaType};base64,${file.data}`;\n }\n\n // Convert Uint8Array to base64 data URL\n const base64 = this.uint8ArrayToBase64(file.data);\n return `data:${file.mediaType};base64,${base64}`;\n });\n }\n\n /**\n * Converts Uint8Array to base64 string.\n */\n private uint8ArrayToBase64(data: Uint8Array): string {\n let binary = '';\n for (let i = 0; i < data.length; i++) {\n binary += String.fromCharCode(data[i]);\n }\n return btoa(binary);\n }\n\n private buildInputPayload(\n prompt: string,\n runpodSize: string,\n seed?: number,\n runpodOptions?: Record<string, unknown>,\n aspectRatio?: string,\n standardizedImages?: string[]\n ): Record<string, unknown> {\n // Check if this is a Flux model that uses different parameters\n const isFluxModel =\n this.modelId.includes('flux') ||\n this.modelId.includes('black-forest-labs');\n\n if (isFluxModel) {\n // Check if this is Flux Kontext (uses different parameters)\n const isKontext = this.modelId.includes('kontext');\n\n if (isKontext) {\n // Flux Kontext uses size format and has image input\n // Prioritize standardized files over providerOptions\n const kontextPayload: Record<string, unknown> = {\n prompt,\n negative_prompt: runpodOptions?.negative_prompt ?? '',\n seed: seed ?? -1,\n num_inference_steps: 28,\n guidance: 2,\n size: runpodSize,\n output_format: 'png',\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\n ...runpodOptions,\n };\n\n // Use standardized files if provided (first image), otherwise use providerOptions.image\n if (standardizedImages && standardizedImages.length > 0) {\n kontextPayload.image = standardizedImages[0];\n }\n\n return kontextPayload;\n } else {\n // Regular Flux models use width/height\n const [width, height] = runpodSize.split('*').map(Number);\n\n return {\n prompt,\n negative_prompt: runpodOptions?.negative_prompt ?? '',\n seed: seed ?? -1,\n num_inference_steps: this.modelId.includes('schnell') ? 4 : 28,\n guidance: this.modelId.includes('schnell') ? 7 : 2,\n width,\n height,\n image_format: 'png',\n ...runpodOptions,\n };\n }\n }\n\n // Check if this is a Pruna model\n const isPrunaModel =\n this.modelId.includes('pruna') || this.modelId.includes('p-image');\n if (isPrunaModel) {\n const isPrunaEdit = this.modelId.includes('edit');\n\n if (isPrunaEdit) {\n // Pruna image edit\n // Supported aspect_ratio: \"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\"\n // Supports 1-5 images via providerOptions.runpod.images\n const editPayload: Record<string, unknown> = {\n prompt,\n aspect_ratio:\n (runpodOptions?.aspect_ratio as string) ?? aspectRatio ?? '1:1',\n disable_safety_checker:\n (runpodOptions?.disable_safety_checker as boolean) ?? false,\n };\n\n // Add seed if provided\n if (seed !== undefined) {\n editPayload.seed = seed;\n } else if (runpodOptions?.seed !== undefined) {\n editPayload.seed = runpodOptions.seed;\n }\n\n // Use standardized files if provided, otherwise use providerOptions.images\n if (standardizedImages && standardizedImages.length > 0) {\n editPayload.images = standardizedImages;\n } else if (runpodOptions?.images) {\n editPayload.images = runpodOptions.images;\n }\n\n return editPayload;\n } else {\n // Pruna text-to-image\n // Supported aspect_ratio: \"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\", \"custom\"\n // For custom: width/height 256-1440, must be multiple of 16\n const t2iPayload: Record<string, unknown> = {\n prompt,\n aspect_ratio:\n (runpodOptions?.aspect_ratio as string) ?? aspectRatio ?? '1:1',\n disable_safety_checker:\n (runpodOptions?.disable_safety_checker as boolean) ?? false,\n };\n\n // Add seed if provided\n if (seed !== undefined) {\n t2iPayload.seed = seed;\n } else if (runpodOptions?.seed !== undefined) {\n t2iPayload.seed = runpodOptions.seed;\n }\n\n // Handle custom aspect ratio with width/height\n if (t2iPayload.aspect_ratio === 'custom') {\n if (runpodOptions?.width) {\n t2iPayload.width = runpodOptions.width;\n }\n if (runpodOptions?.height) {\n t2iPayload.height = runpodOptions.height;\n }\n }\n\n return t2iPayload;\n }\n }\n\n // Check if this is a Nano Banana Pro model (google/nano-banana-pro-edit)\n const isNanaBananaProModel = this.modelId.includes('nano-banana-pro');\n if (isNanaBananaProModel) {\n // Nano Banana Pro image edit\n // Supported aspect_ratio: \"1:1\", \"16:9\", \"9:16\", \"4:3\", \"3:4\", \"3:2\", \"2:3\", \"21:9\", \"9:21\"\n // Supported resolution: \"1k\", \"2k\", \"4k\"\n // Supported output_format: \"jpeg\", \"png\", \"webp\"\n const nanoBananaPayload: Record<string, unknown> = {\n prompt,\n aspect_ratio:\n (runpodOptions?.aspect_ratio as string) ?? aspectRatio ?? '1:1',\n resolution: (runpodOptions?.resolution as string) ?? '1k',\n output_format: (runpodOptions?.output_format as string) ?? 'jpeg',\n enable_base64_output:\n (runpodOptions?.enable_base64_output as boolean) ?? false,\n enable_sync_mode:\n (runpodOptions?.enable_sync_mode as boolean) ?? false,\n };\n\n // Use standardized files if provided, otherwise use providerOptions.images\n if (standardizedImages && standardizedImages.length > 0) {\n nanoBananaPayload.images = standardizedImages;\n } else if (runpodOptions?.images) {\n nanoBananaPayload.images = runpodOptions.images;\n }\n\n return nanoBananaPayload;\n }\n\n // Default format for Qwen and other models\n const defaultPayload: Record<string, unknown> = {\n prompt,\n negative_prompt: runpodOptions?.negative_prompt ?? '',\n size: runpodSize,\n seed: seed ?? -1,\n enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,\n ...runpodOptions,\n };\n\n // For edit models, use standardized files if provided\n if (standardizedImages && standardizedImages.length > 0) {\n // Single image models use 'image', multi-image models use 'images'\n if (standardizedImages.length === 1) {\n defaultPayload.image = standardizedImages[0];\n } else {\n defaultPayload.images = standardizedImages;\n }\n }\n\n return defaultPayload;\n }\n}\n\n// Runpod image API response schema (handles both sync and async responses)\nconst runpodImageResponseSchema = z.object({\n id: z.string(),\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\n delayTime: z.number().optional(),\n executionTime: z.number().optional(),\n output: z\n .object({\n cost: z.number().optional(),\n result: z.string().optional(), // URL to the generated image (Qwen format)\n image_url: z.string().optional(), // URL to the generated image (Flux format)\n })\n .optional(), // Optional for IN_QUEUE/IN_PROGRESS responses\n});\n\n// Schema for polling status endpoint\nconst runpodImageStatusSchema = z.object({\n id: z.string(),\n status: z.enum(['COMPLETED', 'IN_QUEUE', 'IN_PROGRESS', 'FAILED']),\n output: z\n .object({\n cost: z.number().optional(),\n result: z.string().optional(),\n image_url: z.string().optional(),\n })\n .optional(),\n error: z.string().optional(), // Error message if FAILED\n});\n","import { z } from 'zod';\r\nimport { createJsonErrorResponseHandler } from '@ai-sdk/provider-utils';\r\n\r\n// Runpod image API error schema (supports both error formats)\r\nexport const runpodImageErrorSchema = z.object({\r\n error: z.string().optional(),\r\n message: z.string().optional(),\r\n});\r\n\r\nexport type RunpodImageErrorData = z.infer<typeof runpodImageErrorSchema>;\r\n\r\nexport const runpodImageFailedResponseHandler = createJsonErrorResponseHandler({\r\n errorSchema: runpodImageErrorSchema as any,\r\n errorToMessage: (data: RunpodImageErrorData) => {\r\n // Prefer message if available (more descriptive)\r\n if (data.message) {\r\n return data.message;\r\n }\r\n \r\n // If error field exists, try to extract nested JSON message\r\n if (data.error) {\r\n // Runpod sometimes returns nested JSON in the error field like:\r\n // \"Error submitting task: 400, {\\\"code\\\":400,\\\"message\\\":\\\"...\\\"}\"\r\n // Try to extract the inner message for cleaner error messages\r\n // Find the last occurrence of { which likely starts the JSON object\r\n const lastBraceIndex = data.error.lastIndexOf('{');\r\n if (lastBraceIndex !== -1) {\r\n try {\r\n const jsonStr = data.error.substring(lastBraceIndex);\r\n const nestedError = JSON.parse(jsonStr);\r\n if (nestedError.message && typeof nestedError.message === 'string') {\r\n return nestedError.message;\r\n }\r\n } catch {\r\n // If parsing fails, fall back to the original error string\r\n }\r\n }\r\n return data.error;\r\n }\r\n \r\n return 'Unknown Runpod error';\r\n },\r\n});\r\n\r\n","import {\n JSONValue,\n SpeechModelV3,\n SpeechModelV3CallOptions,\n SharedV3Warning,\n} from '@ai-sdk/provider';\nimport { FetchFunction, withoutTrailingSlash } from '@ai-sdk/provider-utils';\n\nexport interface RunpodSpeechModelConfig {\n provider: string;\n baseURL: string;\n headers: () => Record<string, string>;\n fetch?: FetchFunction;\n _internal?: {\n currentDate?: () => Date;\n };\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction replaceNewlinesWithSpaces(value: string): string {\n return value.replace(/[\\r\\n]+/g, ' ');\n}\n\nexport class RunpodSpeechModel implements SpeechModelV3 {\n readonly specificationVersion = 'v3';\n\n get provider(): string {\n return this.config.provider;\n }\n\n constructor(\n readonly modelId: string,\n private readonly config: RunpodSpeechModelConfig\n ) {}\n\n private getRunpodRunSyncUrl(): string {\n // `withoutTrailingSlash` is typed to potentially return undefined, but in our\n // case `config.baseURL` is always a string.\n const baseURL =\n withoutTrailingSlash(this.config.baseURL) ?? this.config.baseURL;\n\n // Allow users to pass /run or /runsync directly.\n if (baseURL.endsWith('/run') || baseURL.endsWith('/runsync')) {\n return baseURL;\n }\n\n return `${baseURL}/runsync`;\n }\n\n async doGenerate(\n options: SpeechModelV3CallOptions\n ): Promise<Awaited<ReturnType<SpeechModelV3['doGenerate']>>> {\n const currentDate = this.config._internal?.currentDate?.() ?? new Date();\n\n const warnings: SharedV3Warning[] = [];\n\n const {\n text,\n voice,\n outputFormat,\n instructions,\n speed,\n language,\n providerOptions,\n abortSignal,\n headers,\n } = options;\n\n // This endpoint currently returns wav. Warn and ignore other formats.\n if (outputFormat != null && outputFormat !== 'wav') {\n warnings.push({\n type: 'unsupported',\n feature: 'outputFormat',\n details: `Unsupported outputFormat: ${outputFormat}. This endpoint returns 'wav'.`,\n });\n }\n\n if (instructions != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'instructions',\n details: `Instructions are not supported by this speech endpoint.`,\n });\n }\n\n if (speed != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'speed',\n details: `Speed is not supported by this speech endpoint.`,\n });\n }\n\n if (language != null) {\n warnings.push({\n type: 'unsupported',\n feature: 'language',\n details: `Language selection is not supported by this speech endpoint.`,\n });\n }\n\n const runpodProviderOptions = isRecord(providerOptions)\n ? (providerOptions as any).runpod\n : undefined;\n\n const voiceUrl =\n isRecord(runpodProviderOptions) &&\n (typeof runpodProviderOptions.voice_url === 'string' ||\n typeof runpodProviderOptions.voiceUrl === 'string')\n ? (runpodProviderOptions.voice_url ??\n runpodProviderOptions.voiceUrl ??\n undefined)\n : undefined;\n\n const input: Record<string, unknown> = {\n prompt: replaceNewlinesWithSpaces(text),\n };\n\n // The endpoint supports either a built-in voice name or a voice_url prompt.\n if (voiceUrl) {\n input.voice_url = voiceUrl;\n } else if (voice) {\n input.voice = voice;\n }\n\n const requestBody = { input };\n const url = this.getRunpodRunSyncUrl();\n\n const fetchFn = this.config.fetch ?? fetch;\n\n const requestHeaders: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...this.config.headers(),\n };\n\n if (headers) {\n for (const [key, value] of Object.entries(headers)) {\n if (value != null) {\n requestHeaders[key] = value;\n }\n }\n }\n\n const response = await fetchFn(url, {\n method: 'POST',\n headers: requestHeaders,\n body: JSON.stringify(requestBody),\n signal: abortSignal,\n });\n\n const responseHeaders = Object.fromEntries(response.headers.entries());\n const rawBodyText = await response.text();\n\n let parsed: any = undefined;\n try {\n parsed = rawBodyText ? JSON.parse(rawBodyText) : undefined;\n } catch {\n // ignore - we'll surface the raw body in the error below\n }\n\n if (!response.ok) {\n const message =\n (parsed && typeof parsed.error === 'string' && parsed.error) ||\n rawBodyText ||\n `HTTP ${response.status}`;\n throw new Error(`Runpod speech request failed: ${message}`);\n }\n\n const output = parsed?.output ?? parsed;\n\n const audioUrl = output?.audio_url;\n if (typeof audioUrl !== 'string' || audioUrl.length === 0) {\n throw new Error('Runpod speech response did not include an audio_url.');\n }\n\n const audioResponse = await fetchFn(audioUrl, { signal: abortSignal });\n if (!audioResponse.ok) {\n throw new Error(\n `Failed to download generated audio (${audioResponse.status}).`\n );\n }\n\n const audio = new Uint8Array(await audioResponse.arrayBuffer());\n\n const providerMetadata: Record<string, Record<string, JSONValue>> = {\n runpod: {\n audioUrl,\n ...(typeof output?.cost === 'number' ? { cost: output.cost } : {}),\n },\n };\n\n return {\n audio,\n warnings,\n request: {\n body: JSON.stringify(requestBody),\n },\n response: {\n timestamp: currentDate,\n modelId: this.modelId,\n headers: responseHeaders as any,\n body: rawBodyText,\n },\n providerMetadata,\n };\n }\n}\n"],"mappings":"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","names":["import_provider_utils","import_provider_utils","import_zod","import_provider_utils"]}