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