@runpod/ai-sdk-provider 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @runpod/ai-sdk-provider
2
2
 
3
+ ## 0.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 1fec4a8: added support for image gen:
8
+ - `qwen/qwen-image`
9
+ - `bytedance/seedream-3.0`
10
+ - `black-forest-labs/flux-1-kontext-dev`
11
+ - `black-forest-labs/flux-1-schnell`
12
+ - `black-forest-labs/flux-1-dev`
13
+
14
+ ## 0.1.1
15
+
16
+ ### Patch Changes
17
+
18
+ - 3c90c0e: simplified the docs
19
+
3
20
  ## 0.1.0
4
21
 
5
22
  ### Minor Changes
package/README.md CHANGED
@@ -1,16 +1,23 @@
1
- # RunPod AI SDK Provider
1
+ # Runpod AI SDK Provider
2
2
 
3
- The **RunPod provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model support for [RunPod's](https://runpod.io) public endpoints.
3
+ The **Runpod provider** for the [AI SDK](https://ai-sdk.dev/docs) contains language model and image generation support for [Runpod's](https://runpod.io) public endpoints.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
+ # npm
8
9
  npm install @runpod/ai-sdk-provider
10
+
11
+ # pnpm
12
+ pnpm add @runpod/ai-sdk-provider
13
+
14
+ # yarn
15
+ yarn add @runpod/ai-sdk-provider
9
16
  ```
10
17
 
11
18
  ## Setup
12
19
 
13
- The RunPod provider requires a RunPod API key. You can obtain one from the [RunPod console](https://runpod.io).
20
+ The Runpod provider requires a Runpod API key. You can obtain one from the [Runpod console](https://console.runpod.io/user/settings) under "API Keys".
14
21
 
15
22
  ### Environment Variable
16
23
 
@@ -25,27 +32,39 @@ export RUNPOD_API_KEY="your-api-key-here"
25
32
  Import the provider:
26
33
 
27
34
  ```ts
28
- import { runpod } from "@runpod/ai-sdk-provider";
35
+ import { runpod } from '@runpod/ai-sdk-provider';
29
36
  ```
30
37
 
31
38
  ## Supported Models
32
39
 
40
+ ### Language Models
41
+
33
42
  | Model ID | Description |
34
43
  | -------------------------------------- | ------------------------------------------------------------------- |
35
44
  | `deep-cogito/deep-cogito-v2-llama-70b` | 70B parameter general-purpose LLM with advanced reasoning |
36
45
  | `qwen/qwen3-32b-awq` | 32B parameter multilingual model with strong reasoning capabilities |
37
46
 
47
+ ### Image Models
48
+
49
+ | Model ID | Description | Supported Aspect Ratios |
50
+ | -------------------------------------- | ------------------------------- | ----------------------- |
51
+ | `qwen/qwen-image` | Text-to-image generation | 1:1, 4:3, 3:4 |
52
+ | `bytedance/seedream-3.0` | Advanced text-to-image model | 1:1, 4:3, 3:4 |
53
+ | `black-forest-labs/flux-1-kontext-dev` | Context-aware image generation | 1:1, 4:3, 3:4 |
54
+ | `black-forest-labs/flux-1-schnell` | Fast image generation (4 steps) | 1:1, 4:3, 3:4 |
55
+ | `black-forest-labs/flux-1-dev` | High-quality image generation | 1:1, 4:3, 3:4 |
56
+
38
57
  ## Usage Examples
39
58
 
40
59
  ### Basic Text Generation
41
60
 
42
61
  ```ts
43
- import { runpod } from "@runpod/ai-sdk-provider";
44
- import { generateText } from "ai";
62
+ import { runpod } from '@runpod/ai-sdk-provider';
63
+ import { generateText } from 'ai';
45
64
 
46
65
  const { text } = await generateText({
47
- model: runpod("deep-cogito/deep-cogito-v2-llama-70b"),
48
- prompt: "Write a Python function that sorts a list:",
66
+ model: runpod('deep-cogito/deep-cogito-v2-llama-70b'),
67
+ prompt: 'Write a Python function that sorts a list:',
49
68
  });
50
69
 
51
70
  console.log(text);
@@ -53,19 +72,19 @@ console.log(text);
53
72
 
54
73
  ### Streaming
55
74
 
56
- **Note**: Streaming is not yet supported by RunPod's public endpoints. The team is working on implementing this feature.
75
+ **Note**: Streaming is not yet supported by Runpod's public endpoints. The team is working on implementing this feature.
57
76
 
58
77
  ### Chat Conversations
59
78
 
60
79
  ```ts
61
- import { runpod } from "@runpod/ai-sdk-provider";
62
- import { generateText } from "ai";
80
+ import { runpod } from '@runpod/ai-sdk-provider';
81
+ import { generateText } from 'ai';
63
82
 
64
83
  const { text } = await generateText({
65
- model: runpod("deep-cogito/deep-cogito-v2-llama-70b"),
84
+ model: runpod('deep-cogito/deep-cogito-v2-llama-70b'),
66
85
  messages: [
67
- { role: "system", content: "You are a helpful assistant." },
68
- { role: "user", content: "What is the capital of France?" },
86
+ { role: 'system', content: 'You are a helpful assistant.' },
87
+ { role: 'user', content: 'What is the capital of France?' },
69
88
  ],
70
89
  });
71
90
  ```
@@ -73,18 +92,18 @@ const { text } = await generateText({
73
92
  ### Function Calling
74
93
 
75
94
  ```ts
76
- import { runpod } from "@runpod/ai-sdk-provider";
77
- import { generateText, tool } from "ai";
78
- import { z } from "zod";
95
+ import { runpod } from '@runpod/ai-sdk-provider';
96
+ import { generateText, tool } from 'ai';
97
+ import { z } from 'zod';
79
98
 
80
99
  const { text, toolCalls } = await generateText({
81
- model: runpod("deep-cogito/deep-cogito-v2-llama-70b"),
82
- prompt: "What is the weather like in San Francisco?",
100
+ model: runpod('deep-cogito/deep-cogito-v2-llama-70b'),
101
+ prompt: 'What is the weather like in San Francisco?',
83
102
  tools: {
84
103
  getWeather: tool({
85
- description: "Get weather information for a city",
104
+ description: 'Get weather information for a city',
86
105
  parameters: z.object({
87
- city: z.string().describe("The city name"),
106
+ city: z.string().describe('The city name'),
88
107
  }),
89
108
  execute: async ({ city }) => {
90
109
  // Your weather API call here
@@ -98,12 +117,12 @@ const { text, toolCalls } = await generateText({
98
117
  ### Structured Output
99
118
 
100
119
  ```ts
101
- import { runpod } from "@runpod/ai-sdk-provider";
102
- import { generateObject } from "ai";
103
- import { z } from "zod";
120
+ import { runpod } from '@runpod/ai-sdk-provider';
121
+ import { generateObject } from 'ai';
122
+ import { z } from 'zod';
104
123
 
105
124
  const { object } = await generateObject({
106
- model: runpod("qwen/qwen3-32b-awq"),
125
+ model: runpod('qwen/qwen3-32b-awq'),
107
126
  schema: z.object({
108
127
  recipe: z.object({
109
128
  name: z.string(),
@@ -111,44 +130,69 @@ const { object } = await generateObject({
111
130
  steps: z.array(z.string()),
112
131
  }),
113
132
  }),
114
- prompt: "Generate a recipe for chocolate chip cookies.",
133
+ prompt: 'Generate a recipe for chocolate chip cookies.',
115
134
  });
116
135
 
117
136
  console.log(object.recipe);
118
137
  ```
119
138
 
120
- ## Model Methods
121
-
122
- The provider supports multiple ways to create models:
139
+ ### Image Generation
123
140
 
124
141
  ```ts
125
- // Default chat model
126
- const model1 = runpod("deep-cogito/deep-cogito-v2-llama-70b");
127
-
128
- // Explicit chat model
129
- const model2 = runpod.chatModel("deep-cogito/deep-cogito-v2-llama-70b");
142
+ import { runpod } from '@runpod/ai-sdk-provider';
143
+ import { experimental_generateImage as generateImage } from 'ai';
130
144
 
131
- // Language model (alias for chat)
132
- const model3 = runpod.languageModel("qwen/qwen3-32b-awq");
145
+ const { image } = await generateImage({
146
+ model: runpod.imageModel('qwen/qwen-image'),
147
+ prompt: 'A fashion-forward woman in Paris wearing a trench coat',
148
+ aspectRatio: '4:3',
149
+ });
133
150
 
134
- // Completion model
135
- const model4 = runpod.completionModel("deep-cogito/deep-cogito-v2-llama-70b");
151
+ // With additional parameters
152
+ const { image } = await generateImage({
153
+ model: runpod.imageModel('qwen/qwen-image'),
154
+ prompt: 'A sunset over mountains',
155
+ size: '1328x1328',
156
+ seed: 42,
157
+ providerOptions: {
158
+ runpod: {
159
+ negative_prompt: 'blurry, low quality',
160
+ enable_safety_checker: true,
161
+ },
162
+ },
163
+ });
136
164
  ```
137
165
 
138
- ## API Compatibility
139
-
140
- RunPod's endpoints are OpenAI API compatible, supporting:
141
-
142
- - Chat completions (`/chat/completions`)
143
- - Text completions (`/completions`)
144
- - Function/tool calling
145
- - Structured outputs
146
-
147
- **Note**: Streaming responses are not yet supported but are being worked on.
166
+ #### Provider Options
167
+
168
+ The Runpod provider supports additional options via `providerOptions.runpod`:
169
+
170
+ | Option | Type | Default | Description |
171
+ | ----------------------- | --------- | ------- | --------------------------------------------------- |
172
+ | `negative_prompt` | `string` | - | Text describing what you don't want in the image |
173
+ | `enable_safety_checker` | `boolean` | `true` | Enable content safety filtering |
174
+ | `image` | `string` | - | Input image URL (required for Flux Kontext models) |
175
+ | `maxPollAttempts` | `number` | `60` | Maximum polling attempts for async image generation |
176
+ | `pollIntervalMillis` | `number` | `5000` | Polling interval in milliseconds (5 seconds) |
177
+
178
+ **Notes**:
179
+
180
+ - 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.
181
+ - Model availability may vary. Some models might be temporarily unavailable or require specific parameters.
182
+ - **Verified working models**: All models tested and confirmed working
183
+ - `qwen/qwen-image` - Original model (60s, JPEG)
184
+ - `bytedance/seedream-3.0` - Fast model (17s, JPEG)
185
+ - `black-forest-labs/flux-1-schnell` - Very fast (2s, PNG)
186
+ - `black-forest-labs/flux-1-dev` - High quality (6s, PNG)
187
+ - `black-forest-labs/flux-1-kontext-dev` - Context-aware with input images (38s, PNG)
188
+ - The provider automatically handles different parameter formats:
189
+ - **Qwen/Seedream**: `size` parameter, `result` response field
190
+ - **Flux standard**: `width/height` parameters, `image_url` response field
191
+ - **Flux Kontext**: `size` parameter + `image` input, `image_url` response field
148
192
 
149
193
  ## Links
150
194
 
151
- - [RunPod](https://runpod.io) - Cloud platform for AI compute
152
- - [RunPod Public Endpoints Documentation](https://docs.runpod.io/hub/public-endpoints)
195
+ - [Runpod](https://runpod.io) - Cloud platform for AI compute
196
+ - [Runpod Public Endpoints Documentation](https://docs.runpod.io/hub/public-endpoints)
153
197
  - [AI SDK Documentation](https://ai-sdk.dev/docs)
154
198
  - [GitHub Repository](https://github.com/runpod/ai-sdk-provider)
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { LanguageModelV2 } from '@ai-sdk/provider';
1
+ import { LanguageModelV2, ImageModelV2 } from '@ai-sdk/provider';
2
2
  import { FetchFunction } from '@ai-sdk/provider-utils';
3
3
  export { OpenAICompatibleErrorData as RunPodErrorData } from '@ai-sdk/openai-compatible';
4
4
 
@@ -6,6 +6,8 @@ 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';
10
+
9
11
  interface RunPodProviderSettings {
10
12
  /**
11
13
  RunPod API key.
@@ -38,8 +40,12 @@ interface RunPodProvider {
38
40
  Creates a completion model for text generation.
39
41
  */
40
42
  completionModel(modelId: RunPodCompletionModelId): LanguageModelV2;
43
+ /**
44
+ Creates an image model for image generation.
45
+ */
46
+ imageModel(modelId: RunpodImageModelId): ImageModelV2;
41
47
  }
42
48
  declare function createRunPod(options?: RunPodProviderSettings): RunPodProvider;
43
49
  declare const runpod: RunPodProvider;
44
50
 
45
- export { type RunPodChatModelId, type RunPodCompletionModelId, type RunPodProvider, type RunPodProviderSettings, createRunPod, runpod };
51
+ export { type RunPodChatModelId, type RunPodCompletionModelId, type RunPodProvider, type RunPodProviderSettings, type RunpodImageModelId, createRunPod, runpod };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { LanguageModelV2 } from '@ai-sdk/provider';
1
+ import { LanguageModelV2, ImageModelV2 } from '@ai-sdk/provider';
2
2
  import { FetchFunction } from '@ai-sdk/provider-utils';
3
3
  export { OpenAICompatibleErrorData as RunPodErrorData } from '@ai-sdk/openai-compatible';
4
4
 
@@ -6,6 +6,8 @@ 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';
10
+
9
11
  interface RunPodProviderSettings {
10
12
  /**
11
13
  RunPod API key.
@@ -38,8 +40,12 @@ interface RunPodProvider {
38
40
  Creates a completion model for text generation.
39
41
  */
40
42
  completionModel(modelId: RunPodCompletionModelId): LanguageModelV2;
43
+ /**
44
+ Creates an image model for image generation.
45
+ */
46
+ imageModel(modelId: RunpodImageModelId): ImageModelV2;
41
47
  }
42
48
  declare function createRunPod(options?: RunPodProviderSettings): RunPodProvider;
43
49
  declare const runpod: RunPodProvider;
44
50
 
45
- export { type RunPodChatModelId, type RunPodCompletionModelId, type RunPodProvider, type RunPodProviderSettings, createRunPod, runpod };
51
+ export { type RunPodChatModelId, type RunPodCompletionModelId, type RunPodProvider, type RunPodProviderSettings, type RunpodImageModelId, createRunPod, runpod };
package/dist/index.js CHANGED
@@ -27,18 +27,307 @@ module.exports = __toCommonJS(index_exports);
27
27
 
28
28
  // src/runpod-provider.ts
29
29
  var import_openai_compatible = require("@ai-sdk/openai-compatible");
30
+ var import_provider_utils2 = require("@ai-sdk/provider-utils");
31
+
32
+ // src/runpod-image-model.ts
30
33
  var import_provider_utils = require("@ai-sdk/provider-utils");
34
+ var import_provider = require("@ai-sdk/provider");
35
+ var import_zod = require("zod");
36
+ var SUPPORTED_ASPECT_RATIOS = {
37
+ "1:1": "1328*1328",
38
+ // ✅ Native support
39
+ "4:3": "1472*1140",
40
+ // ✅ Native support
41
+ "3:4": "1140*1472"
42
+ // ✅ Native support
43
+ };
44
+ var SUPPORTED_SIZES = /* @__PURE__ */ new Set([
45
+ // Native aspect ratio sizes
46
+ "1328*1328",
47
+ // 1:1
48
+ "1472*1140",
49
+ // 4:3
50
+ "1140*1472",
51
+ // 3:4
52
+ // Additional validated sizes
53
+ "512*512",
54
+ "768*768",
55
+ "1024*1024",
56
+ "512*768",
57
+ "768*512",
58
+ "1024*768",
59
+ "768*1024"
60
+ ]);
61
+ var RunpodImageModel = class {
62
+ constructor(modelId, config) {
63
+ this.modelId = modelId;
64
+ this.config = config;
65
+ this.specificationVersion = "v2";
66
+ this.maxImagesPerCall = 1;
67
+ }
68
+ get provider() {
69
+ return this.config.provider;
70
+ }
71
+ async doGenerate({
72
+ prompt,
73
+ n = 1,
74
+ size,
75
+ aspectRatio,
76
+ seed,
77
+ providerOptions,
78
+ headers,
79
+ abortSignal
80
+ }) {
81
+ const warnings = [];
82
+ let runpodSize;
83
+ if (size) {
84
+ const runpodSizeCandidate = size.replace("x", "*");
85
+ if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {
86
+ throw new import_provider.InvalidArgumentError({
87
+ argument: "size",
88
+ message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(
89
+ SUPPORTED_SIZES
90
+ ).map((s) => s.replace("*", "x")).join(", ")}`
91
+ });
92
+ }
93
+ runpodSize = runpodSizeCandidate;
94
+ } else if (aspectRatio) {
95
+ if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {
96
+ throw new import_provider.InvalidArgumentError({
97
+ argument: "aspectRatio",
98
+ message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(", ")}`
99
+ });
100
+ }
101
+ runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];
102
+ } else {
103
+ runpodSize = "1328*1328";
104
+ }
105
+ if (n > 1) {
106
+ warnings.push({
107
+ type: "unsupported-setting",
108
+ setting: "n",
109
+ details: "Runpod image models only support generating 1 image at a time. Using n=1."
110
+ });
111
+ }
112
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
113
+ const inputPayload = this.buildInputPayload(
114
+ prompt,
115
+ runpodSize,
116
+ seed,
117
+ providerOptions.runpod
118
+ );
119
+ const { value: response, responseHeaders } = await (0, import_provider_utils.postJsonToApi)({
120
+ url: `${this.config.baseURL}/runsync`,
121
+ headers: (0, import_provider_utils.combineHeaders)(this.config.headers(), headers),
122
+ body: {
123
+ input: inputPayload
124
+ },
125
+ failedResponseHandler: (0, import_provider_utils.createJsonErrorResponseHandler)({
126
+ errorSchema: runpodImageErrorSchema,
127
+ errorToMessage: (data) => data.error ?? "Unknown error"
128
+ }),
129
+ successfulResponseHandler: (0, import_provider_utils.createJsonResponseHandler)(
130
+ runpodImageResponseSchema
131
+ ),
132
+ abortSignal,
133
+ fetch: this.config.fetch
134
+ });
135
+ const typedResponse = response;
136
+ if (typedResponse.status === "COMPLETED" && (typedResponse.output?.result || typedResponse.output?.image_url)) {
137
+ const imageUrl = typedResponse.output.result || typedResponse.output.image_url;
138
+ const imageData = await this.downloadImage(imageUrl, abortSignal);
139
+ return {
140
+ images: [imageData],
141
+ warnings,
142
+ response: {
143
+ timestamp: currentDate,
144
+ modelId: this.modelId,
145
+ headers: responseHeaders
146
+ },
147
+ providerMetadata: {
148
+ runpod: {
149
+ images: [
150
+ {
151
+ url: imageUrl,
152
+ cost: typedResponse.output?.cost
153
+ }
154
+ ]
155
+ }
156
+ }
157
+ };
158
+ } else if (typedResponse.status === "IN_QUEUE" || typedResponse.status === "IN_PROGRESS") {
159
+ const pollOptions = {
160
+ maxAttempts: providerOptions.runpod?.maxPollAttempts,
161
+ pollIntervalMillis: providerOptions.runpod?.pollIntervalMillis
162
+ };
163
+ const imageUrl = await this.pollForCompletion(
164
+ typedResponse.id,
165
+ abortSignal,
166
+ pollOptions
167
+ );
168
+ const imageData = await this.downloadImage(imageUrl, abortSignal);
169
+ return {
170
+ images: [imageData],
171
+ warnings,
172
+ response: {
173
+ timestamp: currentDate,
174
+ modelId: this.modelId,
175
+ headers: responseHeaders
176
+ },
177
+ providerMetadata: {
178
+ runpod: {
179
+ images: [
180
+ {
181
+ url: imageUrl,
182
+ jobId: typedResponse.id
183
+ }
184
+ ]
185
+ }
186
+ }
187
+ };
188
+ } else {
189
+ throw new Error(`Unexpected response status: ${typedResponse.status}`);
190
+ }
191
+ }
192
+ async downloadImage(imageUrl, abortSignal) {
193
+ const { value: imageData } = await (0, import_provider_utils.getFromApi)({
194
+ url: imageUrl,
195
+ successfulResponseHandler: (0, import_provider_utils.createBinaryResponseHandler)(),
196
+ failedResponseHandler: (0, import_provider_utils.createJsonErrorResponseHandler)({
197
+ errorSchema: runpodImageErrorSchema,
198
+ errorToMessage: (data) => data.error ?? "Failed to download image"
199
+ }),
200
+ abortSignal,
201
+ fetch: this.config.fetch
202
+ });
203
+ return imageData;
204
+ }
205
+ async pollForCompletion(jobId, abortSignal, pollOptions) {
206
+ const maxAttempts = pollOptions?.maxAttempts ?? 60;
207
+ const pollInterval = pollOptions?.pollIntervalMillis ?? 5e3;
208
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
209
+ if (abortSignal?.aborted) {
210
+ throw new Error("Image generation was aborted");
211
+ }
212
+ const { value: statusResponse } = await (0, import_provider_utils.getFromApi)({
213
+ url: `${this.config.baseURL}/status/${jobId}`,
214
+ headers: this.config.headers(),
215
+ successfulResponseHandler: (0, import_provider_utils.createJsonResponseHandler)(
216
+ runpodImageStatusSchema
217
+ ),
218
+ failedResponseHandler: (0, import_provider_utils.createJsonErrorResponseHandler)({
219
+ errorSchema: runpodImageErrorSchema,
220
+ errorToMessage: (data) => data.error ?? "Failed to check job status"
221
+ }),
222
+ abortSignal,
223
+ fetch: this.config.fetch
224
+ });
225
+ const typedStatusResponse = statusResponse;
226
+ if (typedStatusResponse.status === "COMPLETED" && (typedStatusResponse.output?.result || typedStatusResponse.output?.image_url)) {
227
+ return typedStatusResponse.output.result || typedStatusResponse.output.image_url;
228
+ }
229
+ if (typedStatusResponse.status === "FAILED") {
230
+ throw new Error(
231
+ `Image generation failed: ${typedStatusResponse.error || "Unknown error"}`
232
+ );
233
+ }
234
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
235
+ }
236
+ throw new Error(
237
+ `Image generation timed out after ${maxAttempts} attempts (${maxAttempts * pollInterval / 1e3}s)`
238
+ );
239
+ }
240
+ buildInputPayload(prompt, runpodSize, seed, runpodOptions) {
241
+ const isFluxModel = this.modelId.includes("flux") || this.modelId.includes("black-forest-labs");
242
+ if (isFluxModel) {
243
+ const isKontext = this.modelId.includes("kontext");
244
+ if (isKontext) {
245
+ return {
246
+ prompt,
247
+ negative_prompt: runpodOptions?.negative_prompt ?? "",
248
+ seed: seed ?? -1,
249
+ num_inference_steps: 28,
250
+ guidance: 2,
251
+ size: runpodSize,
252
+ output_format: "png",
253
+ enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
254
+ ...runpodOptions
255
+ // This will include the 'image' parameter if provided
256
+ };
257
+ } else {
258
+ const [width, height] = runpodSize.split("*").map(Number);
259
+ return {
260
+ prompt,
261
+ negative_prompt: runpodOptions?.negative_prompt ?? "",
262
+ seed: seed ?? -1,
263
+ num_inference_steps: this.modelId.includes("schnell") ? 4 : 28,
264
+ guidance: this.modelId.includes("schnell") ? 7 : 2,
265
+ width,
266
+ height,
267
+ image_format: "png",
268
+ ...runpodOptions
269
+ };
270
+ }
271
+ }
272
+ return {
273
+ prompt,
274
+ negative_prompt: runpodOptions?.negative_prompt ?? "",
275
+ size: runpodSize,
276
+ seed: seed ?? -1,
277
+ enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
278
+ ...runpodOptions
279
+ };
280
+ }
281
+ };
282
+ var runpodImageResponseSchema = import_zod.z.object({
283
+ id: import_zod.z.string(),
284
+ status: import_zod.z.enum(["COMPLETED", "IN_QUEUE", "IN_PROGRESS", "FAILED"]),
285
+ delayTime: import_zod.z.number().optional(),
286
+ executionTime: import_zod.z.number().optional(),
287
+ output: import_zod.z.object({
288
+ cost: import_zod.z.number().optional(),
289
+ result: import_zod.z.string().optional(),
290
+ // URL to the generated image (Qwen format)
291
+ image_url: import_zod.z.string().optional()
292
+ // URL to the generated image (Flux format)
293
+ }).optional()
294
+ // Optional for IN_QUEUE/IN_PROGRESS responses
295
+ });
296
+ var runpodImageStatusSchema = import_zod.z.object({
297
+ id: import_zod.z.string(),
298
+ status: import_zod.z.enum(["COMPLETED", "IN_QUEUE", "IN_PROGRESS", "FAILED"]),
299
+ output: import_zod.z.object({
300
+ cost: import_zod.z.number().optional(),
301
+ result: import_zod.z.string().optional(),
302
+ image_url: import_zod.z.string().optional()
303
+ }).optional(),
304
+ error: import_zod.z.string().optional()
305
+ // Error message if FAILED
306
+ });
307
+ var runpodImageErrorSchema = import_zod.z.object({
308
+ error: import_zod.z.string(),
309
+ message: import_zod.z.string().optional()
310
+ });
311
+
312
+ // src/runpod-provider.ts
31
313
  var MODEL_ID_TO_ENDPOINT_URL = {
32
314
  "deep-cogito/deep-cogito-v2-llama-70b": "https://api.runpod.ai/v2/deep-cogito-v2-llama-70b/openai/v1",
33
315
  "qwen/qwen3-32b-awq": "https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1"
34
316
  };
317
+ var IMAGE_MODEL_ID_TO_ENDPOINT_URL = {
318
+ "qwen/qwen-image": "https://api.runpod.ai/v2/qwen-image-t2i",
319
+ "bytedance/seedream-3.0": "https://api.runpod.ai/v2/seedream-3-0-t2i",
320
+ "black-forest-labs/flux-1-kontext-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev",
321
+ "black-forest-labs/flux-1-schnell": "https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell",
322
+ "black-forest-labs/flux-1-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-dev"
323
+ };
35
324
  var MODEL_ID_TO_OPENAI_NAME = {
36
325
  "deep-cogito/deep-cogito-v2-llama-70b": "deepcogito/cogito-v2-preview-llama-70B",
37
326
  "qwen/qwen3-32b-awq": "Qwen/Qwen3-32B-AWQ"
38
327
  };
39
328
  function createRunPod(options = {}) {
40
329
  const getHeaders = () => ({
41
- Authorization: `Bearer ${(0, import_provider_utils.loadApiKey)({
330
+ Authorization: `Bearer ${(0, import_provider_utils2.loadApiKey)({
42
331
  apiKey: options.apiKey,
43
332
  environmentVariableName: "RUNPOD_API_KEY",
44
333
  description: "RunPod"
@@ -56,7 +345,7 @@ function createRunPod(options = {}) {
56
345
  }
57
346
  return {
58
347
  provider: `runpod.${modelType}`,
59
- url: ({ path }) => `${(0, import_provider_utils.withoutTrailingSlash)(baseURL)}${path}`,
348
+ url: ({ path }) => `${(0, import_provider_utils2.withoutTrailingSlash)(baseURL)}${path}`,
60
349
  headers: getHeaders,
61
350
  fetch: options.fetch
62
351
  };
@@ -75,10 +364,27 @@ function createRunPod(options = {}) {
75
364
  getModelConfig(modelId, "completion")
76
365
  );
77
366
  };
367
+ const createImageModel = (modelId) => {
368
+ const baseURL = IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId];
369
+ if (!baseURL) {
370
+ throw new Error(
371
+ `Unsupported Runpod image model: ${modelId}. Supported models: ${Object.keys(
372
+ IMAGE_MODEL_ID_TO_ENDPOINT_URL
373
+ ).join(", ")}`
374
+ );
375
+ }
376
+ return new RunpodImageModel(modelId, {
377
+ provider: "runpod.image",
378
+ baseURL,
379
+ headers: getHeaders,
380
+ fetch: options.fetch
381
+ });
382
+ };
78
383
  const provider = (modelId) => createChatModel(modelId);
79
384
  provider.completionModel = createCompletionModel;
80
385
  provider.languageModel = createChatModel;
81
386
  provider.chatModel = createChatModel;
387
+ provider.imageModel = createImageModel;
82
388
  return provider;
83
389
  }
84
390
  var runpod = createRunPod();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/runpod-provider.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 { OpenAICompatibleErrorData as RunPodErrorData } from '@ai-sdk/openai-compatible';\n","import { LanguageModelV2 } 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';\n\nexport interface RunPodProviderSettings {\n /**\nRunPod API key.\n*/\n apiKey?: 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\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 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 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 const 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(', ')}`\n );\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n };\n };\n\n const createChatModel = (modelId: RunPodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'chat')\n );\n };\n\n const createCompletionModel = (modelId: RunPodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'completion')\n );\n };\n\n const provider = (modelId: RunPodChatModelId) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n\n return provider;\n}\n\nexport const runpod = createRunPod();\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,+BAGO;AACP,4BAIO;AA2CP,IAAM,2BAAmD;AAAA,EACvD,wCACE;AAAA,EACF,sBAAsB;AACxB;AAGA,IAAM,0BAAkD;AAAA,EACtD,wCACE;AAAA,EACF,sBAAsB;AACxB;AAEO,SAAS,aACd,UAAkC,CAAC,GACnB;AAChB,QAAM,aAAa,OAAO;AAAA,IACxB,eAAe,cAAU,kCAAW;AAAA,MAClC,QAAQ,QAAQ;AAAA,MAChB,yBAAyB;AAAA,MACzB,aAAa;AAAA,IACf,CAAC,CAAC;AAAA,IACF,GAAG,QAAQ;AAAA,EACb;AASA,QAAM,iBAAiB,CACrB,SACA,cACsB;AACtB,UAAM,UAAU,yBAAyB,OAAO;AAChD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR,6BAA6B,OAAO,uBAAuB,OAAO;AAAA,UAChE;AAAA,QACF,EAAE,KAAK,IAAI,CAAC;AAAA,MACd;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU,UAAU,SAAS;AAAA,MAC7B,KAAK,CAAC,EAAE,KAAK,MAAM,OAAG,4CAAqB,OAAO,CAAC,GAAG,IAAI;AAAA,MAC1D,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,kBAAkB,CAAC,YAA+B;AACtD,UAAM,kBAAkB,wBAAwB,OAAO,KAAK;AAC5D,WAAO,IAAI;AAAA,MACT;AAAA,MACA,eAAe,SAAS,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,QAAM,wBAAwB,CAAC,YAAqC;AAClE,UAAM,kBAAkB,wBAAwB,OAAO,KAAK;AAC5D,WAAO,IAAI;AAAA,MACT;AAAA,MACA,eAAe,SAAS,YAAY;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,YAA+B,gBAAgB,OAAO;AAExE,WAAS,kBAAkB;AAC3B,WAAS,gBAAgB;AACzB,WAAS,YAAY;AAErB,SAAO;AACT;AAEO,IAAM,SAAS,aAAa;","names":[]}
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 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 '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 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 const 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(', ')}`\n );\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n };\n };\n\n const createChatModel = (modelId: RunPodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'chat')\n );\n };\n\n const createCompletionModel = (modelId: RunPodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'completion')\n );\n };\n\n const createImageModel = (modelId: RunpodImageModelId) => {\n const 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(', ')}`\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"]}
package/dist/index.mjs CHANGED
@@ -7,10 +7,306 @@ import {
7
7
  loadApiKey,
8
8
  withoutTrailingSlash
9
9
  } from "@ai-sdk/provider-utils";
10
+
11
+ // src/runpod-image-model.ts
12
+ import {
13
+ combineHeaders,
14
+ createJsonResponseHandler,
15
+ createJsonErrorResponseHandler,
16
+ createBinaryResponseHandler,
17
+ postJsonToApi,
18
+ getFromApi
19
+ } from "@ai-sdk/provider-utils";
20
+ import { InvalidArgumentError } from "@ai-sdk/provider";
21
+ import { z } from "zod";
22
+ var SUPPORTED_ASPECT_RATIOS = {
23
+ "1:1": "1328*1328",
24
+ // ✅ Native support
25
+ "4:3": "1472*1140",
26
+ // ✅ Native support
27
+ "3:4": "1140*1472"
28
+ // ✅ Native support
29
+ };
30
+ var SUPPORTED_SIZES = /* @__PURE__ */ new Set([
31
+ // Native aspect ratio sizes
32
+ "1328*1328",
33
+ // 1:1
34
+ "1472*1140",
35
+ // 4:3
36
+ "1140*1472",
37
+ // 3:4
38
+ // Additional validated sizes
39
+ "512*512",
40
+ "768*768",
41
+ "1024*1024",
42
+ "512*768",
43
+ "768*512",
44
+ "1024*768",
45
+ "768*1024"
46
+ ]);
47
+ var RunpodImageModel = class {
48
+ constructor(modelId, config) {
49
+ this.modelId = modelId;
50
+ this.config = config;
51
+ this.specificationVersion = "v2";
52
+ this.maxImagesPerCall = 1;
53
+ }
54
+ get provider() {
55
+ return this.config.provider;
56
+ }
57
+ async doGenerate({
58
+ prompt,
59
+ n = 1,
60
+ size,
61
+ aspectRatio,
62
+ seed,
63
+ providerOptions,
64
+ headers,
65
+ abortSignal
66
+ }) {
67
+ const warnings = [];
68
+ let runpodSize;
69
+ if (size) {
70
+ const runpodSizeCandidate = size.replace("x", "*");
71
+ if (!SUPPORTED_SIZES.has(runpodSizeCandidate)) {
72
+ throw new InvalidArgumentError({
73
+ argument: "size",
74
+ message: `Size ${size} is not supported by Runpod. Supported sizes: ${Array.from(
75
+ SUPPORTED_SIZES
76
+ ).map((s) => s.replace("*", "x")).join(", ")}`
77
+ });
78
+ }
79
+ runpodSize = runpodSizeCandidate;
80
+ } else if (aspectRatio) {
81
+ if (!SUPPORTED_ASPECT_RATIOS[aspectRatio]) {
82
+ throw new InvalidArgumentError({
83
+ argument: "aspectRatio",
84
+ message: `Aspect ratio ${aspectRatio} is not supported by Runpod. Supported aspect ratios: ${Object.keys(SUPPORTED_ASPECT_RATIOS).join(", ")}`
85
+ });
86
+ }
87
+ runpodSize = SUPPORTED_ASPECT_RATIOS[aspectRatio];
88
+ } else {
89
+ runpodSize = "1328*1328";
90
+ }
91
+ if (n > 1) {
92
+ warnings.push({
93
+ type: "unsupported-setting",
94
+ setting: "n",
95
+ details: "Runpod image models only support generating 1 image at a time. Using n=1."
96
+ });
97
+ }
98
+ const currentDate = this.config._internal?.currentDate?.() ?? /* @__PURE__ */ new Date();
99
+ const inputPayload = this.buildInputPayload(
100
+ prompt,
101
+ runpodSize,
102
+ seed,
103
+ providerOptions.runpod
104
+ );
105
+ const { value: response, responseHeaders } = await postJsonToApi({
106
+ url: `${this.config.baseURL}/runsync`,
107
+ headers: combineHeaders(this.config.headers(), headers),
108
+ body: {
109
+ input: inputPayload
110
+ },
111
+ failedResponseHandler: createJsonErrorResponseHandler({
112
+ errorSchema: runpodImageErrorSchema,
113
+ errorToMessage: (data) => data.error ?? "Unknown error"
114
+ }),
115
+ successfulResponseHandler: createJsonResponseHandler(
116
+ runpodImageResponseSchema
117
+ ),
118
+ abortSignal,
119
+ fetch: this.config.fetch
120
+ });
121
+ const typedResponse = response;
122
+ if (typedResponse.status === "COMPLETED" && (typedResponse.output?.result || typedResponse.output?.image_url)) {
123
+ const imageUrl = typedResponse.output.result || typedResponse.output.image_url;
124
+ const imageData = await this.downloadImage(imageUrl, abortSignal);
125
+ return {
126
+ images: [imageData],
127
+ warnings,
128
+ response: {
129
+ timestamp: currentDate,
130
+ modelId: this.modelId,
131
+ headers: responseHeaders
132
+ },
133
+ providerMetadata: {
134
+ runpod: {
135
+ images: [
136
+ {
137
+ url: imageUrl,
138
+ cost: typedResponse.output?.cost
139
+ }
140
+ ]
141
+ }
142
+ }
143
+ };
144
+ } else if (typedResponse.status === "IN_QUEUE" || typedResponse.status === "IN_PROGRESS") {
145
+ const pollOptions = {
146
+ maxAttempts: providerOptions.runpod?.maxPollAttempts,
147
+ pollIntervalMillis: providerOptions.runpod?.pollIntervalMillis
148
+ };
149
+ const imageUrl = await this.pollForCompletion(
150
+ typedResponse.id,
151
+ abortSignal,
152
+ pollOptions
153
+ );
154
+ const imageData = await this.downloadImage(imageUrl, abortSignal);
155
+ return {
156
+ images: [imageData],
157
+ warnings,
158
+ response: {
159
+ timestamp: currentDate,
160
+ modelId: this.modelId,
161
+ headers: responseHeaders
162
+ },
163
+ providerMetadata: {
164
+ runpod: {
165
+ images: [
166
+ {
167
+ url: imageUrl,
168
+ jobId: typedResponse.id
169
+ }
170
+ ]
171
+ }
172
+ }
173
+ };
174
+ } else {
175
+ throw new Error(`Unexpected response status: ${typedResponse.status}`);
176
+ }
177
+ }
178
+ async downloadImage(imageUrl, abortSignal) {
179
+ const { value: imageData } = await getFromApi({
180
+ url: imageUrl,
181
+ successfulResponseHandler: createBinaryResponseHandler(),
182
+ failedResponseHandler: createJsonErrorResponseHandler({
183
+ errorSchema: runpodImageErrorSchema,
184
+ errorToMessage: (data) => data.error ?? "Failed to download image"
185
+ }),
186
+ abortSignal,
187
+ fetch: this.config.fetch
188
+ });
189
+ return imageData;
190
+ }
191
+ async pollForCompletion(jobId, abortSignal, pollOptions) {
192
+ const maxAttempts = pollOptions?.maxAttempts ?? 60;
193
+ const pollInterval = pollOptions?.pollIntervalMillis ?? 5e3;
194
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
195
+ if (abortSignal?.aborted) {
196
+ throw new Error("Image generation was aborted");
197
+ }
198
+ const { value: statusResponse } = await getFromApi({
199
+ url: `${this.config.baseURL}/status/${jobId}`,
200
+ headers: this.config.headers(),
201
+ successfulResponseHandler: createJsonResponseHandler(
202
+ runpodImageStatusSchema
203
+ ),
204
+ failedResponseHandler: createJsonErrorResponseHandler({
205
+ errorSchema: runpodImageErrorSchema,
206
+ errorToMessage: (data) => data.error ?? "Failed to check job status"
207
+ }),
208
+ abortSignal,
209
+ fetch: this.config.fetch
210
+ });
211
+ const typedStatusResponse = statusResponse;
212
+ if (typedStatusResponse.status === "COMPLETED" && (typedStatusResponse.output?.result || typedStatusResponse.output?.image_url)) {
213
+ return typedStatusResponse.output.result || typedStatusResponse.output.image_url;
214
+ }
215
+ if (typedStatusResponse.status === "FAILED") {
216
+ throw new Error(
217
+ `Image generation failed: ${typedStatusResponse.error || "Unknown error"}`
218
+ );
219
+ }
220
+ await new Promise((resolve) => setTimeout(resolve, pollInterval));
221
+ }
222
+ throw new Error(
223
+ `Image generation timed out after ${maxAttempts} attempts (${maxAttempts * pollInterval / 1e3}s)`
224
+ );
225
+ }
226
+ buildInputPayload(prompt, runpodSize, seed, runpodOptions) {
227
+ const isFluxModel = this.modelId.includes("flux") || this.modelId.includes("black-forest-labs");
228
+ if (isFluxModel) {
229
+ const isKontext = this.modelId.includes("kontext");
230
+ if (isKontext) {
231
+ return {
232
+ prompt,
233
+ negative_prompt: runpodOptions?.negative_prompt ?? "",
234
+ seed: seed ?? -1,
235
+ num_inference_steps: 28,
236
+ guidance: 2,
237
+ size: runpodSize,
238
+ output_format: "png",
239
+ enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
240
+ ...runpodOptions
241
+ // This will include the 'image' parameter if provided
242
+ };
243
+ } else {
244
+ const [width, height] = runpodSize.split("*").map(Number);
245
+ return {
246
+ prompt,
247
+ negative_prompt: runpodOptions?.negative_prompt ?? "",
248
+ seed: seed ?? -1,
249
+ num_inference_steps: this.modelId.includes("schnell") ? 4 : 28,
250
+ guidance: this.modelId.includes("schnell") ? 7 : 2,
251
+ width,
252
+ height,
253
+ image_format: "png",
254
+ ...runpodOptions
255
+ };
256
+ }
257
+ }
258
+ return {
259
+ prompt,
260
+ negative_prompt: runpodOptions?.negative_prompt ?? "",
261
+ size: runpodSize,
262
+ seed: seed ?? -1,
263
+ enable_safety_checker: runpodOptions?.enable_safety_checker ?? true,
264
+ ...runpodOptions
265
+ };
266
+ }
267
+ };
268
+ var runpodImageResponseSchema = z.object({
269
+ id: z.string(),
270
+ status: z.enum(["COMPLETED", "IN_QUEUE", "IN_PROGRESS", "FAILED"]),
271
+ delayTime: z.number().optional(),
272
+ executionTime: z.number().optional(),
273
+ output: z.object({
274
+ cost: z.number().optional(),
275
+ result: z.string().optional(),
276
+ // URL to the generated image (Qwen format)
277
+ image_url: z.string().optional()
278
+ // URL to the generated image (Flux format)
279
+ }).optional()
280
+ // Optional for IN_QUEUE/IN_PROGRESS responses
281
+ });
282
+ var runpodImageStatusSchema = z.object({
283
+ id: z.string(),
284
+ status: z.enum(["COMPLETED", "IN_QUEUE", "IN_PROGRESS", "FAILED"]),
285
+ output: z.object({
286
+ cost: z.number().optional(),
287
+ result: z.string().optional(),
288
+ image_url: z.string().optional()
289
+ }).optional(),
290
+ error: z.string().optional()
291
+ // Error message if FAILED
292
+ });
293
+ var runpodImageErrorSchema = z.object({
294
+ error: z.string(),
295
+ message: z.string().optional()
296
+ });
297
+
298
+ // src/runpod-provider.ts
10
299
  var MODEL_ID_TO_ENDPOINT_URL = {
11
300
  "deep-cogito/deep-cogito-v2-llama-70b": "https://api.runpod.ai/v2/deep-cogito-v2-llama-70b/openai/v1",
12
301
  "qwen/qwen3-32b-awq": "https://api.runpod.ai/v2/qwen3-32b-awq/openai/v1"
13
302
  };
303
+ var IMAGE_MODEL_ID_TO_ENDPOINT_URL = {
304
+ "qwen/qwen-image": "https://api.runpod.ai/v2/qwen-image-t2i",
305
+ "bytedance/seedream-3.0": "https://api.runpod.ai/v2/seedream-3-0-t2i",
306
+ "black-forest-labs/flux-1-kontext-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-kontext-dev",
307
+ "black-forest-labs/flux-1-schnell": "https://api.runpod.ai/v2/black-forest-labs-flux-1-schnell",
308
+ "black-forest-labs/flux-1-dev": "https://api.runpod.ai/v2/black-forest-labs-flux-1-dev"
309
+ };
14
310
  var MODEL_ID_TO_OPENAI_NAME = {
15
311
  "deep-cogito/deep-cogito-v2-llama-70b": "deepcogito/cogito-v2-preview-llama-70B",
16
312
  "qwen/qwen3-32b-awq": "Qwen/Qwen3-32B-AWQ"
@@ -54,10 +350,27 @@ function createRunPod(options = {}) {
54
350
  getModelConfig(modelId, "completion")
55
351
  );
56
352
  };
353
+ const createImageModel = (modelId) => {
354
+ const baseURL = IMAGE_MODEL_ID_TO_ENDPOINT_URL[modelId];
355
+ if (!baseURL) {
356
+ throw new Error(
357
+ `Unsupported Runpod image model: ${modelId}. Supported models: ${Object.keys(
358
+ IMAGE_MODEL_ID_TO_ENDPOINT_URL
359
+ ).join(", ")}`
360
+ );
361
+ }
362
+ return new RunpodImageModel(modelId, {
363
+ provider: "runpod.image",
364
+ baseURL,
365
+ headers: getHeaders,
366
+ fetch: options.fetch
367
+ });
368
+ };
57
369
  const provider = (modelId) => createChatModel(modelId);
58
370
  provider.completionModel = createCompletionModel;
59
371
  provider.languageModel = createChatModel;
60
372
  provider.chatModel = createChatModel;
373
+ provider.imageModel = createImageModel;
61
374
  return provider;
62
375
  }
63
376
  var runpod = createRunPod();
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/runpod-provider.ts"],"sourcesContent":["import { LanguageModelV2 } 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';\n\nexport interface RunPodProviderSettings {\n /**\nRunPod API key.\n*/\n apiKey?: 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\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 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 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 const 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(', ')}`\n );\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n };\n };\n\n const createChatModel = (modelId: RunPodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'chat')\n );\n };\n\n const createCompletionModel = (modelId: RunPodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'completion')\n );\n };\n\n const provider = (modelId: RunPodChatModelId) => createChatModel(modelId);\n\n provider.completionModel = createCompletionModel;\n provider.languageModel = createChatModel;\n provider.chatModel = createChatModel;\n\n return provider;\n}\n\nexport const runpod = createRunPod();\n"],"mappings":";AACA;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EAEE;AAAA,EACA;AAAA,OACK;AA2CP,IAAM,2BAAmD;AAAA,EACvD,wCACE;AAAA,EACF,sBAAsB;AACxB;AAGA,IAAM,0BAAkD;AAAA,EACtD,wCACE;AAAA,EACF,sBAAsB;AACxB;AAEO,SAAS,aACd,UAAkC,CAAC,GACnB;AAChB,QAAM,aAAa,OAAO;AAAA,IACxB,eAAe,UAAU,WAAW;AAAA,MAClC,QAAQ,QAAQ;AAAA,MAChB,yBAAyB;AAAA,MACzB,aAAa;AAAA,IACf,CAAC,CAAC;AAAA,IACF,GAAG,QAAQ;AAAA,EACb;AASA,QAAM,iBAAiB,CACrB,SACA,cACsB;AACtB,UAAM,UAAU,yBAAyB,OAAO;AAChD,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI;AAAA,QACR,6BAA6B,OAAO,uBAAuB,OAAO;AAAA,UAChE;AAAA,QACF,EAAE,KAAK,IAAI,CAAC;AAAA,MACd;AAAA,IACF;AAEA,WAAO;AAAA,MACL,UAAU,UAAU,SAAS;AAAA,MAC7B,KAAK,CAAC,EAAE,KAAK,MAAM,GAAG,qBAAqB,OAAO,CAAC,GAAG,IAAI;AAAA,MAC1D,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,IACjB;AAAA,EACF;AAEA,QAAM,kBAAkB,CAAC,YAA+B;AACtD,UAAM,kBAAkB,wBAAwB,OAAO,KAAK;AAC5D,WAAO,IAAI;AAAA,MACT;AAAA,MACA,eAAe,SAAS,MAAM;AAAA,IAChC;AAAA,EACF;AAEA,QAAM,wBAAwB,CAAC,YAAqC;AAClE,UAAM,kBAAkB,wBAAwB,OAAO,KAAK;AAC5D,WAAO,IAAI;AAAA,MACT;AAAA,MACA,eAAe,SAAS,YAAY;AAAA,IACtC;AAAA,EACF;AAEA,QAAM,WAAW,CAAC,YAA+B,gBAAgB,OAAO;AAExE,WAAS,kBAAkB;AAC3B,WAAS,gBAAgB;AACzB,WAAS,YAAY;AAErB,SAAO;AACT;AAEO,IAAM,SAAS,aAAa;","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 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 '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 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 const 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(', ')}`\n );\n }\n\n return {\n provider: `runpod.${modelType}`,\n url: ({ path }) => `${withoutTrailingSlash(baseURL)}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n };\n };\n\n const createChatModel = (modelId: RunPodChatModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleChatLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'chat')\n );\n };\n\n const createCompletionModel = (modelId: RunPodCompletionModelId) => {\n const openaiModelName = MODEL_ID_TO_OPENAI_NAME[modelId] || modelId;\n return new OpenAICompatibleCompletionLanguageModel(\n openaiModelName,\n getModelConfig(modelId, 'completion')\n );\n };\n\n const createImageModel = (modelId: RunpodImageModelId) => {\n const 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(', ')}`\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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runpod/ai-sdk-provider",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "license": "Apache-2.0",
5
5
  "sideEffects": false,
6
6
  "main": "./dist/index.js",