@ai-sdk/prodia 2.0.0-beta.0 → 2.0.0-beta.10

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