@ai-sdk/prodia 2.0.0-beta.3 → 2.0.0-beta.30

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
@@ -1,39 +1,176 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
1
+ // src/prodia-provider.ts
2
+ import {
3
+ NoSuchModelError
4
+ } from "@ai-sdk/provider";
5
+ import {
6
+ loadApiKey,
7
+ withoutTrailingSlash,
8
+ withUserAgentSuffix
9
+ } from "@ai-sdk/provider-utils";
19
10
 
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- VERSION: () => VERSION,
24
- createProdia: () => createProdia,
25
- prodia: () => prodia
26
- });
27
- module.exports = __toCommonJS(index_exports);
11
+ // src/prodia-image-model.ts
12
+ import {
13
+ combineHeaders,
14
+ lazySchema,
15
+ parseJSON,
16
+ parseProviderOptions,
17
+ postToApi,
18
+ resolve,
19
+ serializeModelOptions,
20
+ WORKFLOW_SERIALIZE,
21
+ WORKFLOW_DESERIALIZE,
22
+ zodSchema
23
+ } from "@ai-sdk/provider-utils";
24
+ import { z as z2 } from "zod/v4";
28
25
 
29
- // src/prodia-provider.ts
30
- var import_provider = require("@ai-sdk/provider");
31
- var import_provider_utils2 = require("@ai-sdk/provider-utils");
26
+ // src/prodia-api.ts
27
+ import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
28
+ import { z } from "zod/v4";
29
+ var prodiaJobResultSchema = z.object({
30
+ id: z.string(),
31
+ created_at: z.string().optional(),
32
+ updated_at: z.string().optional(),
33
+ expires_at: z.string().optional(),
34
+ state: z.object({
35
+ current: z.string()
36
+ }).optional(),
37
+ config: z.object({
38
+ seed: z.number().optional()
39
+ }).passthrough().optional(),
40
+ metrics: z.object({
41
+ elapsed: z.number().optional(),
42
+ ips: z.number().optional()
43
+ }).optional(),
44
+ price: z.object({
45
+ product: z.string(),
46
+ dollars: z.number()
47
+ }).nullish()
48
+ });
49
+ function buildProdiaProviderMetadata(jobResult) {
50
+ var _a, _b, _c, _d;
51
+ return {
52
+ jobId: jobResult.id,
53
+ ...((_a = jobResult.config) == null ? void 0 : _a.seed) != null && {
54
+ seed: jobResult.config.seed
55
+ },
56
+ ...((_b = jobResult.metrics) == null ? void 0 : _b.elapsed) != null && {
57
+ elapsed: jobResult.metrics.elapsed
58
+ },
59
+ ...((_c = jobResult.metrics) == null ? void 0 : _c.ips) != null && {
60
+ iterationsPerSecond: jobResult.metrics.ips
61
+ },
62
+ ...jobResult.created_at != null && {
63
+ createdAt: jobResult.created_at
64
+ },
65
+ ...jobResult.updated_at != null && {
66
+ updatedAt: jobResult.updated_at
67
+ },
68
+ ...((_d = jobResult.price) == null ? void 0 : _d.dollars) != null && {
69
+ dollars: jobResult.price.dollars
70
+ }
71
+ };
72
+ }
73
+ function parseMultipart(data, boundary) {
74
+ const parts = [];
75
+ const boundaryBytes = new TextEncoder().encode(`--${boundary}`);
76
+ const endBoundaryBytes = new TextEncoder().encode(`--${boundary}--`);
77
+ const positions = [];
78
+ for (let i = 0; i <= data.length - boundaryBytes.length; i++) {
79
+ let match = true;
80
+ for (let j = 0; j < boundaryBytes.length; j++) {
81
+ if (data[i + j] !== boundaryBytes[j]) {
82
+ match = false;
83
+ break;
84
+ }
85
+ }
86
+ if (match) {
87
+ positions.push(i);
88
+ }
89
+ }
90
+ for (let i = 0; i < positions.length - 1; i++) {
91
+ const start = positions[i] + boundaryBytes.length;
92
+ const end = positions[i + 1];
93
+ let isEndBoundary = true;
94
+ for (let j = 0; j < endBoundaryBytes.length && isEndBoundary; j++) {
95
+ if (data[positions[i] + j] !== endBoundaryBytes[j]) {
96
+ isEndBoundary = false;
97
+ }
98
+ }
99
+ if (isEndBoundary && positions[i] + endBoundaryBytes.length <= data.length) {
100
+ continue;
101
+ }
102
+ let partStart = start;
103
+ if (data[partStart] === 13 && data[partStart + 1] === 10) {
104
+ partStart += 2;
105
+ } else if (data[partStart] === 10) {
106
+ partStart += 1;
107
+ }
108
+ let partEnd = end;
109
+ if (data[partEnd - 2] === 13 && data[partEnd - 1] === 10) {
110
+ partEnd -= 2;
111
+ } else if (data[partEnd - 1] === 10) {
112
+ partEnd -= 1;
113
+ }
114
+ const partData = data.slice(partStart, partEnd);
115
+ let headerEnd = -1;
116
+ for (let j = 0; j < partData.length - 3; j++) {
117
+ if (partData[j] === 13 && partData[j + 1] === 10 && partData[j + 2] === 13 && partData[j + 3] === 10) {
118
+ headerEnd = j;
119
+ break;
120
+ }
121
+ if (partData[j] === 10 && partData[j + 1] === 10) {
122
+ headerEnd = j;
123
+ break;
124
+ }
125
+ }
126
+ if (headerEnd === -1) {
127
+ continue;
128
+ }
129
+ const headerBytes = partData.slice(0, headerEnd);
130
+ const headerStr = new TextDecoder().decode(headerBytes);
131
+ const headers = {};
132
+ for (const line of headerStr.split(/\r?\n/)) {
133
+ const colonIdx = line.indexOf(":");
134
+ if (colonIdx > 0) {
135
+ const key = line.slice(0, colonIdx).trim().toLowerCase();
136
+ const value = line.slice(colonIdx + 1).trim();
137
+ headers[key] = value;
138
+ }
139
+ }
140
+ let bodyStart = headerEnd + 2;
141
+ if (partData[headerEnd] === 13) {
142
+ bodyStart = headerEnd + 4;
143
+ }
144
+ const body = partData.slice(bodyStart);
145
+ parts.push({ headers, body });
146
+ }
147
+ return parts;
148
+ }
149
+ var prodiaErrorSchema = z.object({
150
+ message: z.string().optional(),
151
+ detail: z.unknown().optional(),
152
+ error: z.string().optional()
153
+ });
154
+ var prodiaFailedResponseHandler = createJsonErrorResponseHandler({
155
+ errorSchema: prodiaErrorSchema,
156
+ errorToMessage: (error) => {
157
+ var _a;
158
+ const parsed = prodiaErrorSchema.safeParse(error);
159
+ if (!parsed.success) return "Unknown Prodia error";
160
+ const { message, detail, error: errorField } = parsed.data;
161
+ if (typeof detail === "string") return detail;
162
+ if (detail != null) {
163
+ try {
164
+ return JSON.stringify(detail);
165
+ } catch (e) {
166
+ }
167
+ }
168
+ return (_a = errorField != null ? errorField : message) != null ? _a : "Unknown Prodia error";
169
+ }
170
+ });
32
171
 
33
172
  // src/prodia-image-model.ts
34
- var import_provider_utils = require("@ai-sdk/provider-utils");
35
- var import_v4 = require("zod/v4");
36
- var ProdiaImageModel = class {
173
+ var ProdiaImageModel = class _ProdiaImageModel {
37
174
  constructor(modelId, config) {
38
175
  this.modelId = modelId;
39
176
  this.config = config;
@@ -43,6 +180,15 @@ var ProdiaImageModel = class {
43
180
  get provider() {
44
181
  return this.config.provider;
45
182
  }
183
+ static [WORKFLOW_SERIALIZE](model) {
184
+ return serializeModelOptions({
185
+ modelId: model.modelId,
186
+ config: model.config
187
+ });
188
+ }
189
+ static [WORKFLOW_DESERIALIZE](options) {
190
+ return new _ProdiaImageModel(options.modelId, options.config);
191
+ }
46
192
  async getArgs({
47
193
  prompt,
48
194
  size,
@@ -50,7 +196,7 @@ var ProdiaImageModel = class {
50
196
  providerOptions
51
197
  }) {
52
198
  const warnings = [];
53
- const prodiaOptions = await (0, import_provider_utils.parseProviderOptions)({
199
+ const prodiaOptions = await parseProviderOptions({
54
200
  provider: "prodia",
55
201
  providerOptions,
56
202
  schema: prodiaImageModelOptionsSchema
@@ -106,14 +252,14 @@ var ProdiaImageModel = class {
106
252
  return { body, warnings };
107
253
  }
108
254
  async doGenerate(options) {
109
- var _a, _b, _c, _d, _e, _f, _g;
255
+ var _a, _b, _c;
110
256
  const { body, warnings } = await this.getArgs(options);
111
257
  const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
112
- const combinedHeaders = (0, import_provider_utils.combineHeaders)(
113
- await (0, import_provider_utils.resolve)(this.config.headers),
258
+ const combinedHeaders = combineHeaders(
259
+ this.config.headers ? await resolve(this.config.headers) : void 0,
114
260
  options.headers
115
261
  );
116
- const { value: multipartResult, responseHeaders } = await (0, import_provider_utils.postToApi)({
262
+ const { value: multipartResult, responseHeaders } = await postToApi({
117
263
  url: `${this.config.baseURL}/job?price=true`,
118
264
  headers: {
119
265
  ...combinedHeaders,
@@ -135,29 +281,7 @@ var ProdiaImageModel = class {
135
281
  warnings,
136
282
  providerMetadata: {
137
283
  prodia: {
138
- images: [
139
- {
140
- jobId: jobResult.id,
141
- ...((_d = jobResult.config) == null ? void 0 : _d.seed) != null && {
142
- seed: jobResult.config.seed
143
- },
144
- ...((_e = jobResult.metrics) == null ? void 0 : _e.elapsed) != null && {
145
- elapsed: jobResult.metrics.elapsed
146
- },
147
- ...((_f = jobResult.metrics) == null ? void 0 : _f.ips) != null && {
148
- iterationsPerSecond: jobResult.metrics.ips
149
- },
150
- ...jobResult.created_at != null && {
151
- createdAt: jobResult.created_at
152
- },
153
- ...jobResult.updated_at != null && {
154
- updatedAt: jobResult.updated_at
155
- },
156
- ...((_g = jobResult.price) == null ? void 0 : _g.dollars) != null && {
157
- dollars: jobResult.price.dollars
158
- }
159
- }
160
- ]
284
+ images: [buildProdiaProviderMetadata(jobResult)]
161
285
  }
162
286
  },
163
287
  response: {
@@ -187,56 +311,36 @@ var stylePresets = [
187
311
  "texture",
188
312
  "craft-clay"
189
313
  ];
190
- var prodiaImageModelOptionsSchema = (0, import_provider_utils.lazySchema)(
191
- () => (0, import_provider_utils.zodSchema)(
192
- import_v4.z.object({
314
+ var prodiaImageModelOptionsSchema = lazySchema(
315
+ () => zodSchema(
316
+ z2.object({
193
317
  /**
194
318
  * Amount of computational iterations to run. More is typically higher quality.
195
319
  */
196
- steps: import_v4.z.number().int().min(1).max(4).optional(),
320
+ steps: z2.number().int().min(1).max(4).optional(),
197
321
  /**
198
322
  * Width of the output image in pixels.
199
323
  */
200
- width: import_v4.z.number().int().min(256).max(1920).optional(),
324
+ width: z2.number().int().min(256).max(1920).optional(),
201
325
  /**
202
326
  * Height of the output image in pixels.
203
327
  */
204
- height: import_v4.z.number().int().min(256).max(1920).optional(),
328
+ height: z2.number().int().min(256).max(1920).optional(),
205
329
  /**
206
330
  * Apply a visual theme to your output image.
207
331
  */
208
- stylePreset: import_v4.z.enum(stylePresets).optional(),
332
+ stylePreset: z2.enum(stylePresets).optional(),
209
333
  /**
210
334
  * Augment the output with a LoRa model.
211
335
  */
212
- loras: import_v4.z.array(import_v4.z.string()).max(3).optional(),
336
+ loras: z2.array(z2.string()).max(3).optional(),
213
337
  /**
214
338
  * When using JPEG output, return a progressive JPEG.
215
339
  */
216
- progressive: import_v4.z.boolean().optional()
340
+ progressive: z2.boolean().optional()
217
341
  })
218
342
  )
219
343
  );
220
- var prodiaJobResultSchema = import_v4.z.object({
221
- id: import_v4.z.string(),
222
- created_at: import_v4.z.string().optional(),
223
- updated_at: import_v4.z.string().optional(),
224
- expires_at: import_v4.z.string().optional(),
225
- state: import_v4.z.object({
226
- current: import_v4.z.string()
227
- }).optional(),
228
- config: import_v4.z.object({
229
- seed: import_v4.z.number().optional()
230
- }).passthrough().optional(),
231
- metrics: import_v4.z.object({
232
- elapsed: import_v4.z.number().optional(),
233
- ips: import_v4.z.number().optional()
234
- }).optional(),
235
- price: import_v4.z.object({
236
- product: import_v4.z.string(),
237
- dollars: import_v4.z.number()
238
- }).nullish()
239
- });
240
344
  function createMultipartResponseHandler() {
241
345
  return async ({
242
346
  response
@@ -264,7 +368,10 @@ function createMultipartResponseHandler() {
264
368
  const partContentType = (_c = part.headers["content-type"]) != null ? _c : "";
265
369
  if (contentDisposition.includes('name="job"')) {
266
370
  const jsonStr = new TextDecoder().decode(part.body);
267
- jobResult = prodiaJobResultSchema.parse(JSON.parse(jsonStr));
371
+ jobResult = await parseJSON({
372
+ text: jsonStr,
373
+ schema: zodSchema(prodiaJobResultSchema)
374
+ });
268
375
  } else if (contentDisposition.includes('name="output"')) {
269
376
  imageBytes = part.body;
270
377
  } else if (partContentType.startsWith("image/")) {
@@ -283,116 +390,573 @@ function createMultipartResponseHandler() {
283
390
  };
284
391
  };
285
392
  }
286
- function parseMultipart(data, boundary) {
287
- const parts = [];
288
- const boundaryBytes = new TextEncoder().encode(`--${boundary}`);
289
- const endBoundaryBytes = new TextEncoder().encode(`--${boundary}--`);
290
- const positions = [];
291
- for (let i = 0; i <= data.length - boundaryBytes.length; i++) {
292
- let match = true;
293
- for (let j = 0; j < boundaryBytes.length; j++) {
294
- if (data[i + j] !== boundaryBytes[j]) {
295
- match = false;
296
- break;
297
- }
393
+
394
+ // src/prodia-language-model.ts
395
+ import {
396
+ UnsupportedFunctionalityError
397
+ } from "@ai-sdk/provider";
398
+ import {
399
+ combineHeaders as combineHeaders2,
400
+ isCustomReasoning,
401
+ isProviderReference,
402
+ convertBase64ToUint8Array,
403
+ generateId,
404
+ lazySchema as lazySchema2,
405
+ parseJSON as parseJSON2,
406
+ parseProviderOptions as parseProviderOptions2,
407
+ postFormDataToApi,
408
+ resolve as resolve2,
409
+ serializeModelOptions as serializeModelOptions2,
410
+ WORKFLOW_SERIALIZE as WORKFLOW_SERIALIZE2,
411
+ WORKFLOW_DESERIALIZE as WORKFLOW_DESERIALIZE2,
412
+ zodSchema as zodSchema2
413
+ } from "@ai-sdk/provider-utils";
414
+ import { z as z3 } from "zod/v4";
415
+ var ProdiaLanguageModel = class _ProdiaLanguageModel {
416
+ constructor(modelId, config) {
417
+ this.modelId = modelId;
418
+ this.config = config;
419
+ this.specificationVersion = "v4";
420
+ this.supportedUrls = {};
421
+ }
422
+ get provider() {
423
+ return this.config.provider;
424
+ }
425
+ static [WORKFLOW_SERIALIZE2](model) {
426
+ return serializeModelOptions2({
427
+ modelId: model.modelId,
428
+ config: model.config
429
+ });
430
+ }
431
+ static [WORKFLOW_DESERIALIZE2](options) {
432
+ return new _ProdiaLanguageModel(options.modelId, options.config);
433
+ }
434
+ async doGenerate(options) {
435
+ var _a, _b, _c, _d;
436
+ const warnings = [];
437
+ if (options.temperature !== void 0) {
438
+ warnings.push({ type: "unsupported", feature: "temperature" });
298
439
  }
299
- if (match) {
300
- positions.push(i);
440
+ if (options.topP !== void 0) {
441
+ warnings.push({ type: "unsupported", feature: "topP" });
301
442
  }
302
- }
303
- for (let i = 0; i < positions.length - 1; i++) {
304
- const start = positions[i] + boundaryBytes.length;
305
- const end = positions[i + 1];
306
- let isEndBoundary = true;
307
- for (let j = 0; j < endBoundaryBytes.length && isEndBoundary; j++) {
308
- if (data[positions[i] + j] !== endBoundaryBytes[j]) {
309
- isEndBoundary = false;
310
- }
443
+ if (options.topK !== void 0) {
444
+ warnings.push({ type: "unsupported", feature: "topK" });
311
445
  }
312
- if (isEndBoundary && positions[i] + endBoundaryBytes.length <= data.length) {
313
- continue;
446
+ if (options.maxOutputTokens !== void 0) {
447
+ warnings.push({ type: "unsupported", feature: "maxOutputTokens" });
314
448
  }
315
- let partStart = start;
316
- if (data[partStart] === 13 && data[partStart + 1] === 10) {
317
- partStart += 2;
318
- } else if (data[partStart] === 10) {
319
- partStart += 1;
449
+ if (options.stopSequences !== void 0) {
450
+ warnings.push({ type: "unsupported", feature: "stopSequences" });
320
451
  }
321
- let partEnd = end;
322
- if (data[partEnd - 2] === 13 && data[partEnd - 1] === 10) {
323
- partEnd -= 2;
324
- } else if (data[partEnd - 1] === 10) {
325
- partEnd -= 1;
452
+ if (options.presencePenalty !== void 0) {
453
+ warnings.push({ type: "unsupported", feature: "presencePenalty" });
326
454
  }
327
- const partData = data.slice(partStart, partEnd);
328
- let headerEnd = -1;
329
- for (let j = 0; j < partData.length - 3; j++) {
330
- if (partData[j] === 13 && partData[j + 1] === 10 && partData[j + 2] === 13 && partData[j + 3] === 10) {
331
- headerEnd = j;
455
+ if (options.frequencyPenalty !== void 0) {
456
+ warnings.push({ type: "unsupported", feature: "frequencyPenalty" });
457
+ }
458
+ if (options.tools !== void 0 && options.tools.length > 0) {
459
+ warnings.push({ type: "unsupported", feature: "tools" });
460
+ }
461
+ if (options.toolChoice !== void 0) {
462
+ warnings.push({ type: "unsupported", feature: "toolChoice" });
463
+ }
464
+ if (options.responseFormat !== void 0 && options.responseFormat.type !== "text") {
465
+ warnings.push({ type: "unsupported", feature: "responseFormat" });
466
+ }
467
+ if (isCustomReasoning(options.reasoning)) {
468
+ warnings.push({
469
+ type: "unsupported",
470
+ feature: "reasoning",
471
+ details: "This provider does not support reasoning configuration."
472
+ });
473
+ }
474
+ const prodiaOptions = await parseProviderOptions2({
475
+ provider: "prodia",
476
+ providerOptions: options.providerOptions,
477
+ schema: prodiaLanguageModelOptionsSchema
478
+ });
479
+ let prompt = "";
480
+ let systemMessage = "";
481
+ for (const message of options.prompt) {
482
+ if (message.role === "system") {
483
+ systemMessage = message.content;
484
+ }
485
+ }
486
+ for (let i = options.prompt.length - 1; i >= 0; i--) {
487
+ const message = options.prompt[i];
488
+ if (message.role === "user") {
489
+ for (const part of message.content) {
490
+ if (part.type === "text") {
491
+ prompt += (prompt ? "\n" : "") + part.text;
492
+ }
493
+ }
332
494
  break;
333
495
  }
334
- if (partData[j] === 10 && partData[j + 1] === 10) {
335
- headerEnd = j;
496
+ }
497
+ if (systemMessage) {
498
+ prompt = systemMessage + "\n" + prompt;
499
+ }
500
+ let imageBytes;
501
+ let imageMediaType = "image/png";
502
+ for (let i = options.prompt.length - 1; i >= 0; i--) {
503
+ const message = options.prompt[i];
504
+ if (message.role === "user") {
505
+ for (const part of message.content) {
506
+ if (part.type === "file" && part.mediaType.startsWith("image/")) {
507
+ if (isProviderReference(part.data)) {
508
+ throw new UnsupportedFunctionalityError({
509
+ functionality: "file parts with provider references"
510
+ });
511
+ }
512
+ if (part.data instanceof Uint8Array) {
513
+ imageBytes = part.data;
514
+ } else if (typeof part.data === "string") {
515
+ imageBytes = convertBase64ToUint8Array(part.data);
516
+ } else if (part.data instanceof URL) {
517
+ const fetchFn = (_a = this.config.fetch) != null ? _a : globalThis.fetch;
518
+ const response = await fetchFn(part.data.toString());
519
+ const arrayBuffer = await response.arrayBuffer();
520
+ imageBytes = new Uint8Array(arrayBuffer);
521
+ }
522
+ imageMediaType = part.mediaType;
523
+ break;
524
+ }
525
+ }
336
526
  break;
337
527
  }
338
528
  }
339
- if (headerEnd === -1) {
340
- continue;
529
+ const jobConfig = {
530
+ prompt,
531
+ include_messages: true
532
+ };
533
+ if ((prodiaOptions == null ? void 0 : prodiaOptions.aspectRatio) !== void 0) {
534
+ jobConfig.aspect_ratio = prodiaOptions.aspectRatio;
341
535
  }
342
- const headerBytes = partData.slice(0, headerEnd);
343
- const headerStr = new TextDecoder().decode(headerBytes);
344
- const headers = {};
345
- for (const line of headerStr.split(/\r?\n/)) {
346
- const colonIdx = line.indexOf(":");
347
- if (colonIdx > 0) {
348
- const key = line.slice(0, colonIdx).trim().toLowerCase();
349
- const value = line.slice(colonIdx + 1).trim();
350
- headers[key] = value;
536
+ const body = {
537
+ type: this.modelId,
538
+ config: jobConfig
539
+ };
540
+ const currentDate = (_d = (_c = (_b = this.config._internal) == null ? void 0 : _b.currentDate) == null ? void 0 : _c.call(_b)) != null ? _d : /* @__PURE__ */ new Date();
541
+ const combinedHeaders = combineHeaders2(
542
+ this.config.headers ? await resolve2(this.config.headers) : void 0,
543
+ options.headers
544
+ );
545
+ const formData = new FormData();
546
+ formData.append(
547
+ "job",
548
+ new Blob([JSON.stringify(body)], { type: "application/json" }),
549
+ "job.json"
550
+ );
551
+ if (imageBytes) {
552
+ const ext = imageMediaType === "image/png" ? ".png" : imageMediaType === "image/jpeg" ? ".jpg" : imageMediaType === "image/webp" ? ".webp" : "";
553
+ formData.append(
554
+ "input",
555
+ new Blob([imageBytes], { type: imageMediaType }),
556
+ "input" + ext
557
+ );
558
+ }
559
+ const { value: multipartResult, responseHeaders } = await postFormDataToApi(
560
+ {
561
+ url: `${this.config.baseURL}/job?price=true`,
562
+ headers: {
563
+ ...combinedHeaders,
564
+ Accept: "multipart/form-data"
565
+ },
566
+ formData,
567
+ failedResponseHandler: prodiaFailedResponseHandler,
568
+ successfulResponseHandler: createLanguageMultipartResponseHandler(),
569
+ abortSignal: options.abortSignal,
570
+ fetch: this.config.fetch
351
571
  }
572
+ );
573
+ const { jobResult, textContent, fileContent } = multipartResult;
574
+ const content = [];
575
+ if (textContent !== void 0) {
576
+ content.push({ type: "text", text: textContent });
352
577
  }
353
- let bodyStart = headerEnd + 2;
354
- if (partData[headerEnd] === 13) {
355
- bodyStart = headerEnd + 4;
578
+ for (const file of fileContent) {
579
+ content.push({
580
+ type: "file",
581
+ mediaType: file.mediaType,
582
+ data: file.data
583
+ });
356
584
  }
357
- const body = partData.slice(bodyStart);
358
- parts.push({ headers, body });
585
+ return {
586
+ content,
587
+ finishReason: { unified: "stop", raw: void 0 },
588
+ usage: {
589
+ inputTokens: {
590
+ total: void 0,
591
+ noCache: void 0,
592
+ cacheRead: void 0,
593
+ cacheWrite: void 0
594
+ },
595
+ outputTokens: {
596
+ total: void 0,
597
+ text: void 0,
598
+ reasoning: void 0
599
+ }
600
+ },
601
+ warnings,
602
+ providerMetadata: {
603
+ prodia: buildProdiaProviderMetadata(jobResult)
604
+ },
605
+ response: {
606
+ modelId: this.modelId,
607
+ timestamp: currentDate,
608
+ headers: responseHeaders
609
+ }
610
+ };
359
611
  }
360
- return parts;
361
- }
362
- var prodiaErrorSchema = import_v4.z.object({
363
- message: import_v4.z.string().optional(),
364
- detail: import_v4.z.unknown().optional(),
365
- error: import_v4.z.string().optional()
366
- });
367
- var prodiaFailedResponseHandler = (0, import_provider_utils.createJsonErrorResponseHandler)({
368
- errorSchema: prodiaErrorSchema,
369
- errorToMessage: (error) => {
612
+ async doStream(options) {
370
613
  var _a;
371
- const parsed = prodiaErrorSchema.safeParse(error);
372
- if (!parsed.success) return "Unknown Prodia error";
373
- const { message, detail, error: errorField } = parsed.data;
374
- if (typeof detail === "string") return detail;
375
- if (detail != null) {
376
- try {
377
- return JSON.stringify(detail);
378
- } catch (e) {
614
+ const result = await this.doGenerate(options);
615
+ const stream = new ReadableStream({
616
+ start(controller) {
617
+ var _a2, _b;
618
+ controller.enqueue({
619
+ type: "stream-start",
620
+ warnings: result.warnings
621
+ });
622
+ controller.enqueue({
623
+ type: "response-metadata",
624
+ modelId: (_a2 = result.response) == null ? void 0 : _a2.modelId,
625
+ timestamp: (_b = result.response) == null ? void 0 : _b.timestamp
626
+ });
627
+ for (const part of result.content) {
628
+ if (part.type === "text") {
629
+ const id = generateId();
630
+ controller.enqueue({ type: "text-start", id });
631
+ controller.enqueue({
632
+ type: "text-delta",
633
+ id,
634
+ delta: part.text
635
+ });
636
+ controller.enqueue({ type: "text-end", id });
637
+ } else if (part.type === "file") {
638
+ controller.enqueue({
639
+ type: "file",
640
+ mediaType: part.mediaType,
641
+ data: part.data
642
+ });
643
+ }
644
+ }
645
+ controller.enqueue({
646
+ type: "finish",
647
+ usage: result.usage,
648
+ finishReason: result.finishReason,
649
+ providerMetadata: result.providerMetadata
650
+ });
651
+ controller.close();
379
652
  }
653
+ });
654
+ return {
655
+ stream,
656
+ response: {
657
+ headers: (_a = result.response) == null ? void 0 : _a.headers
658
+ }
659
+ };
660
+ }
661
+ };
662
+ var prodiaLanguageModelOptionsSchema = lazySchema2(
663
+ () => zodSchema2(
664
+ z3.object({
665
+ /**
666
+ * Aspect ratio for the output image.
667
+ */
668
+ aspectRatio: z3.enum([
669
+ "1:1",
670
+ "2:3",
671
+ "3:2",
672
+ "4:5",
673
+ "5:4",
674
+ "4:7",
675
+ "7:4",
676
+ "9:16",
677
+ "16:9",
678
+ "9:21",
679
+ "21:9"
680
+ ]).optional()
681
+ })
682
+ )
683
+ );
684
+ function createLanguageMultipartResponseHandler() {
685
+ return async ({
686
+ response
687
+ }) => {
688
+ var _a, _b, _c;
689
+ const contentType = (_a = response.headers.get("content-type")) != null ? _a : "";
690
+ const responseHeaders = {};
691
+ response.headers.forEach((value, key) => {
692
+ responseHeaders[key] = value;
693
+ });
694
+ const boundaryMatch = contentType.match(/boundary=([^\s;]+)/);
695
+ if (!boundaryMatch) {
696
+ throw new Error(
697
+ `Prodia response missing multipart boundary in content-type: ${contentType}`
698
+ );
380
699
  }
381
- return (_a = errorField != null ? errorField : message) != null ? _a : "Unknown Prodia error";
700
+ const boundary = boundaryMatch[1];
701
+ const arrayBuffer = await response.arrayBuffer();
702
+ const bytes = new Uint8Array(arrayBuffer);
703
+ const parts = parseMultipart(bytes, boundary);
704
+ let jobResult;
705
+ let textContent;
706
+ const fileContent = [];
707
+ for (const part of parts) {
708
+ const contentDisposition = (_b = part.headers["content-disposition"]) != null ? _b : "";
709
+ const partContentType = (_c = part.headers["content-type"]) != null ? _c : "";
710
+ if (contentDisposition.includes('name="job"')) {
711
+ const jsonStr = new TextDecoder().decode(part.body);
712
+ jobResult = await parseJSON2({
713
+ text: jsonStr,
714
+ schema: zodSchema2(prodiaJobResultSchema)
715
+ });
716
+ } else if (contentDisposition.includes('name="output"')) {
717
+ if (partContentType.startsWith("text/") || contentDisposition.includes(".txt")) {
718
+ textContent = new TextDecoder().decode(part.body);
719
+ } else if (partContentType.startsWith("image/")) {
720
+ fileContent.push({
721
+ mediaType: partContentType,
722
+ data: part.body
723
+ });
724
+ }
725
+ }
726
+ }
727
+ if (!jobResult) {
728
+ throw new Error("Prodia multipart response missing job part");
729
+ }
730
+ return {
731
+ value: { jobResult, textContent, fileContent },
732
+ responseHeaders
733
+ };
734
+ };
735
+ }
736
+
737
+ // src/prodia-video-model.ts
738
+ import {
739
+ combineHeaders as combineHeaders3,
740
+ convertBase64ToUint8Array as convertBase64ToUint8Array2,
741
+ lazySchema as lazySchema3,
742
+ parseJSON as parseJSON3,
743
+ parseProviderOptions as parseProviderOptions3,
744
+ postFormDataToApi as postFormDataToApi2,
745
+ postToApi as postToApi2,
746
+ resolve as resolve3,
747
+ zodSchema as zodSchema3
748
+ } from "@ai-sdk/provider-utils";
749
+ import { z as z4 } from "zod/v4";
750
+ var ProdiaVideoModel = class {
751
+ constructor(modelId, config) {
752
+ this.modelId = modelId;
753
+ this.config = config;
754
+ this.specificationVersion = "v4";
755
+ this.maxVideosPerCall = 1;
382
756
  }
383
- });
757
+ get provider() {
758
+ return this.config.provider;
759
+ }
760
+ async doGenerate(options) {
761
+ var _a, _b, _c;
762
+ const warnings = [];
763
+ const prodiaOptions = await parseProviderOptions3({
764
+ provider: "prodia",
765
+ providerOptions: options.providerOptions,
766
+ schema: prodiaVideoModelOptionsSchema
767
+ });
768
+ const jobConfig = {};
769
+ if (options.prompt !== void 0) {
770
+ jobConfig.prompt = options.prompt;
771
+ }
772
+ if (options.seed !== void 0) {
773
+ jobConfig.seed = options.seed;
774
+ }
775
+ if ((prodiaOptions == null ? void 0 : prodiaOptions.resolution) !== void 0) {
776
+ jobConfig.resolution = prodiaOptions.resolution;
777
+ }
778
+ const body = {
779
+ type: this.modelId,
780
+ config: jobConfig
781
+ };
782
+ const currentDate = (_c = (_b = (_a = this.config._internal) == null ? void 0 : _a.currentDate) == null ? void 0 : _b.call(_a)) != null ? _c : /* @__PURE__ */ new Date();
783
+ const combinedHeaders = combineHeaders3(
784
+ await resolve3(this.config.headers),
785
+ options.headers
786
+ );
787
+ let multipartResult;
788
+ let responseHeaders;
789
+ if (options.image) {
790
+ const imageData = await resolveVideoFileData(
791
+ options.image,
792
+ this.config.fetch
793
+ );
794
+ const formData = new FormData();
795
+ formData.append(
796
+ "job",
797
+ new Blob([JSON.stringify(body)], { type: "application/json" }),
798
+ "job.json"
799
+ );
800
+ formData.append(
801
+ "input",
802
+ new Blob([imageData.bytes], { type: imageData.mediaType }),
803
+ "input" + getExtension(imageData.mediaType)
804
+ );
805
+ const result = await postFormDataToApi2({
806
+ url: `${this.config.baseURL}/job?price=true`,
807
+ headers: {
808
+ ...combinedHeaders,
809
+ Accept: "multipart/form-data; video/mp4"
810
+ },
811
+ formData,
812
+ failedResponseHandler: prodiaFailedResponseHandler,
813
+ successfulResponseHandler: createVideoMultipartResponseHandler(),
814
+ abortSignal: options.abortSignal,
815
+ fetch: this.config.fetch
816
+ });
817
+ multipartResult = result.value;
818
+ responseHeaders = result.responseHeaders;
819
+ } else {
820
+ const result = await postToApi2({
821
+ url: `${this.config.baseURL}/job?price=true`,
822
+ headers: {
823
+ ...combinedHeaders,
824
+ Accept: "multipart/form-data; video/mp4",
825
+ "Content-Type": "application/json"
826
+ },
827
+ body: {
828
+ content: JSON.stringify(body),
829
+ values: body
830
+ },
831
+ failedResponseHandler: prodiaFailedResponseHandler,
832
+ successfulResponseHandler: createVideoMultipartResponseHandler(),
833
+ abortSignal: options.abortSignal,
834
+ fetch: this.config.fetch
835
+ });
836
+ multipartResult = result.value;
837
+ responseHeaders = result.responseHeaders;
838
+ }
839
+ const { jobResult, videoBytes, videoMediaType } = multipartResult;
840
+ return {
841
+ videos: [
842
+ {
843
+ type: "binary",
844
+ data: videoBytes,
845
+ mediaType: videoMediaType
846
+ }
847
+ ],
848
+ warnings,
849
+ providerMetadata: {
850
+ prodia: {
851
+ videos: [buildProdiaProviderMetadata(jobResult)]
852
+ }
853
+ },
854
+ response: {
855
+ modelId: this.modelId,
856
+ timestamp: currentDate,
857
+ headers: responseHeaders
858
+ }
859
+ };
860
+ }
861
+ };
862
+ var prodiaVideoModelOptionsSchema = lazySchema3(
863
+ () => zodSchema3(
864
+ z4.object({
865
+ /**
866
+ * Video resolution (e.g. "480p", "720p").
867
+ */
868
+ resolution: z4.string().optional()
869
+ })
870
+ )
871
+ );
872
+ function createVideoMultipartResponseHandler() {
873
+ return async ({
874
+ response
875
+ }) => {
876
+ var _a, _b, _c;
877
+ const contentType = (_a = response.headers.get("content-type")) != null ? _a : "";
878
+ const responseHeaders = {};
879
+ response.headers.forEach((value, key) => {
880
+ responseHeaders[key] = value;
881
+ });
882
+ const boundaryMatch = contentType.match(/boundary=([^\s;]+)/);
883
+ if (!boundaryMatch) {
884
+ throw new Error(
885
+ `Prodia response missing multipart boundary in content-type: ${contentType}`
886
+ );
887
+ }
888
+ const boundary = boundaryMatch[1];
889
+ const arrayBuffer = await response.arrayBuffer();
890
+ const bytes = new Uint8Array(arrayBuffer);
891
+ const parts = parseMultipart(bytes, boundary);
892
+ let jobResult;
893
+ let videoBytes;
894
+ let videoMediaType = "video/mp4";
895
+ for (const part of parts) {
896
+ const contentDisposition = (_b = part.headers["content-disposition"]) != null ? _b : "";
897
+ const partContentType = (_c = part.headers["content-type"]) != null ? _c : "";
898
+ if (contentDisposition.includes('name="job"')) {
899
+ const jsonStr = new TextDecoder().decode(part.body);
900
+ jobResult = await parseJSON3({
901
+ text: jsonStr,
902
+ schema: zodSchema3(prodiaJobResultSchema)
903
+ });
904
+ } else if (contentDisposition.includes('name="output"')) {
905
+ videoBytes = part.body;
906
+ if (partContentType.startsWith("video/")) {
907
+ videoMediaType = partContentType;
908
+ }
909
+ } else if (partContentType.startsWith("video/")) {
910
+ videoBytes = part.body;
911
+ videoMediaType = partContentType;
912
+ }
913
+ }
914
+ if (!jobResult) {
915
+ throw new Error("Prodia multipart response missing job part");
916
+ }
917
+ if (!videoBytes) {
918
+ throw new Error("Prodia multipart response missing output video");
919
+ }
920
+ return {
921
+ value: { jobResult, videoBytes, videoMediaType },
922
+ responseHeaders
923
+ };
924
+ };
925
+ }
926
+ async function resolveVideoFileData(file, fetchFunction) {
927
+ var _a;
928
+ if (file.type === "file") {
929
+ const data = typeof file.data === "string" ? convertBase64ToUint8Array2(file.data) : file.data;
930
+ return { bytes: data, mediaType: file.mediaType };
931
+ }
932
+ const response = await (fetchFunction != null ? fetchFunction : globalThis.fetch)(file.url);
933
+ const arrayBuffer = await response.arrayBuffer();
934
+ const mediaType = (_a = response.headers.get("content-type")) != null ? _a : "application/octet-stream";
935
+ return { bytes: new Uint8Array(arrayBuffer), mediaType };
936
+ }
937
+ function getExtension(mediaType) {
938
+ var _a;
939
+ const map = {
940
+ "image/png": ".png",
941
+ "image/jpeg": ".jpg",
942
+ "image/webp": ".webp",
943
+ "video/mp4": ".mp4",
944
+ "video/webm": ".webm"
945
+ };
946
+ return (_a = map[mediaType]) != null ? _a : "";
947
+ }
384
948
 
385
949
  // src/version.ts
386
- var VERSION = true ? "2.0.0-beta.3" : "0.0.0-test";
950
+ var VERSION = true ? "2.0.0-beta.30" : "0.0.0-test";
387
951
 
388
952
  // src/prodia-provider.ts
389
953
  var defaultBaseURL = "https://inference.prodia.com/v2";
390
954
  function createProdia(options = {}) {
391
955
  var _a;
392
- const baseURL = (0, import_provider_utils2.withoutTrailingSlash)((_a = options.baseURL) != null ? _a : defaultBaseURL);
393
- const getHeaders = () => (0, import_provider_utils2.withUserAgentSuffix)(
956
+ const baseURL = withoutTrailingSlash((_a = options.baseURL) != null ? _a : defaultBaseURL);
957
+ const getHeaders = () => withUserAgentSuffix(
394
958
  {
395
- Authorization: `Bearer ${(0, import_provider_utils2.loadApiKey)({
959
+ Authorization: `Bearer ${loadApiKey({
396
960
  apiKey: options.apiKey,
397
961
  environmentVariableName: "PRODIA_TOKEN",
398
962
  description: "Prodia"
@@ -407,32 +971,39 @@ function createProdia(options = {}) {
407
971
  headers: getHeaders,
408
972
  fetch: options.fetch
409
973
  });
974
+ const createLanguageModel = (modelId) => new ProdiaLanguageModel(modelId, {
975
+ provider: "prodia.language",
976
+ baseURL: baseURL != null ? baseURL : defaultBaseURL,
977
+ headers: getHeaders,
978
+ fetch: options.fetch
979
+ });
980
+ const createVideoModel = (modelId) => new ProdiaVideoModel(modelId, {
981
+ provider: "prodia.video",
982
+ baseURL: baseURL != null ? baseURL : defaultBaseURL,
983
+ headers: getHeaders,
984
+ fetch: options.fetch
985
+ });
410
986
  const embeddingModel = (modelId) => {
411
- throw new import_provider.NoSuchModelError({
987
+ throw new NoSuchModelError({
412
988
  modelId,
413
989
  modelType: "embeddingModel"
414
990
  });
415
991
  };
416
- const languageModel = (modelId) => {
417
- throw new import_provider.NoSuchModelError({
418
- modelId,
419
- modelType: "languageModel"
420
- });
421
- };
422
992
  return {
423
993
  specificationVersion: "v4",
994
+ languageModel: createLanguageModel,
424
995
  imageModel: createImageModel,
425
996
  image: createImageModel,
426
- languageModel,
997
+ videoModel: createVideoModel,
998
+ video: createVideoModel,
427
999
  embeddingModel,
428
1000
  textEmbeddingModel: embeddingModel
429
1001
  };
430
1002
  }
431
1003
  var prodia = createProdia();
432
- // Annotate the CommonJS export names for ESM import in node:
433
- 0 && (module.exports = {
1004
+ export {
434
1005
  VERSION,
435
1006
  createProdia,
436
1007
  prodia
437
- });
1008
+ };
438
1009
  //# sourceMappingURL=index.js.map