corent-sdk 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -4
- package/dist/index.cjs +288 -16
- package/dist/index.d.cts +262 -7
- package/dist/index.d.ts +262 -7
- package/dist/index.js +288 -16
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -3,6 +3,8 @@ var DEFAULT_BASE_URL = "https://api.corent.tech";
|
|
|
3
3
|
var MAX_RETRIES = 3;
|
|
4
4
|
var POLL_INTERVAL_MS = 3e3;
|
|
5
5
|
var DEFAULT_WAIT_TIMEOUT_MS = 9e5;
|
|
6
|
+
var MAX_BATCH_ITEMS = 50;
|
|
7
|
+
var MAX_IMAGES_PER_REQUEST = 10;
|
|
6
8
|
var CorentError = class extends Error {
|
|
7
9
|
constructor(message, statusCode) {
|
|
8
10
|
super(message);
|
|
@@ -30,7 +32,9 @@ var Corent = class {
|
|
|
30
32
|
images;
|
|
31
33
|
videos;
|
|
32
34
|
speech;
|
|
35
|
+
text;
|
|
33
36
|
jobs;
|
|
37
|
+
batches;
|
|
34
38
|
constructor(apiKey, options = {}) {
|
|
35
39
|
this.apiKey = apiKey;
|
|
36
40
|
this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
@@ -38,26 +42,63 @@ var Corent = class {
|
|
|
38
42
|
this.images = new Images(this);
|
|
39
43
|
this.videos = new Videos(this);
|
|
40
44
|
this.speech = new Speech(this);
|
|
45
|
+
this.text = new Text(this);
|
|
41
46
|
this.jobs = new Jobs(this);
|
|
47
|
+
this.batches = new Batches(this);
|
|
42
48
|
}
|
|
43
|
-
/** Prepaid balance in cents. */
|
|
49
|
+
/** Prepaid balance in cents. See `balance()` for what is actually spendable. */
|
|
44
50
|
async balanceCents() {
|
|
45
51
|
const r = await this.request("GET", "/v1/account/balance");
|
|
46
52
|
return r.balance_cents;
|
|
47
53
|
}
|
|
54
|
+
/** The full picture: the total, what running generations have reserved, and
|
|
55
|
+
* what a new request can actually spend. availableCents is the number a 402
|
|
56
|
+
* is decided against — check that one before an expensive batch. */
|
|
57
|
+
async balance() {
|
|
58
|
+
const r = await this.request("GET", "/v1/account/balance");
|
|
59
|
+
return {
|
|
60
|
+
balanceCents: r.balance_cents,
|
|
61
|
+
heldCents: r.held_cents ?? 0,
|
|
62
|
+
availableCents: r.available_cents ?? r.balance_cents
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** The voices `speech.generate` will accept as voiceId. This exists
|
|
66
|
+
* because the API requires a voice id and, until 2026-08-30, published no
|
|
67
|
+
* list of legal values. */
|
|
68
|
+
async voices() {
|
|
69
|
+
const r = await this.request("GET", "/v1/voices");
|
|
70
|
+
return r.voices ?? [];
|
|
71
|
+
}
|
|
72
|
+
/** What this account has spent, by lane and over time. */
|
|
73
|
+
async usage() {
|
|
74
|
+
return this.request("GET", "/v1/account/usage");
|
|
75
|
+
}
|
|
76
|
+
/** Live operational status of the generation tiers. Public. */
|
|
77
|
+
async status() {
|
|
78
|
+
return this.request("GET", "/v1/status");
|
|
79
|
+
}
|
|
48
80
|
/** The live tier catalog with honest min–max price ranges. Public. */
|
|
49
81
|
async tiers() {
|
|
50
82
|
const r = await this.request("GET", "/v1/tiers");
|
|
51
83
|
return r.tiers;
|
|
52
84
|
}
|
|
85
|
+
/** The direct-access menu: every model you can pin by name, with its kind,
|
|
86
|
+
* quality score and live status. Names come back in their published
|
|
87
|
+
* spelling ("corent-flux-schnell") and can be passed straight back as
|
|
88
|
+
* `model`. Carries no price -- billing is flat cost-plus and the exact
|
|
89
|
+
* charge comes back on each generation. Public. */
|
|
90
|
+
async models() {
|
|
91
|
+
const r = await this.request("GET", "/v1/models");
|
|
92
|
+
return r.models;
|
|
93
|
+
}
|
|
53
94
|
/** @internal */
|
|
54
|
-
async request(method, path, body, idempotent = false) {
|
|
95
|
+
async request(method, path, body, idempotent = false, retryTransport = true, idempotencyKey) {
|
|
55
96
|
const headers = {
|
|
56
97
|
Authorization: `Bearer ${this.apiKey}`,
|
|
57
|
-
"User-Agent": "corent-js/0.
|
|
98
|
+
"User-Agent": "corent-js/0.3.0"
|
|
58
99
|
};
|
|
59
100
|
if (body) headers["Content-Type"] = "application/json";
|
|
60
|
-
if (idempotent) headers["Idempotency-Key"] = crypto.randomUUID();
|
|
101
|
+
if (idempotent) headers["Idempotency-Key"] = idempotencyKey ?? crypto.randomUUID();
|
|
61
102
|
let lastError;
|
|
62
103
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
63
104
|
let resp;
|
|
@@ -69,6 +110,7 @@ var Corent = class {
|
|
|
69
110
|
});
|
|
70
111
|
} catch (err) {
|
|
71
112
|
lastError = err;
|
|
113
|
+
if (!retryTransport) throw new CorentError(`request failed: ${err}`);
|
|
72
114
|
await sleep(Math.min(2 ** attempt * 1e3, 8e3));
|
|
73
115
|
continue;
|
|
74
116
|
}
|
|
@@ -111,22 +153,108 @@ var Images = class {
|
|
|
111
153
|
}
|
|
112
154
|
c;
|
|
113
155
|
/** Render an image. Submits as a background job and polls, so a client
|
|
114
|
-
* timeout can never lose a finished render. Pass wait:false for the Job.
|
|
156
|
+
* timeout can never lose a finished render. Pass wait:false for the Job.
|
|
157
|
+
*
|
|
158
|
+
* `model` pins an exact model from client.models() instead of letting the
|
|
159
|
+
* router choose — direct access: never substituted, flat cost-plus price.
|
|
160
|
+
* e.g. model: "corent-flux-schnell". Pass tier OR model, not both. */
|
|
115
161
|
async generate(prompt, options = {}) {
|
|
162
|
+
if (options.referenceImageUrls && (options.referenceImageUrls.length < 1 || options.referenceImageUrls.length > 4)) {
|
|
163
|
+
throw new InvalidRequestError("referenceImageUrls must contain 1 to 4 image URLs", 400);
|
|
164
|
+
}
|
|
116
165
|
const body = {
|
|
117
166
|
prompt,
|
|
118
167
|
aspect_ratio: options.aspectRatio ?? "1:1",
|
|
119
168
|
async: true
|
|
120
169
|
};
|
|
121
170
|
if (options.tier) body.tier = options.tier;
|
|
171
|
+
if (options.model) body.model = options.model;
|
|
122
172
|
if (options.style) body.style = options.style;
|
|
123
|
-
|
|
173
|
+
if (options.referenceImageUrls) body.reference_image_urls = options.referenceImageUrls;
|
|
174
|
+
if (options.seed !== void 0) body.seed = options.seed;
|
|
175
|
+
if (options.negativePrompt) body.negative_prompt = options.negativePrompt;
|
|
176
|
+
if (options.sourceImageUrl) body.source_image_url = options.sourceImageUrl;
|
|
177
|
+
if (options.strength !== void 0) body.strength = options.strength;
|
|
178
|
+
if (options.outputFormat) body.output_format = options.outputFormat;
|
|
179
|
+
if (options.transparent) body.transparent = true;
|
|
180
|
+
if (options.width !== void 0) body.width = options.width;
|
|
181
|
+
if (options.height !== void 0) body.height = options.height;
|
|
182
|
+
if (options.enhancePrompt === false) body.enhance_prompt = false;
|
|
183
|
+
if (options.webhookUrl) {
|
|
184
|
+
body.webhook_url = options.webhookUrl;
|
|
185
|
+
if (options.webhookSecret) body.webhook_secret = options.webhookSecret;
|
|
186
|
+
delete body.async;
|
|
187
|
+
}
|
|
188
|
+
const submitted = await this.c.request(
|
|
189
|
+
"POST",
|
|
190
|
+
"/v1/images/generate",
|
|
191
|
+
body,
|
|
192
|
+
true,
|
|
193
|
+
true,
|
|
194
|
+
options.idempotencyKey
|
|
195
|
+
);
|
|
124
196
|
if (submitted.status === "completed") return imageFromJob(submitted);
|
|
125
|
-
if (options.wait === false) {
|
|
197
|
+
if (options.webhookUrl || options.wait === false) {
|
|
126
198
|
return { id: submitted.id, status: submitted.status, raw: submitted };
|
|
127
199
|
}
|
|
128
200
|
return imageFromJob(await this.c.waitForJob(submitted.id, options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS));
|
|
129
201
|
}
|
|
202
|
+
/** Render several versions of one prompt in a single call, 2–10.
|
|
203
|
+
*
|
|
204
|
+
* Each one is a real render at the normal price, so asking for four costs
|
|
205
|
+
* four images. They come back together, and `totalCostCents` is the whole
|
|
206
|
+
* charge. Partial success is a real outcome: if three of four land you get
|
|
207
|
+
* three and are billed for three.
|
|
208
|
+
*
|
|
209
|
+
* Different from client.batches.images(), which runs DIFFERENT prompts and
|
|
210
|
+
* returns job ids to poll. This one runs the SAME prompt and waits. */
|
|
211
|
+
async generateMany(prompt, count, options = {}) {
|
|
212
|
+
if (count < 2 || count > MAX_IMAGES_PER_REQUEST) {
|
|
213
|
+
throw new InvalidRequestError(
|
|
214
|
+
`generateMany takes 2 to ${MAX_IMAGES_PER_REQUEST}; use generate() for one`,
|
|
215
|
+
400
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
const body = {
|
|
219
|
+
prompt,
|
|
220
|
+
aspect_ratio: options.aspectRatio ?? "1:1",
|
|
221
|
+
n: count
|
|
222
|
+
};
|
|
223
|
+
if (options.tier) body.tier = options.tier;
|
|
224
|
+
if (options.model) body.model = options.model;
|
|
225
|
+
if (options.style) body.style = options.style;
|
|
226
|
+
if (options.referenceImageUrls) body.reference_image_urls = options.referenceImageUrls;
|
|
227
|
+
if (options.seed !== void 0) body.seed = options.seed;
|
|
228
|
+
if (options.negativePrompt) body.negative_prompt = options.negativePrompt;
|
|
229
|
+
if (options.sourceImageUrl) body.source_image_url = options.sourceImageUrl;
|
|
230
|
+
if (options.strength !== void 0) body.strength = options.strength;
|
|
231
|
+
if (options.outputFormat) body.output_format = options.outputFormat;
|
|
232
|
+
if (options.transparent) body.transparent = true;
|
|
233
|
+
if (options.width !== void 0) body.width = options.width;
|
|
234
|
+
if (options.height !== void 0) body.height = options.height;
|
|
235
|
+
if (options.enhancePrompt === false) body.enhance_prompt = false;
|
|
236
|
+
const r = await this.c.request(
|
|
237
|
+
"POST",
|
|
238
|
+
"/v1/images/generate",
|
|
239
|
+
body,
|
|
240
|
+
true,
|
|
241
|
+
true,
|
|
242
|
+
options.idempotencyKey
|
|
243
|
+
);
|
|
244
|
+
const meta = r.meta ?? {};
|
|
245
|
+
return {
|
|
246
|
+
images: (r.images ?? []).map((image) => ({
|
|
247
|
+
id: r.id,
|
|
248
|
+
url: image.url,
|
|
249
|
+
width: image.width,
|
|
250
|
+
height: image.height,
|
|
251
|
+
model: meta.model,
|
|
252
|
+
costCents: void 0
|
|
253
|
+
})),
|
|
254
|
+
// The total for every image that actually landed.
|
|
255
|
+
totalCostCents: meta.cost_cents
|
|
256
|
+
};
|
|
257
|
+
}
|
|
130
258
|
};
|
|
131
259
|
var Videos = class {
|
|
132
260
|
constructor(c) {
|
|
@@ -135,18 +263,41 @@ var Videos = class {
|
|
|
135
263
|
c;
|
|
136
264
|
/** Render a video (1–5 minutes typical). resolution: 720p | 1080p | 4k —
|
|
137
265
|
* tier-capped, clamped down rather than rejected. imageUrl animates an
|
|
138
|
-
* existing image (image-to-video).
|
|
266
|
+
* existing image (image-to-video).
|
|
267
|
+
*
|
|
268
|
+
* `model` pins an exact model from client.models() — direct access, never
|
|
269
|
+
* substituted, and duration/resolution snap to THAT model's own menu rather
|
|
270
|
+
* than a tier cap. e.g. model: "corent-seedance-2.0". Pass tier OR model,
|
|
271
|
+
* not both. */
|
|
139
272
|
async generate(prompt, options = {}) {
|
|
140
|
-
const body = {
|
|
141
|
-
|
|
142
|
-
aspect_ratio: options.aspectRatio ?? "16:9"
|
|
143
|
-
};
|
|
273
|
+
const body = { prompt };
|
|
274
|
+
if (options.aspectRatio) body.aspect_ratio = options.aspectRatio;
|
|
144
275
|
if (options.tier) body.tier = options.tier;
|
|
276
|
+
if (options.model) body.model = options.model;
|
|
277
|
+
if (options.style) body.style = options.style;
|
|
145
278
|
if (options.durationS !== void 0) body.duration_s = options.durationS;
|
|
146
279
|
if (options.resolution) body.resolution = options.resolution;
|
|
147
280
|
if (options.imageUrl) body.image_url = options.imageUrl;
|
|
148
|
-
|
|
149
|
-
if (options.
|
|
281
|
+
if (options.audio !== void 0) body.audio = options.audio;
|
|
282
|
+
if (options.endImageUrl) body.end_image_url = options.endImageUrl;
|
|
283
|
+
if (options.camera) body.camera = options.camera;
|
|
284
|
+
if (options.negativePrompt) body.negative_prompt = options.negativePrompt;
|
|
285
|
+
if (options.seed !== void 0) body.seed = options.seed;
|
|
286
|
+
if (options.fps !== void 0) body.fps = options.fps;
|
|
287
|
+
if (options.enhancePrompt === false) body.enhance_prompt = false;
|
|
288
|
+
if (options.webhookUrl) {
|
|
289
|
+
body.webhook_url = options.webhookUrl;
|
|
290
|
+
if (options.webhookSecret) body.webhook_secret = options.webhookSecret;
|
|
291
|
+
}
|
|
292
|
+
const submitted = await this.c.request(
|
|
293
|
+
"POST",
|
|
294
|
+
"/v1/videos/generate",
|
|
295
|
+
body,
|
|
296
|
+
true,
|
|
297
|
+
true,
|
|
298
|
+
options.idempotencyKey
|
|
299
|
+
);
|
|
300
|
+
if (options.webhookUrl || options.wait === false) {
|
|
150
301
|
return { id: submitted.id, status: submitted.status, raw: submitted };
|
|
151
302
|
}
|
|
152
303
|
return videoFromJob(await this.c.waitForJob(submitted.id, options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS));
|
|
@@ -157,15 +308,111 @@ var Speech = class {
|
|
|
157
308
|
this.c = c;
|
|
158
309
|
}
|
|
159
310
|
c;
|
|
160
|
-
/** Text to speech; synchronous, returns the finished audio and exact charge.
|
|
311
|
+
/** Text to speech; synchronous, returns the finished audio and exact charge.
|
|
312
|
+
* `model` pins an exact speech model from client.models(),
|
|
313
|
+
* e.g. model: "corent-eleven-multilingual-v2". */
|
|
161
314
|
async generate(text, options = {}) {
|
|
162
315
|
const body = { text };
|
|
163
316
|
if (options.voiceId) body.voice_id = options.voiceId;
|
|
164
|
-
|
|
317
|
+
if (options.model) body.model = options.model;
|
|
318
|
+
if (options.stability !== void 0) body.stability = options.stability;
|
|
319
|
+
if (options.similarity !== void 0) body.similarity = options.similarity;
|
|
320
|
+
if (options.style !== void 0) body.style = options.style;
|
|
321
|
+
if (options.speed !== void 0) body.speed = options.speed;
|
|
322
|
+
if (options.language) body.language = options.language;
|
|
323
|
+
if (options.outputFormat) body.output_format = options.outputFormat;
|
|
324
|
+
const r = await this.c.request("POST", "/v1/audio/speech", body, true, true, options.idempotencyKey);
|
|
165
325
|
const meta = r.meta ?? {};
|
|
166
326
|
return { id: r.id, url: r.audio_url, model: meta.model, costCents: meta.cost_cents };
|
|
167
327
|
}
|
|
168
328
|
};
|
|
329
|
+
var Text = class {
|
|
330
|
+
constructor(c) {
|
|
331
|
+
this.c = c;
|
|
332
|
+
}
|
|
333
|
+
c;
|
|
334
|
+
/** One prompt in, the finished text out. `system` frames the request.
|
|
335
|
+
*
|
|
336
|
+
* `model` pins an exact text model from client.models() (kind "text"),
|
|
337
|
+
* e.g. model: "corent-claude-opus-5"; otherwise `tier` picks the routed
|
|
338
|
+
* lane. Pass tier OR model, not both. */
|
|
339
|
+
async generate(prompt, options = {}) {
|
|
340
|
+
const messages = options.system ? [{ role: "system", content: options.system }, { role: "user", content: prompt }] : [{ role: "user", content: prompt }];
|
|
341
|
+
return this.chat(messages, options);
|
|
342
|
+
}
|
|
343
|
+
/** A full OpenAI-shaped conversation, including tool results. Streaming is
|
|
344
|
+
* not wrapped here — point any OpenAI client at https://api.corent.tech/v1
|
|
345
|
+
* with your Corent key for that. */
|
|
346
|
+
async chat(messages, options = {}) {
|
|
347
|
+
const body = {
|
|
348
|
+
// The API's `model` field carries both modes: a pinned catalog name
|
|
349
|
+
// ("corent-claude-opus-5"), or "corent/text-<tier>" for the routed lane.
|
|
350
|
+
// Note the two are different namespaces -- the routed lane keeps its
|
|
351
|
+
// slash form. Whatever the caller passes goes through verbatim; the API
|
|
352
|
+
// still accepts the older bare spellings. lite matches the router's own
|
|
353
|
+
// default for an unrecognised tier.
|
|
354
|
+
model: options.model ?? `corent/text-${options.tier ?? "lite"}`,
|
|
355
|
+
messages
|
|
356
|
+
};
|
|
357
|
+
if (options.maxTokens !== void 0) body.max_tokens = options.maxTokens;
|
|
358
|
+
if (options.maxCompletionTokens !== void 0) body.max_completion_tokens = options.maxCompletionTokens;
|
|
359
|
+
if (options.temperature !== void 0) body.temperature = options.temperature;
|
|
360
|
+
if (options.tools) body.tools = options.tools;
|
|
361
|
+
if (options.toolChoice !== void 0) body.tool_choice = options.toolChoice;
|
|
362
|
+
if (options.responseFormat) body.response_format = options.responseFormat;
|
|
363
|
+
const r = await this.c.request("POST", "/v1/chat/completions", body, false, false);
|
|
364
|
+
const choice = (r.choices ?? [{}])[0];
|
|
365
|
+
const message = choice.message ?? {};
|
|
366
|
+
const usage = r.usage ?? {};
|
|
367
|
+
return {
|
|
368
|
+
id: r.id,
|
|
369
|
+
text: message.content ?? "",
|
|
370
|
+
model: r.model,
|
|
371
|
+
finishReason: choice.finish_reason,
|
|
372
|
+
toolCalls: message.tool_calls,
|
|
373
|
+
promptTokens: usage.prompt_tokens,
|
|
374
|
+
completionTokens: usage.completion_tokens,
|
|
375
|
+
costCents: (r.corent ?? {}).cost_cents
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
};
|
|
379
|
+
var Batches = class {
|
|
380
|
+
constructor(c) {
|
|
381
|
+
this.c = c;
|
|
382
|
+
}
|
|
383
|
+
c;
|
|
384
|
+
async images(items, options = {}) {
|
|
385
|
+
return this.submit("/v1/images/generate/batch", items.map(imageBatchItemBody), options);
|
|
386
|
+
}
|
|
387
|
+
async videos(items, options = {}) {
|
|
388
|
+
return this.submit("/v1/videos/generate/batch", items.map(videoBatchItemBody), options);
|
|
389
|
+
}
|
|
390
|
+
/** How far along a submitted batch is, and each item's job id. Fetch a
|
|
391
|
+
* finished item's media with client.jobs.get(). */
|
|
392
|
+
async progress(batchId) {
|
|
393
|
+
const r = await this.c.request("GET", `/v1/batches/${batchId}`);
|
|
394
|
+
return {
|
|
395
|
+
batchId: r.batch_id,
|
|
396
|
+
total: r.total,
|
|
397
|
+
completed: r.completed,
|
|
398
|
+
failed: r.failed,
|
|
399
|
+
pending: r.pending,
|
|
400
|
+
jobs: r.jobs ?? []
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
async submit(path, items, options) {
|
|
404
|
+
if (items.length < 1 || items.length > MAX_BATCH_ITEMS) {
|
|
405
|
+
throw new InvalidRequestError(`a batch takes 1 to ${MAX_BATCH_ITEMS} items, got ${items.length}`, 400);
|
|
406
|
+
}
|
|
407
|
+
const body = { items };
|
|
408
|
+
if (options.webhookUrl) {
|
|
409
|
+
body.webhook_url = options.webhookUrl;
|
|
410
|
+
if (options.webhookSecret) body.webhook_secret = options.webhookSecret;
|
|
411
|
+
}
|
|
412
|
+
const r = await this.c.request("POST", path, body, true, true, options.idempotencyKey);
|
|
413
|
+
return { batchId: r.batch_id, jobIds: r.job_ids ?? [] };
|
|
414
|
+
}
|
|
415
|
+
};
|
|
169
416
|
var Jobs = class {
|
|
170
417
|
constructor(c) {
|
|
171
418
|
this.c = c;
|
|
@@ -175,6 +422,15 @@ var Jobs = class {
|
|
|
175
422
|
const raw = await this.c.request("GET", `/v1/jobs/${jobId}`);
|
|
176
423
|
return { id: raw.id, status: raw.status, raw };
|
|
177
424
|
}
|
|
425
|
+
/** Stop a job that has not finished and release its money hold.
|
|
426
|
+
*
|
|
427
|
+
* Charges nothing. A job that completed just before the cancel landed stays
|
|
428
|
+
* completed and stays billed for what was really delivered — `cancelled`
|
|
429
|
+
* says which happened. */
|
|
430
|
+
async cancel(jobId) {
|
|
431
|
+
const r = await this.c.request("POST", `/v1/jobs/${jobId}/cancel`);
|
|
432
|
+
return { id: r.id, status: r.status, cancelled: Boolean(r.cancelled) };
|
|
433
|
+
}
|
|
178
434
|
async wait(jobId, timeoutMs = DEFAULT_WAIT_TIMEOUT_MS) {
|
|
179
435
|
const raw = await this.c.waitForJob(jobId, timeoutMs);
|
|
180
436
|
return { id: raw.id, status: raw.status, raw };
|
|
@@ -218,6 +474,22 @@ function videoFromJob(job) {
|
|
|
218
474
|
costCents: meta.cost_cents
|
|
219
475
|
};
|
|
220
476
|
}
|
|
477
|
+
function imageBatchItemBody(item) {
|
|
478
|
+
const body = { prompt: item.prompt };
|
|
479
|
+
if (item.tier) body.tier = item.tier;
|
|
480
|
+
if (item.style) body.style = item.style;
|
|
481
|
+
if (item.aspectRatio) body.aspect_ratio = item.aspectRatio;
|
|
482
|
+
return body;
|
|
483
|
+
}
|
|
484
|
+
function videoBatchItemBody(item) {
|
|
485
|
+
const body = { prompt: item.prompt };
|
|
486
|
+
if (item.tier) body.tier = item.tier;
|
|
487
|
+
if (item.style) body.style = item.style;
|
|
488
|
+
if (item.aspectRatio) body.aspect_ratio = item.aspectRatio;
|
|
489
|
+
if (item.durationS !== void 0) body.duration_s = item.durationS;
|
|
490
|
+
if (item.resolution) body.resolution = item.resolution;
|
|
491
|
+
return body;
|
|
492
|
+
}
|
|
221
493
|
function sleep(ms) {
|
|
222
494
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
223
495
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "corent-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Official TypeScript/JavaScript SDK for Corent — one API for AI image, video, and
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Official TypeScript/JavaScript SDK for Corent — one API for AI image, video, voice, and text generation with built-in routing, failover, and exact receipts.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
21
21
|
"test": "npm run build && node --test test/*.test.js"
|
|
22
22
|
},
|
|
23
|
-
"keywords": ["ai", "image-generation", "video-generation", "text-to-speech", "api", "corent"],
|
|
23
|
+
"keywords": ["ai", "image-generation", "video-generation", "text-to-speech", "llm", "api", "corent"],
|
|
24
24
|
"homepage": "https://corent.tech/docs",
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"tsup": "^8.0.0",
|