codai-sdk 0.67.0 → 0.69.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/dist/index.d.ts +2179 -318
- package/dist/index.js +414 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1583,7 +1583,7 @@ function decodeBase64(b64) {
|
|
|
1583
1583
|
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
1584
1584
|
return out;
|
|
1585
1585
|
}
|
|
1586
|
-
function abortableSleep$
|
|
1586
|
+
function abortableSleep$7(ms, signal) {
|
|
1587
1587
|
return new Promise((resolve, reject) => {
|
|
1588
1588
|
if (signal?.aborted) return reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
1589
1589
|
const t = setTimeout(() => {
|
|
@@ -1698,7 +1698,7 @@ var Videos = class {
|
|
|
1698
1698
|
}
|
|
1699
1699
|
if (st.status === "failed" || st.status === "filtered") throw new Error(`codai video job ${st.status}: ${st.error ?? "no details"}`);
|
|
1700
1700
|
if (Date.now() + pollIntervalMs > deadline) throw new Error(`codai video job ${job.id} did not finish within ${timeoutMs} ms`);
|
|
1701
|
-
await abortableSleep$
|
|
1701
|
+
await abortableSleep$7(pollIntervalMs, signal);
|
|
1702
1702
|
}
|
|
1703
1703
|
}
|
|
1704
1704
|
};
|
|
@@ -1797,14 +1797,14 @@ var Renders = class {
|
|
|
1797
1797
|
}
|
|
1798
1798
|
if (st.status === "failed") throw new Error(`codai render failed: ${st.error ?? "no details"}`);
|
|
1799
1799
|
if (Date.now() + pollIntervalMs > deadline) throw new Error(`codai render ${job.id} did not finish within ${timeoutMs} ms`);
|
|
1800
|
-
await abortableSleep$
|
|
1800
|
+
await abortableSleep$7(pollIntervalMs, signal);
|
|
1801
1801
|
}
|
|
1802
1802
|
}
|
|
1803
1803
|
};
|
|
1804
1804
|
|
|
1805
1805
|
//#endregion
|
|
1806
1806
|
//#region src/resources/documents.ts
|
|
1807
|
-
function abortableSleep$
|
|
1807
|
+
function abortableSleep$6(ms, signal) {
|
|
1808
1808
|
return new Promise((resolve, reject) => {
|
|
1809
1809
|
if (signal?.aborted) return reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
1810
1810
|
const t = setTimeout(() => {
|
|
@@ -1897,7 +1897,7 @@ var Documents = class {
|
|
|
1897
1897
|
if (st.status === "succeeded") return st;
|
|
1898
1898
|
if (st.status === "failed") throw new Error(`codai document preview failed: ${st.error ?? "no details"}`);
|
|
1899
1899
|
if (Date.now() + pollIntervalMs > deadline) throw new Error(`codai document preview ${job.id} did not finish within ${timeoutMs} ms`);
|
|
1900
|
-
await abortableSleep$
|
|
1900
|
+
await abortableSleep$6(pollIntervalMs, signal);
|
|
1901
1901
|
}
|
|
1902
1902
|
}
|
|
1903
1903
|
/** Queue a deck video and poll `renders.retrieve` until it succeeds. Throws on `failed` or timeout. */
|
|
@@ -1929,7 +1929,7 @@ var Documents = class {
|
|
|
1929
1929
|
}
|
|
1930
1930
|
if (st.status === "failed") throw new Error(`codai deck video failed: ${st.error ?? "no details"}`);
|
|
1931
1931
|
if (Date.now() + pollIntervalMs > deadline) throw new Error(`codai deck video ${accepted.id} did not finish within ${timeoutMs} ms`);
|
|
1932
|
-
await abortableSleep$
|
|
1932
|
+
await abortableSleep$6(pollIntervalMs, signal);
|
|
1933
1933
|
}
|
|
1934
1934
|
}
|
|
1935
1935
|
};
|
|
@@ -1937,7 +1937,7 @@ var Documents = class {
|
|
|
1937
1937
|
//#endregion
|
|
1938
1938
|
//#region src/resources/exports.ts
|
|
1939
1939
|
const path$6 = (id) => `/v1/studio/exports/${encodeURIComponent(id)}`;
|
|
1940
|
-
function abortableSleep$
|
|
1940
|
+
function abortableSleep$5(ms, signal) {
|
|
1941
1941
|
return new Promise((resolve, reject) => {
|
|
1942
1942
|
if (signal?.aborted) return reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
1943
1943
|
const t = setTimeout(() => {
|
|
@@ -1978,13 +1978,15 @@ var Exports = class {
|
|
|
1978
1978
|
});
|
|
1979
1979
|
if (st.status === "succeeded" || st.status === "failed") return st;
|
|
1980
1980
|
if (Date.now() + intervalMs > deadline) throw new Error(`codai export ${id} did not finish within ${timeoutMs} ms`);
|
|
1981
|
-
await abortableSleep$
|
|
1981
|
+
await abortableSleep$5(intervalMs, signal);
|
|
1982
1982
|
}
|
|
1983
1983
|
}
|
|
1984
1984
|
};
|
|
1985
1985
|
|
|
1986
1986
|
//#endregion
|
|
1987
1987
|
//#region src/resources/creatives.ts
|
|
1988
|
+
/** True when a `build` answer is the 202 carousel / print export job (poll `exports.wait(r.export.id)`). */
|
|
1989
|
+
const isPagedBuild = (r) => "export" in r && r.export != null;
|
|
1988
1990
|
const path$5 = (id, tail = "") => `/v1/studio/creatives/${encodeURIComponent(id)}${tail}`;
|
|
1989
1991
|
const lottieQuery = (q) => ({
|
|
1990
1992
|
format: q.format,
|
|
@@ -2159,6 +2161,24 @@ var Creatives = class {
|
|
|
2159
2161
|
});
|
|
2160
2162
|
}
|
|
2161
2163
|
/**
|
|
2164
|
+
* Mixdown + mastering + exports of an `audio` creative (MU-05; same `POST …/render` route, HTTP 202). `formats`
|
|
2165
|
+
* (default `['wav', 'mp3']`), `stems: true` adds one WAV per audible track (+50 %), `lrc` exports the timed lyrics
|
|
2166
|
+
* (default on when the document has them), `loudness` is `streaming` (−14) | `podcast` (−16) | `broadcast` (−23) or
|
|
2167
|
+
* LUFS (−40…−5). Poll `renders.retrieve(render_id)`: the finished render's `data[]` holds one signed asset per output
|
|
2168
|
+
* (`output: mix | stem | lrc`). $0.001 per output second, minimum $0.01; held up front, billed on the measured length.
|
|
2169
|
+
* 400 `empty_audio` / `too_long` (20 min) / `no_lyrics`; video creatives use `render`.
|
|
2170
|
+
*/
|
|
2171
|
+
renderAudio(id, body = {}, opts = {}) {
|
|
2172
|
+
return this.http.json(path$5(id, "/render"), {
|
|
2173
|
+
method: "POST",
|
|
2174
|
+
body,
|
|
2175
|
+
headers: opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0,
|
|
2176
|
+
ext: opts.ext,
|
|
2177
|
+
signal: opts.signal,
|
|
2178
|
+
noRetry: !opts.idempotencyKey
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
/**
|
|
2162
2182
|
* PNG still frames at up to 6 times (`t_ms`). `exact: false` (default) screenshots the compiled HTML; `exact: true`
|
|
2163
2183
|
* cuts them from a draft render of the covering scenes. Waits up to ~90 s: frames (`status: 'succeeded'`) or a
|
|
2164
2184
|
* running job (`status: 'running'`) to poll with `frameJob(id, frame_job_id)`. Cached frames are free; 60 frame
|
|
@@ -2308,6 +2328,11 @@ var Creatives = class {
|
|
|
2308
2328
|
* Studio document (`document`, exactly the `POST /v1/studio/documents` body). Converter notes come back in
|
|
2309
2329
|
* `warnings`. The file is free; `preview: true` also queues a billed preview (poll it with
|
|
2310
2330
|
* `documents.waitForPreview`). 400 `not_supported_for_kind` (video / image) or `invalid_spec`.
|
|
2331
|
+
*
|
|
2332
|
+
* A carousel (`format: 'png'` zip of slides or `'pdf'`) or print (`'pdf'`, PDF/X-4 with bleed and optional
|
|
2333
|
+
* `crop_marks`) creative answers HTTP 202 with a queued export job in `export` (`format_id` picks the format,
|
|
2334
|
+
* `quote_micro_usd` is held). Tell the two apart with `isPagedBuild`, poll with `exports.wait(r.export.id)` or use
|
|
2335
|
+
* `buildAndWait`.
|
|
2311
2336
|
*/
|
|
2312
2337
|
build(id, body = {}, opts = {}) {
|
|
2313
2338
|
return this.http.json(path$5(id, "/build"), {
|
|
@@ -2319,6 +2344,69 @@ var Creatives = class {
|
|
|
2319
2344
|
});
|
|
2320
2345
|
}
|
|
2321
2346
|
/**
|
|
2347
|
+
* `build`, then — for a carousel / print creative — poll the export job until it has `succeeded` or `failed`
|
|
2348
|
+
* (`exports.wait`). Resolves to the 200 build for deck / doc / sheet, or to the finished `StudioExport`.
|
|
2349
|
+
*/
|
|
2350
|
+
async buildAndWait(id, body = {}, opts = {}) {
|
|
2351
|
+
const r = await this.build(id, body, {
|
|
2352
|
+
ext: opts.ext,
|
|
2353
|
+
signal: opts.signal
|
|
2354
|
+
});
|
|
2355
|
+
if (!isPagedBuild(r)) return r;
|
|
2356
|
+
const e = r.export;
|
|
2357
|
+
if (e.status === "succeeded" || e.status === "failed") return e;
|
|
2358
|
+
return new Exports(this.http).wait(e.id, opts);
|
|
2359
|
+
}
|
|
2360
|
+
/**
|
|
2361
|
+
* Social post copy for a carousel, image or video creative: a caption + hashtags per platform (`platforms`,
|
|
2362
|
+
* default Instagram + LinkedIn; `language` `ro` (default) | `en`; optional `brief`, `tone`, `seq`) and one alt text
|
|
2363
|
+
* per slide, every answer repaired to the platform's hard limits (changes listed in `fixes`). Nothing is written to
|
|
2364
|
+
* the creative. Token-metered (`cost_micro_usd`) under a small wallet hold (402 `insufficient_funds`); 400
|
|
2365
|
+
* `not_supported_for_kind`, 422 `no_post_copy`, 504 `timeout`. `idempotencyKey` replays a retry (24 h).
|
|
2366
|
+
*/
|
|
2367
|
+
postCopy(id, body = {}, opts = {}) {
|
|
2368
|
+
return this.http.json(path$5(id, "/post-copy"), {
|
|
2369
|
+
method: "POST",
|
|
2370
|
+
body: stripUndefined(body),
|
|
2371
|
+
headers: opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0,
|
|
2372
|
+
ext: opts.ext,
|
|
2373
|
+
signal: opts.signal,
|
|
2374
|
+
noRetry: !opts.idempotencyKey
|
|
2375
|
+
});
|
|
2376
|
+
}
|
|
2377
|
+
/**
|
|
2378
|
+
* Edit a video clip by its transcript: delete word ranges (`remove: [{ from_word, to_word }]`, indexes into the
|
|
2379
|
+
* clip asset's cached transcript from `captions`) from video node `node_id`; the pieces are placed back to back as
|
|
2380
|
+
* one new version (`base_seq` rebased like `edit`, locks honoured unless `force`). Free. 409 `captions_required`
|
|
2381
|
+
* (run `captions` on that clip first) or `stale`; video creatives only.
|
|
2382
|
+
*/
|
|
2383
|
+
transcriptCut(id, body, opts = {}) {
|
|
2384
|
+
return this.http.json(path$5(id, "/transcript-cut"), {
|
|
2385
|
+
method: "POST",
|
|
2386
|
+
body: stripUndefined(body),
|
|
2387
|
+
ext: opts.ext,
|
|
2388
|
+
signal: opts.signal,
|
|
2389
|
+
noRetry: true
|
|
2390
|
+
});
|
|
2391
|
+
}
|
|
2392
|
+
/**
|
|
2393
|
+
* Generate a new picture for an `image` node (`prompt`, optional `model`, `aspect_ratio` — default the closest
|
|
2394
|
+
* ratio of the node box — `base_seq`, `force`) and swap it in as one new version. A node with a `castId` sends that
|
|
2395
|
+
* cast entry's `refAssetIds` as references and appends its `description`, so the subject stays consistent. Billed
|
|
2396
|
+
* like `images.generate` (402 `insufficient_funds`); 400 `content_filtered` charges nothing. `idempotencyKey`
|
|
2397
|
+
* replays a retry (24 h).
|
|
2398
|
+
*/
|
|
2399
|
+
regenerateNode(id, nodeId, body, opts = {}) {
|
|
2400
|
+
return this.http.json(path$5(id, `/nodes/${encodeURIComponent(nodeId)}/regenerate`), {
|
|
2401
|
+
method: "POST",
|
|
2402
|
+
body: stripUndefined(body),
|
|
2403
|
+
headers: opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0,
|
|
2404
|
+
ext: opts.ext,
|
|
2405
|
+
signal: opts.signal,
|
|
2406
|
+
noRetry: !opts.idempotencyKey
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
/**
|
|
2322
2410
|
* Re-apply a brand kit (`brand_kit_id`) or a flat token map (`tokens`) to the creative as one new version: literal
|
|
2323
2411
|
* colours equal to the old brand become token refs, `snap: true` maps every other colour to the nearest kit colour,
|
|
2324
2412
|
* `fonts` (default true) sets heading / body font refs by role, locked nodes are skipped unless `force`. The kit
|
|
@@ -2705,7 +2793,7 @@ var Templates = class {
|
|
|
2705
2793
|
//#endregion
|
|
2706
2794
|
//#region src/resources/productions.ts
|
|
2707
2795
|
const path$2 = (id) => `/v1/studio/productions/${encodeURIComponent(id)}`;
|
|
2708
|
-
function abortableSleep$
|
|
2796
|
+
function abortableSleep$4(ms, signal) {
|
|
2709
2797
|
return new Promise((resolve, reject) => {
|
|
2710
2798
|
if (signal?.aborted) return reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2711
2799
|
const t = setTimeout(() => {
|
|
@@ -2754,7 +2842,7 @@ var Productions = class {
|
|
|
2754
2842
|
const p = await this.retrieve(id, opts);
|
|
2755
2843
|
if (isProductionFinished(p)) return p;
|
|
2756
2844
|
if (Date.now() + interval > deadline) throw new Error(`codai: production ${id} did not finish in time (phase ${p.phase})`);
|
|
2757
|
-
await abortableSleep$
|
|
2845
|
+
await abortableSleep$4(interval, opts.signal);
|
|
2758
2846
|
}
|
|
2759
2847
|
}
|
|
2760
2848
|
/** `create` + `wait`. */
|
|
@@ -2764,6 +2852,293 @@ var Productions = class {
|
|
|
2764
2852
|
}
|
|
2765
2853
|
};
|
|
2766
2854
|
|
|
2855
|
+
//#endregion
|
|
2856
|
+
//#region src/resources/media-ops.ts
|
|
2857
|
+
const BASE$1 = "/v1/studio/media-ops";
|
|
2858
|
+
const opPath = (op) => `${BASE$1}/${encodeURIComponent(op)}`;
|
|
2859
|
+
function abortableSleep$3(ms, signal) {
|
|
2860
|
+
return new Promise((resolve, reject) => {
|
|
2861
|
+
if (signal?.aborted) return reject(signal.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2862
|
+
const t = setTimeout(() => {
|
|
2863
|
+
signal?.removeEventListener("abort", onAbort);
|
|
2864
|
+
resolve();
|
|
2865
|
+
}, ms);
|
|
2866
|
+
const onAbort = () => {
|
|
2867
|
+
clearTimeout(t);
|
|
2868
|
+
reject(signal?.reason ?? /* @__PURE__ */ new Error("Aborted"));
|
|
2869
|
+
};
|
|
2870
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
2871
|
+
});
|
|
2872
|
+
}
|
|
2873
|
+
const toBody = (input) => ({
|
|
2874
|
+
asset_ids: input.assetIds ?? [],
|
|
2875
|
+
params: input.params ?? {},
|
|
2876
|
+
...input.maskPngB64 !== void 0 ? { mask_png_b64: input.maskPngB64 } : {}
|
|
2877
|
+
});
|
|
2878
|
+
/** A run answer is a job (async op, HTTP 202) when `object` is `media_op.job`. */
|
|
2879
|
+
const isMediaOpJob = (r) => r.object === "media_op.job";
|
|
2880
|
+
const isMediaOpJobFinished = (j) => j.status === "ready" || j.status === "failed";
|
|
2881
|
+
var MediaOps = class {
|
|
2882
|
+
http;
|
|
2883
|
+
constructor(http) {
|
|
2884
|
+
this.http = http;
|
|
2885
|
+
}
|
|
2886
|
+
/** `GET /v1/studio/media-ops` — every op with engine, mode, inputs, `available` and a list quote (free). */
|
|
2887
|
+
list(opts = {}) {
|
|
2888
|
+
return this.http.json(BASE$1, {
|
|
2889
|
+
ext: opts.ext,
|
|
2890
|
+
signal: opts.signal
|
|
2891
|
+
});
|
|
2892
|
+
}
|
|
2893
|
+
/** `POST /v1/studio/media-ops/{op}/quote` — exact price of this request; nothing is held or billed. */
|
|
2894
|
+
quote(op, input = {}, opts = {}) {
|
|
2895
|
+
return this.http.json(`${opPath(op)}/quote`, {
|
|
2896
|
+
method: "POST",
|
|
2897
|
+
body: toBody(input),
|
|
2898
|
+
ext: opts.ext,
|
|
2899
|
+
signal: opts.signal
|
|
2900
|
+
});
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* `POST /v1/studio/media-ops/{op}` — sync ops resolve to a `media_op.result` with the outputs, async ops to a
|
|
2904
|
+
* `media_op.job` (`status: pending`; poll with `job` / `wait`). Use `isMediaOpJob` to tell them apart.
|
|
2905
|
+
*/
|
|
2906
|
+
run(op, input = {}, opts = {}) {
|
|
2907
|
+
return this.http.json(opPath(op), {
|
|
2908
|
+
method: "POST",
|
|
2909
|
+
body: toBody(input),
|
|
2910
|
+
headers: opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0,
|
|
2911
|
+
noRetry: !opts.idempotencyKey,
|
|
2912
|
+
ext: opts.ext,
|
|
2913
|
+
signal: opts.signal
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
/** `GET /v1/studio/media-ops/jobs/{id}` — the job; reading a finished one stores its outputs and bills it once. */
|
|
2917
|
+
job(id, opts = {}) {
|
|
2918
|
+
return this.http.json(`${BASE$1}/jobs/${encodeURIComponent(id)}`, {
|
|
2919
|
+
ext: opts.ext,
|
|
2920
|
+
signal: opts.signal
|
|
2921
|
+
});
|
|
2922
|
+
}
|
|
2923
|
+
/**
|
|
2924
|
+
* Poll `job` every `intervalMs` (default 3 s) until it is `ready` or `failed` (a failed job resolves too — check
|
|
2925
|
+
* `status` / `error`). Throws after `timeoutMs` (default 20 min) or when `signal` aborts.
|
|
2926
|
+
*/
|
|
2927
|
+
async wait(id, opts = {}) {
|
|
2928
|
+
const interval = opts.intervalMs ?? 3e3;
|
|
2929
|
+
const deadline = Date.now() + (opts.timeoutMs ?? 12e5);
|
|
2930
|
+
for (;;) {
|
|
2931
|
+
const j = await this.job(id, opts);
|
|
2932
|
+
if (isMediaOpJobFinished(j)) return j;
|
|
2933
|
+
if (Date.now() + interval > deadline) throw new Error(`codai: media job ${id} did not finish in time (status ${j.status})`);
|
|
2934
|
+
await abortableSleep$3(interval, opts.signal);
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
/** `run`, then `wait` when the op is async. */
|
|
2938
|
+
async runAndWait(op, input = {}, opts = {}) {
|
|
2939
|
+
const r = await this.run(op, input, opts);
|
|
2940
|
+
return isMediaOpJob(r) && !isMediaOpJobFinished(r) ? this.wait(r.id, opts) : r;
|
|
2941
|
+
}
|
|
2942
|
+
};
|
|
2943
|
+
|
|
2944
|
+
//#endregion
|
|
2945
|
+
//#region src/resources/lyrics.ts
|
|
2946
|
+
const BASE = "/v1/studio/lyrics";
|
|
2947
|
+
var LyricsResource = class {
|
|
2948
|
+
http;
|
|
2949
|
+
constructor(http) {
|
|
2950
|
+
this.http = http;
|
|
2951
|
+
}
|
|
2952
|
+
post(path, body, opts) {
|
|
2953
|
+
return this.http.json(path, {
|
|
2954
|
+
method: "POST",
|
|
2955
|
+
body,
|
|
2956
|
+
headers: opts.idempotencyKey ? { "Idempotency-Key": opts.idempotencyKey } : void 0,
|
|
2957
|
+
noRetry: !opts.idempotencyKey,
|
|
2958
|
+
ext: opts.ext,
|
|
2959
|
+
signal: opts.signal
|
|
2960
|
+
});
|
|
2961
|
+
}
|
|
2962
|
+
/**
|
|
2963
|
+
* `POST /v1/studio/lyrics` — `{ brief, language: 'ro' | 'en', genre?, mood?, structure?, syllables_per_line?,
|
|
2964
|
+
* rhyme_scheme?, lines_per_section?, title? }` → `studio.lyrics` with every line's syllables and rhyme letter, the
|
|
2965
|
+
* whole song as `text` (`[kind]` headers) and a `report`. `repaired: true` when the repair turn won.
|
|
2966
|
+
*/
|
|
2967
|
+
write(body, opts = {}) {
|
|
2968
|
+
return this.post(BASE, body, opts);
|
|
2969
|
+
}
|
|
2970
|
+
/**
|
|
2971
|
+
* `POST /v1/studio/lyrics/align` — `{ creative_id, clip_id, lyrics_text, language?, apply?, base_seq?,
|
|
2972
|
+
* retranscribe? }` → `studio.lyrics_alignment`: timed `lines`, `lrc`, `match_ratio`, `cached`, and `seq` /
|
|
2973
|
+
* `doc_hash` of the new version when applied.
|
|
2974
|
+
*/
|
|
2975
|
+
align(body, opts = {}) {
|
|
2976
|
+
return this.post(`${BASE}/align`, body, opts);
|
|
2977
|
+
}
|
|
2978
|
+
};
|
|
2979
|
+
|
|
2980
|
+
//#endregion
|
|
2981
|
+
//#region src/resources/jam.ts
|
|
2982
|
+
const JAM_SUBPROTOCOL = "codai-jam";
|
|
2983
|
+
/** WebSocket close codes of `/v1/studio/jam`. */
|
|
2984
|
+
const JAM_CLOSE_CODES = {
|
|
2985
|
+
invalidMessage: 4400,
|
|
2986
|
+
unauthorized: 4401,
|
|
2987
|
+
insufficientFunds: 4402,
|
|
2988
|
+
forbidden: 4403,
|
|
2989
|
+
maxDuration: 4408,
|
|
2990
|
+
busy: 4409,
|
|
2991
|
+
upstream: 4502,
|
|
2992
|
+
unavailable: 4503
|
|
2993
|
+
};
|
|
2994
|
+
const JAM_SCALES = [
|
|
2995
|
+
"SCALE_UNSPECIFIED",
|
|
2996
|
+
"C_MAJOR_A_MINOR",
|
|
2997
|
+
"D_FLAT_MAJOR_B_FLAT_MINOR",
|
|
2998
|
+
"D_MAJOR_B_MINOR",
|
|
2999
|
+
"E_FLAT_MAJOR_C_MINOR",
|
|
3000
|
+
"E_MAJOR_D_FLAT_MINOR",
|
|
3001
|
+
"F_MAJOR_D_MINOR",
|
|
3002
|
+
"G_FLAT_MAJOR_E_FLAT_MINOR",
|
|
3003
|
+
"G_MAJOR_E_MINOR",
|
|
3004
|
+
"A_FLAT_MAJOR_F_MINOR",
|
|
3005
|
+
"A_MAJOR_G_FLAT_MINOR",
|
|
3006
|
+
"B_FLAT_MAJOR_G_MINOR",
|
|
3007
|
+
"B_MAJOR_A_FLAT_MINOR"
|
|
3008
|
+
];
|
|
3009
|
+
const OPEN$1 = 1;
|
|
3010
|
+
function toArrayBuffer(data) {
|
|
3011
|
+
if (data instanceof ArrayBuffer) return data;
|
|
3012
|
+
if (ArrayBuffer.isView(data)) {
|
|
3013
|
+
const v = data;
|
|
3014
|
+
return v.buffer.slice(v.byteOffset, v.byteOffset + v.byteLength);
|
|
3015
|
+
}
|
|
3016
|
+
return null;
|
|
3017
|
+
}
|
|
3018
|
+
/** A live jam session: `on()` listeners for status / audio / errors and typed senders. */
|
|
3019
|
+
var JamSession = class {
|
|
3020
|
+
socket;
|
|
3021
|
+
listeners = /* @__PURE__ */ new Map();
|
|
3022
|
+
outbox = [];
|
|
3023
|
+
closed = false;
|
|
3024
|
+
/** Resolves when the socket is open (rejects if it closes first). */
|
|
3025
|
+
ready;
|
|
3026
|
+
constructor(socket) {
|
|
3027
|
+
this.socket = socket;
|
|
3028
|
+
let resolveReady;
|
|
3029
|
+
let rejectReady;
|
|
3030
|
+
this.ready = new Promise((res, rej) => {
|
|
3031
|
+
resolveReady = res;
|
|
3032
|
+
rejectReady = rej;
|
|
3033
|
+
});
|
|
3034
|
+
this.ready.catch(() => void 0);
|
|
3035
|
+
socket.onopen = () => {
|
|
3036
|
+
for (const f of this.outbox.splice(0)) socket.send(f);
|
|
3037
|
+
resolveReady();
|
|
3038
|
+
};
|
|
3039
|
+
socket.onmessage = (ev) => {
|
|
3040
|
+
if (typeof ev.data !== "string") {
|
|
3041
|
+
const buf = toArrayBuffer(ev.data);
|
|
3042
|
+
if (buf) this.emit({
|
|
3043
|
+
type: "audio",
|
|
3044
|
+
data: buf
|
|
3045
|
+
});
|
|
3046
|
+
return;
|
|
3047
|
+
}
|
|
3048
|
+
let parsed;
|
|
3049
|
+
try {
|
|
3050
|
+
parsed = JSON.parse(ev.data);
|
|
3051
|
+
} catch {
|
|
3052
|
+
return;
|
|
3053
|
+
}
|
|
3054
|
+
if (parsed && typeof parsed === "object" && typeof parsed.type === "string") this.emit(parsed);
|
|
3055
|
+
};
|
|
3056
|
+
socket.onerror = () => {};
|
|
3057
|
+
socket.onclose = (ev) => {
|
|
3058
|
+
rejectReady(/* @__PURE__ */ new Error(`jam socket closed before open (${String(ev.code)} ${ev.reason})`));
|
|
3059
|
+
this.closed = true;
|
|
3060
|
+
this.emit({
|
|
3061
|
+
type: "close",
|
|
3062
|
+
code: ev.code,
|
|
3063
|
+
reason: ev.reason
|
|
3064
|
+
});
|
|
3065
|
+
};
|
|
3066
|
+
}
|
|
3067
|
+
on(type, fn) {
|
|
3068
|
+
let set = this.listeners.get(type);
|
|
3069
|
+
if (!set) this.listeners.set(type, set = /* @__PURE__ */ new Set());
|
|
3070
|
+
set.add(fn);
|
|
3071
|
+
return () => set.delete(fn);
|
|
3072
|
+
}
|
|
3073
|
+
/** Send one client message (JSON). Queued until the socket opens. */
|
|
3074
|
+
send(msg) {
|
|
3075
|
+
if (this.closed) throw new Error("jam session is closed");
|
|
3076
|
+
const frame = JSON.stringify(msg);
|
|
3077
|
+
if (this.socket.readyState === OPEN$1) this.socket.send(frame);
|
|
3078
|
+
else this.outbox.push(frame);
|
|
3079
|
+
}
|
|
3080
|
+
prompts(prompts) {
|
|
3081
|
+
this.send({
|
|
3082
|
+
type: "prompts",
|
|
3083
|
+
prompts
|
|
3084
|
+
});
|
|
3085
|
+
}
|
|
3086
|
+
config(config) {
|
|
3087
|
+
this.send({
|
|
3088
|
+
type: "config",
|
|
3089
|
+
...config
|
|
3090
|
+
});
|
|
3091
|
+
}
|
|
3092
|
+
play() {
|
|
3093
|
+
this.send({ type: "play" });
|
|
3094
|
+
}
|
|
3095
|
+
pause() {
|
|
3096
|
+
this.send({ type: "pause" });
|
|
3097
|
+
}
|
|
3098
|
+
stop() {
|
|
3099
|
+
this.send({ type: "stop" });
|
|
3100
|
+
}
|
|
3101
|
+
reset() {
|
|
3102
|
+
this.send({ type: "reset" });
|
|
3103
|
+
}
|
|
3104
|
+
close(code = 1e3, reason = "client closed") {
|
|
3105
|
+
if (this.closed) return;
|
|
3106
|
+
this.socket.close(code, reason);
|
|
3107
|
+
}
|
|
3108
|
+
emit(ev) {
|
|
3109
|
+
for (const fn of this.listeners.get(ev.type) ?? []) fn(ev);
|
|
3110
|
+
for (const fn of this.listeners.get("*") ?? []) fn(ev);
|
|
3111
|
+
}
|
|
3112
|
+
};
|
|
3113
|
+
/** Build the `wss://…/v1/studio/jam` URL (exported for tests and custom transports). */
|
|
3114
|
+
function jamUrl(baseUrl, opts = {}) {
|
|
3115
|
+
const url = new URL(`${baseUrl.replace(/\/$/, "").replace(/^http/, "ws")}/v1/studio/jam`);
|
|
3116
|
+
if (opts.sessionId) url.searchParams.set("session_id", opts.sessionId);
|
|
3117
|
+
return url.toString();
|
|
3118
|
+
}
|
|
3119
|
+
var Jam = class {
|
|
3120
|
+
defaults;
|
|
3121
|
+
constructor(defaults) {
|
|
3122
|
+
this.defaults = defaults;
|
|
3123
|
+
}
|
|
3124
|
+
/** Open a live jam. Returns immediately; `await session.ready` to wait for the socket. */
|
|
3125
|
+
connect(opts = {}) {
|
|
3126
|
+
const Ctor = opts.WebSocket ?? globalThis.WebSocket;
|
|
3127
|
+
if (!Ctor) throw new Error("codai.jam: no WebSocket available — pass options.WebSocket");
|
|
3128
|
+
let token = opts.token;
|
|
3129
|
+
let apiKey = token ? void 0 : opts.apiKey ?? this.defaults.apiKey;
|
|
3130
|
+
if (apiKey?.startsWith("codai_eph_v1.")) {
|
|
3131
|
+
token = apiKey;
|
|
3132
|
+
apiKey = void 0;
|
|
3133
|
+
}
|
|
3134
|
+
if (!token && !apiKey) throw new Error("codai.jam: pass `token` (browser) or `apiKey`");
|
|
3135
|
+
const url = jamUrl(opts.baseUrl ?? this.defaults.baseUrl, opts);
|
|
3136
|
+
const socket = apiKey ? new Ctor(url, [JAM_SUBPROTOCOL], { headers: { Authorization: `Bearer ${apiKey}` } }) : new Ctor(url, [JAM_SUBPROTOCOL, `bearer.${token}`]);
|
|
3137
|
+
if ("binaryType" in socket) socket.binaryType = "arraybuffer";
|
|
3138
|
+
return new JamSession(socket);
|
|
3139
|
+
}
|
|
3140
|
+
};
|
|
3141
|
+
|
|
2767
3142
|
//#endregion
|
|
2768
3143
|
//#region src/resources/batches.ts
|
|
2769
3144
|
const BATCH_DONE = [
|
|
@@ -6453,6 +6828,12 @@ const OPERATION_METHODS = {
|
|
|
6453
6828
|
listCreativeTemplates: "templates.list",
|
|
6454
6829
|
createStudioProduction: "productions.create",
|
|
6455
6830
|
getStudioProduction: "productions.retrieve",
|
|
6831
|
+
listStudioMediaOps: "mediaOps.list",
|
|
6832
|
+
quoteStudioMediaOp: "mediaOps.quote",
|
|
6833
|
+
runStudioMediaOp: "mediaOps.run",
|
|
6834
|
+
getStudioMediaOpJob: "mediaOps.job",
|
|
6835
|
+
writeStudioLyrics: "lyrics.write",
|
|
6836
|
+
alignStudioLyrics: "lyrics.align",
|
|
6456
6837
|
getCreativeTemplate: "templates.retrieve",
|
|
6457
6838
|
deleteCreativeTemplate: "templates.delete",
|
|
6458
6839
|
exportCreativeFcpxml: "creatives.exportFcpxml",
|
|
@@ -6460,6 +6841,9 @@ const OPERATION_METHODS = {
|
|
|
6460
6841
|
getStudioExport: "exports.retrieve",
|
|
6461
6842
|
createCreativeFromDocument: "creatives.fromDocument",
|
|
6462
6843
|
buildCreative: "creatives.build",
|
|
6844
|
+
writeCreativePostCopy: "creatives.postCopy",
|
|
6845
|
+
transcriptCutCreative: "creatives.transcriptCut",
|
|
6846
|
+
regenerateCreativeNode: "creatives.regenerateNode",
|
|
6463
6847
|
createSystemOne: "systemOne.create",
|
|
6464
6848
|
createTranscription: "audio.transcribe",
|
|
6465
6849
|
createSpeech: "audio.speech",
|
|
@@ -6921,6 +7305,13 @@ var CodaiApps = class {
|
|
|
6921
7305
|
* built-in starters; free; use with creatives.create({ kind, template, vars }))
|
|
6922
7306
|
* client.productions.create / .retrieve / .wait / .run (codai Studio brief → promo video: storyboard, images,
|
|
6923
7307
|
* voice-over, editable creative, draft render, one review + repair; billed as the parts are produced)
|
|
7308
|
+
* client.mediaOps.list / .quote / .run / .job / .wait / .runAndWait (codai Studio media operations on your assets:
|
|
7309
|
+
* background removal, upscale, inpaint / outpaint / erase, stems, denoise, MIDI, mastering, analysis, ACE-Step
|
|
7310
|
+
* music and sound effects; quote held, measured cost billed; async ops return a job)
|
|
7311
|
+
* client.lyrics.write / .align (codai Studio lyrics writer with syllable + rhyme checks; karaoke alignment to a clip
|
|
7312
|
+
* of an audio creative with LRC; token-metered / transcription billed)
|
|
7313
|
+
* client.creatives.renderAudio (mixdown + mastering of an audio creative: WAV / MP3 / FLAC, stems, LRC)
|
|
7314
|
+
* client.jam.connect (WebSocket live jam on Lyria RealTime; not an OpenAPI operation)
|
|
6924
7315
|
* client.exports.retrieve / .wait (codai Studio FCPXML exports queued with creatives.exportFcpxml; only newly
|
|
6925
7316
|
* rendered seconds are billed; Lottie exports from creatives.exportLottie are free and ready at once)
|
|
6926
7317
|
* client.batches.create / .dryRun / .list / .get / .cancel / .retry / .exportCsv / .zip / .wait (codai Studio
|
|
@@ -6989,6 +7380,12 @@ var Codai = class {
|
|
|
6989
7380
|
templates;
|
|
6990
7381
|
/** codai Studio productions (`productions.run({ brief, language: 'ro' })` → a finished promo video + editable creative). */
|
|
6991
7382
|
productions;
|
|
7383
|
+
/** codai Studio media operations (`mediaOps.run('audio.separate_stems', { assetIds })` → job; `mediaOps.wait(id)`). */
|
|
7384
|
+
mediaOps;
|
|
7385
|
+
/** codai Studio lyrics (`lyrics.write({ brief, language: 'ro' })`, `lyrics.align({ creative_id, clip_id, lyrics_text })`). */
|
|
7386
|
+
lyrics;
|
|
7387
|
+
/** codai Studio live jam over WebSocket (`jam.connect({ token })` → PCM16 48 kHz stereo; `prompts`, `config`, `play`). */
|
|
7388
|
+
jam;
|
|
6992
7389
|
/** codai Studio FCPXML exports (`creatives.exportFcpxml(id)` queues one; `exports.wait(id)` polls until the zip is ready). */
|
|
6993
7390
|
exports;
|
|
6994
7391
|
/** codai Studio batches (`batches.create({ source: { template_id }, csv })` → one creative per row; `batches.wait(id)`). */
|
|
@@ -7093,6 +7490,12 @@ var Codai = class {
|
|
|
7093
7490
|
this.brandKits = new BrandKits(http);
|
|
7094
7491
|
this.templates = new Templates(http);
|
|
7095
7492
|
this.productions = new Productions(http);
|
|
7493
|
+
this.mediaOps = new MediaOps(http);
|
|
7494
|
+
this.lyrics = new LyricsResource(http);
|
|
7495
|
+
this.jam = new Jam({
|
|
7496
|
+
baseUrl: http.baseUrl,
|
|
7497
|
+
apiKey: opts.apiKey
|
|
7498
|
+
});
|
|
7096
7499
|
this.exports = new Exports(http);
|
|
7097
7500
|
this.batches = new Batches(http);
|
|
7098
7501
|
this.shares = new Shares(http);
|
|
@@ -7227,5 +7630,5 @@ function allKeys(obj) {
|
|
|
7227
7630
|
}
|
|
7228
7631
|
|
|
7229
7632
|
//#endregion
|
|
7230
|
-
export { AbuseReports, Account, AgentRuns, Agents, Assets, Audio, Batches, Billing, BrandKits, Cards, Chat, ChatCompletions, Codai, Codai as default, CodaiApps, CodaiError, Creatives, Devices, Documents, Embeddings, EnvironmentFiles, EnvironmentJobs, EnvironmentMembers, EnvironmentPorts, EnvironmentSecrets, EnvironmentTasks, Environments, Exports, Feedback, Health, Heartbeats, Hosts, HttpClient, Images, Keys, Lists, Memory, Messages, Models, Music, Notifications, OPERATION_METHODS, OrgMembers, Orgs, OsGate, PROVENANCE_MAX_BYTES, PhoneModels, Productions, Projects, Prompts, Provenance, RESOLVE_ATTESTATION_PAYLOAD_TYPE, RESOLVE_OPERATION_METHODS, RESOLVE_TERMINAL_STATUSES, Realtime, RealtimeSession, Receipts, Referrals, Renders, Research, Resolve, ResolveError, ResolveInsufficientFundsError, Responses, STREAMING_OPERATIONS, SandboxFiles, Sandboxes, ScheduleExecutor, SchedulerHosts, Schedules, SessionControls, SessionEvents, SessionLease, SessionShares, Sessions, Settings, Sfx, Shares, SystemOne, TUS_CHUNK_BYTES, Tasks, Templates, Tokens, Tools, Transcripts, Triggers, Usage, Vault, VaultDevices, Verify, Videos, VoiceRevocations, extensionHeaders, frameJson, isAssetDto, isProductionFinished, isResearchFinished, mergeToolCall, readSse, realtimeUrl, resolveAttestationStatement, settingsConflictCurrent, shareTokenFrom, uploadIdFromLocation, vaultUnlockMessage, verifyAttestationWithKeys, verifyResolveWebhook };
|
|
7633
|
+
export { AbuseReports, Account, AgentRuns, Agents, Assets, Audio, Batches, Billing, BrandKits, Cards, Chat, ChatCompletions, Codai, Codai as default, CodaiApps, CodaiError, Creatives, Devices, Documents, Embeddings, EnvironmentFiles, EnvironmentJobs, EnvironmentMembers, EnvironmentPorts, EnvironmentSecrets, EnvironmentTasks, Environments, Exports, Feedback, Health, Heartbeats, Hosts, HttpClient, Images, JAM_CLOSE_CODES, JAM_SCALES, JAM_SUBPROTOCOL, Jam, JamSession, Keys, Lists, LyricsResource, MediaOps, Memory, Messages, Models, Music, Notifications, OPERATION_METHODS, OrgMembers, Orgs, OsGate, PROVENANCE_MAX_BYTES, PhoneModels, Productions, Projects, Prompts, Provenance, RESOLVE_ATTESTATION_PAYLOAD_TYPE, RESOLVE_OPERATION_METHODS, RESOLVE_TERMINAL_STATUSES, Realtime, RealtimeSession, Receipts, Referrals, Renders, Research, Resolve, ResolveError, ResolveInsufficientFundsError, Responses, STREAMING_OPERATIONS, SandboxFiles, Sandboxes, ScheduleExecutor, SchedulerHosts, Schedules, SessionControls, SessionEvents, SessionLease, SessionShares, Sessions, Settings, Sfx, Shares, SystemOne, TUS_CHUNK_BYTES, Tasks, Templates, Tokens, Tools, Transcripts, Triggers, Usage, Vault, VaultDevices, Verify, Videos, VoiceRevocations, extensionHeaders, frameJson, isAssetDto, isMediaOpJob, isMediaOpJobFinished, isPagedBuild, isProductionFinished, isResearchFinished, jamUrl, mergeToolCall, readSse, realtimeUrl, resolveAttestationStatement, settingsConflictCurrent, shareTokenFrom, uploadIdFromLocation, vaultUnlockMessage, verifyAttestationWithKeys, verifyResolveWebhook };
|
|
7231
7634
|
//# sourceMappingURL=index.js.map
|