corent-sdk 0.2.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 +118 -10
- package/dist/index.cjs +271 -17
- package/dist/index.d.cts +248 -8
- package/dist/index.d.ts +248 -8
- package/dist/index.js +271 -17
- 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,32 +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
|
}
|
|
53
85
|
/** The direct-access menu: every model you can pin by name, with its kind,
|
|
54
|
-
* quality score and
|
|
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. */
|
|
55
90
|
async models() {
|
|
56
91
|
const r = await this.request("GET", "/v1/models");
|
|
57
92
|
return r.models;
|
|
58
93
|
}
|
|
59
94
|
/** @internal */
|
|
60
|
-
async request(method, path, body, idempotent = false) {
|
|
95
|
+
async request(method, path, body, idempotent = false, retryTransport = true, idempotencyKey) {
|
|
61
96
|
const headers = {
|
|
62
97
|
Authorization: `Bearer ${this.apiKey}`,
|
|
63
|
-
"User-Agent": "corent-js/0.
|
|
98
|
+
"User-Agent": "corent-js/0.3.0"
|
|
64
99
|
};
|
|
65
100
|
if (body) headers["Content-Type"] = "application/json";
|
|
66
|
-
if (idempotent) headers["Idempotency-Key"] = crypto.randomUUID();
|
|
101
|
+
if (idempotent) headers["Idempotency-Key"] = idempotencyKey ?? crypto.randomUUID();
|
|
67
102
|
let lastError;
|
|
68
103
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
69
104
|
let resp;
|
|
@@ -75,6 +110,7 @@ var Corent = class {
|
|
|
75
110
|
});
|
|
76
111
|
} catch (err) {
|
|
77
112
|
lastError = err;
|
|
113
|
+
if (!retryTransport) throw new CorentError(`request failed: ${err}`);
|
|
78
114
|
await sleep(Math.min(2 ** attempt * 1e3, 8e3));
|
|
79
115
|
continue;
|
|
80
116
|
}
|
|
@@ -121,8 +157,11 @@ var Images = class {
|
|
|
121
157
|
*
|
|
122
158
|
* `model` pins an exact model from client.models() instead of letting the
|
|
123
159
|
* router choose — direct access: never substituted, flat cost-plus price.
|
|
124
|
-
* Pass tier OR model, not both. */
|
|
160
|
+
* e.g. model: "corent-flux-schnell". Pass tier OR model, not both. */
|
|
125
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
|
+
}
|
|
126
165
|
const body = {
|
|
127
166
|
prompt,
|
|
128
167
|
aspect_ratio: options.aspectRatio ?? "1:1",
|
|
@@ -131,13 +170,91 @@ var Images = class {
|
|
|
131
170
|
if (options.tier) body.tier = options.tier;
|
|
132
171
|
if (options.model) body.model = options.model;
|
|
133
172
|
if (options.style) body.style = options.style;
|
|
134
|
-
|
|
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
|
+
);
|
|
135
196
|
if (submitted.status === "completed") return imageFromJob(submitted);
|
|
136
|
-
if (options.wait === false) {
|
|
197
|
+
if (options.webhookUrl || options.wait === false) {
|
|
137
198
|
return { id: submitted.id, status: submitted.status, raw: submitted };
|
|
138
199
|
}
|
|
139
200
|
return imageFromJob(await this.c.waitForJob(submitted.id, options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS));
|
|
140
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
|
+
}
|
|
141
258
|
};
|
|
142
259
|
var Videos = class {
|
|
143
260
|
constructor(c) {
|
|
@@ -150,19 +267,37 @@ var Videos = class {
|
|
|
150
267
|
*
|
|
151
268
|
* `model` pins an exact model from client.models() — direct access, never
|
|
152
269
|
* substituted, and duration/resolution snap to THAT model's own menu rather
|
|
153
|
-
* than a tier cap. Pass tier OR model,
|
|
270
|
+
* than a tier cap. e.g. model: "corent-seedance-2.0". Pass tier OR model,
|
|
271
|
+
* not both. */
|
|
154
272
|
async generate(prompt, options = {}) {
|
|
155
|
-
const body = {
|
|
156
|
-
|
|
157
|
-
aspect_ratio: options.aspectRatio ?? "16:9"
|
|
158
|
-
};
|
|
273
|
+
const body = { prompt };
|
|
274
|
+
if (options.aspectRatio) body.aspect_ratio = options.aspectRatio;
|
|
159
275
|
if (options.tier) body.tier = options.tier;
|
|
160
276
|
if (options.model) body.model = options.model;
|
|
277
|
+
if (options.style) body.style = options.style;
|
|
161
278
|
if (options.durationS !== void 0) body.duration_s = options.durationS;
|
|
162
279
|
if (options.resolution) body.resolution = options.resolution;
|
|
163
280
|
if (options.imageUrl) body.image_url = options.imageUrl;
|
|
164
|
-
|
|
165
|
-
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) {
|
|
166
301
|
return { id: submitted.id, status: submitted.status, raw: submitted };
|
|
167
302
|
}
|
|
168
303
|
return videoFromJob(await this.c.waitForJob(submitted.id, options.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS));
|
|
@@ -174,16 +309,110 @@ var Speech = class {
|
|
|
174
309
|
}
|
|
175
310
|
c;
|
|
176
311
|
/** Text to speech; synchronous, returns the finished audio and exact charge.
|
|
177
|
-
* `model` pins an exact speech model from client.models()
|
|
312
|
+
* `model` pins an exact speech model from client.models(),
|
|
313
|
+
* e.g. model: "corent-eleven-multilingual-v2". */
|
|
178
314
|
async generate(text, options = {}) {
|
|
179
315
|
const body = { text };
|
|
180
316
|
if (options.voiceId) body.voice_id = options.voiceId;
|
|
181
317
|
if (options.model) body.model = options.model;
|
|
182
|
-
|
|
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);
|
|
183
325
|
const meta = r.meta ?? {};
|
|
184
326
|
return { id: r.id, url: r.audio_url, model: meta.model, costCents: meta.cost_cents };
|
|
185
327
|
}
|
|
186
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
|
+
};
|
|
187
416
|
var Jobs = class {
|
|
188
417
|
constructor(c) {
|
|
189
418
|
this.c = c;
|
|
@@ -193,6 +422,15 @@ var Jobs = class {
|
|
|
193
422
|
const raw = await this.c.request("GET", `/v1/jobs/${jobId}`);
|
|
194
423
|
return { id: raw.id, status: raw.status, raw };
|
|
195
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
|
+
}
|
|
196
434
|
async wait(jobId, timeoutMs = DEFAULT_WAIT_TIMEOUT_MS) {
|
|
197
435
|
const raw = await this.c.waitForJob(jobId, timeoutMs);
|
|
198
436
|
return { id: raw.id, status: raw.status, raw };
|
|
@@ -236,6 +474,22 @@ function videoFromJob(job) {
|
|
|
236
474
|
costCents: meta.cost_cents
|
|
237
475
|
};
|
|
238
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
|
+
}
|
|
239
493
|
function sleep(ms) {
|
|
240
494
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
241
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",
|