@nodaro/sdk 1.30.1 → 2.2.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.cjs +454 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +719 -9
- package/dist/index.d.ts +719 -9
- package/dist/index.js +435 -14
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,41 @@
|
|
|
1
|
+
import { SCENE3D_V2_LIMITS, WORKSPACE_HEADER } from '@nodaro/shared';
|
|
2
|
+
export { CHARACTER_ASPECT_DEFAULTS, CHARACTER_ASPECT_OPTIONS, CHARACTER_STYLES, OBJECT_ASPECT_DEFAULTS as CREATURE_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS as CREATURE_ASPECT_OPTIONS, CREATURE_ATTACH_COLUMNS, LOCATION_ASSET_TYPES, LOCATION_ATTACH_COLUMNS, OBJECT_ASPECT_DEFAULTS, OBJECT_ASPECT_OPTIONS, OBJECT_ASSET_TYPES, OBJECT_ATTACH_COLUMNS, PROMPT_PREFIX_KEY, PROMPT_SUFFIX_KEY, SURROUND_DIRECTIONS, USAGE_GROUP_BYS, WORKSPACE_HEADER } from '@nodaro/shared';
|
|
1
3
|
import { buildPersonHints } from '@nodaro/prompts';
|
|
2
4
|
export { PEOPLE, PERSON_DIMENSION_LABELS, PERSON_DIMENSION_ORDER, buildPersonHints } from '@nodaro/prompts';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
// src/binary-response.ts
|
|
7
|
+
async function readBinaryResponse(response, maxBytes) {
|
|
8
|
+
const advertised = response.headers.get("content-length");
|
|
9
|
+
if (advertised !== null && (!/^\d+$/.test(advertised) || Number(advertised) > maxBytes)) {
|
|
10
|
+
await response.body?.cancel();
|
|
11
|
+
throw new Error("Binary response exceeds its declared size limit");
|
|
12
|
+
}
|
|
13
|
+
if (!response.body) return new ArrayBuffer(0);
|
|
14
|
+
const reader = response.body.getReader();
|
|
15
|
+
const chunks = [];
|
|
16
|
+
let length = 0;
|
|
17
|
+
try {
|
|
18
|
+
while (true) {
|
|
19
|
+
const next = await reader.read();
|
|
20
|
+
if (next.done) break;
|
|
21
|
+
length += next.value.byteLength;
|
|
22
|
+
if (length > maxBytes) {
|
|
23
|
+
await reader.cancel();
|
|
24
|
+
throw new Error("Binary response exceeds its declared size limit");
|
|
25
|
+
}
|
|
26
|
+
chunks.push(next.value);
|
|
27
|
+
}
|
|
28
|
+
} finally {
|
|
29
|
+
reader.releaseLock();
|
|
30
|
+
}
|
|
31
|
+
const bytes = new Uint8Array(length);
|
|
32
|
+
let offset = 0;
|
|
33
|
+
for (const chunk of chunks) {
|
|
34
|
+
bytes.set(chunk, offset);
|
|
35
|
+
offset += chunk.byteLength;
|
|
36
|
+
}
|
|
37
|
+
return bytes.buffer;
|
|
38
|
+
}
|
|
5
39
|
|
|
6
40
|
// src/errors.ts
|
|
7
41
|
var NodaroError = class extends Error {
|
|
@@ -59,8 +93,8 @@ var StorageExceededError = class extends NodaroError {
|
|
|
59
93
|
limitBytes;
|
|
60
94
|
};
|
|
61
95
|
var WorkflowConflictError = class extends NodaroError {
|
|
62
|
-
constructor(message = "Workflow was updated by another writer", currentUpdatedAt, currentVersion, currentRecord) {
|
|
63
|
-
super(message,
|
|
96
|
+
constructor(message = "Workflow was updated by another writer", currentUpdatedAt, currentVersion, currentRecord, code = "workflow_conflict") {
|
|
97
|
+
super(message, code, 409);
|
|
64
98
|
this.currentUpdatedAt = currentUpdatedAt;
|
|
65
99
|
this.currentVersion = currentVersion;
|
|
66
100
|
this.currentRecord = currentRecord;
|
|
@@ -70,6 +104,14 @@ var WorkflowConflictError = class extends NodaroError {
|
|
|
70
104
|
currentVersion;
|
|
71
105
|
currentRecord;
|
|
72
106
|
};
|
|
107
|
+
var StudioOpError = class extends NodaroError {
|
|
108
|
+
constructor(message, code, status, opIndex) {
|
|
109
|
+
super(message, code, status);
|
|
110
|
+
this.opIndex = opIndex;
|
|
111
|
+
this.name = "StudioOpError";
|
|
112
|
+
}
|
|
113
|
+
opIndex;
|
|
114
|
+
};
|
|
73
115
|
var JobBlockedError = class extends NodaroError {
|
|
74
116
|
constructor(message = "Blocked by this deployment's content policy") {
|
|
75
117
|
super(message, "job_blocked", 422);
|
|
@@ -116,14 +158,18 @@ function throwFromResponse(status, body) {
|
|
|
116
158
|
const code = body.error?.code ?? "internal_error";
|
|
117
159
|
const message = body.error?.message ?? "Request failed";
|
|
118
160
|
if (status === 401) throw new UnauthorizedError(message);
|
|
119
|
-
if (status === 409 && code === "workflow_conflict") {
|
|
161
|
+
if (status === 409 && (code === "workflow_conflict" || code === "production_busy")) {
|
|
120
162
|
throw new WorkflowConflictError(
|
|
121
163
|
message,
|
|
122
164
|
body.error?.currentUpdatedAt,
|
|
123
165
|
body.error?.currentVersion,
|
|
124
|
-
body.error?.currentRecord
|
|
166
|
+
body.error?.currentRecord,
|
|
167
|
+
code
|
|
125
168
|
);
|
|
126
169
|
}
|
|
170
|
+
if (status >= 400 && status < 500 && typeof body.error?.opIndex === "number") {
|
|
171
|
+
throw new StudioOpError(message, code, status, body.error.opIndex);
|
|
172
|
+
}
|
|
127
173
|
if (status === 422 && code === "job_blocked") throw new JobBlockedError(message);
|
|
128
174
|
if (status === 403 && code === "insufficient_scope") {
|
|
129
175
|
throw new ForbiddenError(message, body.error?.missingScope);
|
|
@@ -492,13 +538,19 @@ var NodesResource = class {
|
|
|
492
538
|
get(type) {
|
|
493
539
|
return this.client.request("GET", `/v1/nodes/${encodeURIComponent(type)}`);
|
|
494
540
|
}
|
|
495
|
-
run(type, params = {}) {
|
|
541
|
+
run(type, params = {}, options = {}) {
|
|
496
542
|
const route = type === "generate-3d-scene" ? "/v1/3d-scene/generate" : type === "edit-3d-scene" ? "/v1/3d-scene/edit" : type === "render-video" && typeof params.planType === "string" ? "/v1/render-video/plan" : `/v1/${encodeURIComponent(type)}`;
|
|
497
|
-
return this.client.request("POST", route, {
|
|
543
|
+
return this.client.request("POST", route, {
|
|
544
|
+
body: params,
|
|
545
|
+
// Transport-level retry safety, opt-in per call. The platform reads the
|
|
546
|
+
// standard header, so a caller that reuses a key on a retry gets the
|
|
547
|
+
// same run back instead of a second charge.
|
|
548
|
+
...options.idempotencyKey ? { headers: { "Idempotency-Key": options.idempotencyKey } } : {}
|
|
549
|
+
});
|
|
498
550
|
}
|
|
499
551
|
async runAndWait(type, params = {}, opts = {}) {
|
|
500
552
|
if (opts.signal?.aborted) throw new JobAbortedError();
|
|
501
|
-
const result = await this.run(type, params);
|
|
553
|
+
const result = await this.run(type, params, { idempotencyKey: opts.idempotencyKey });
|
|
502
554
|
const jobId = extractJobId(result, type);
|
|
503
555
|
return this.pollJob(jobId, type, opts);
|
|
504
556
|
}
|
|
@@ -559,6 +611,125 @@ var NodesResource = class {
|
|
|
559
611
|
}
|
|
560
612
|
}
|
|
561
613
|
};
|
|
614
|
+
function newIdempotencyKey() {
|
|
615
|
+
const random = globalThis.crypto?.randomUUID?.();
|
|
616
|
+
return `sdk-pro3d-${random ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 12)}`}`;
|
|
617
|
+
}
|
|
618
|
+
var Scene3DResource = class {
|
|
619
|
+
constructor(client) {
|
|
620
|
+
this.client = client;
|
|
621
|
+
}
|
|
622
|
+
client;
|
|
623
|
+
capabilities() {
|
|
624
|
+
return this.client.request("GET", "/v1/3d-scene/capabilities");
|
|
625
|
+
}
|
|
626
|
+
/** Current access to both the delivery and its source is required on every read. */
|
|
627
|
+
getDelivery(jobId) {
|
|
628
|
+
return this.client.request("GET", `/v1/3d-scene/deliveries/${encodeURIComponent(jobId)}`);
|
|
629
|
+
}
|
|
630
|
+
deliveryAssetBytes(jobId, asset, options) {
|
|
631
|
+
if (asset.kind !== "poster" && asset.kind !== "validation-report" || asset.usage !== (asset.kind === "poster" ? "poster" : "validation")) {
|
|
632
|
+
throw new Error("This asset is not available through the delivery endpoint");
|
|
633
|
+
}
|
|
634
|
+
if (!Number.isSafeInteger(asset.byteLength) || asset.byteLength < 1 || asset.byteLength > SCENE3D_V2_LIMITS.maxRendererAssetBytes) {
|
|
635
|
+
throw new Error("Invalid scene delivery asset byte length");
|
|
636
|
+
}
|
|
637
|
+
return this.client.requestBytes("GET", `/v1/3d-scene/deliveries/${encodeURIComponent(jobId)}/assets/${encodeURIComponent(asset.assetId)}`, {
|
|
638
|
+
signal: options?.signal,
|
|
639
|
+
maxBytes: asset.byteLength
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
/** Persist deterministic overlays without an LLM or a generation charge. */
|
|
643
|
+
applyEdits(revisionId, params) {
|
|
644
|
+
return this.client.request("POST", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/edits`, { body: params });
|
|
645
|
+
}
|
|
646
|
+
/** Asset access is scoped to an exact retained revision, with fresh authentication. */
|
|
647
|
+
assetBytes(revisionId, asset, options) {
|
|
648
|
+
if (!["glb", "camera-track-json", "poster", "validation-report"].includes(asset.kind)) {
|
|
649
|
+
throw new Error("This asset is not available through the playback endpoint");
|
|
650
|
+
}
|
|
651
|
+
if (!Number.isSafeInteger(asset.byteLength) || asset.byteLength < 1 || asset.byteLength > SCENE3D_V2_LIMITS.maxRendererAssetBytes) {
|
|
652
|
+
throw new Error("Invalid scene asset byte length");
|
|
653
|
+
}
|
|
654
|
+
return this.client.requestBytes("GET", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/assets/${encodeURIComponent(asset.assetId)}`, {
|
|
655
|
+
signal: options?.signal,
|
|
656
|
+
maxBytes: asset.byteLength
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
/** The editable native file has its own authorization lane. */
|
|
660
|
+
sourceBytes(revisionId, options) {
|
|
661
|
+
return this.client.requestBytes("GET", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/source`, {
|
|
662
|
+
signal: options?.signal,
|
|
663
|
+
maxBytes: SCENE3D_V2_LIMITS.maxBlendSourceBytes
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
generate(params) {
|
|
667
|
+
return this.client.nodes.run("generate-3d-scene", params);
|
|
668
|
+
}
|
|
669
|
+
generateAndWait(params, options) {
|
|
670
|
+
return this.client.nodes.runAndWait("generate-3d-scene", params, options);
|
|
671
|
+
}
|
|
672
|
+
edit(params) {
|
|
673
|
+
return this.client.nodes.run("edit-3d-scene", params);
|
|
674
|
+
}
|
|
675
|
+
editAndWait(params, options) {
|
|
676
|
+
return this.client.nodes.runAndWait("edit-3d-scene", params, options);
|
|
677
|
+
}
|
|
678
|
+
/**
|
|
679
|
+
* Price a 3D Render Pro request WITHOUT starting it.
|
|
680
|
+
*
|
|
681
|
+
* Takes the same body a run takes, minus the `quoteId`, and answers a
|
|
682
|
+
* ceiling (`maxCredits`), a `breakdown` to show, and the
|
|
683
|
+
* `normalizedInputHash` admission re-checks. It reserves nothing and spends
|
|
684
|
+
* nothing — a quote is a price, not a purchase.
|
|
685
|
+
*/
|
|
686
|
+
quotePro(params) {
|
|
687
|
+
return this.client.request("POST", "/v1/pro-3d-render/quote", { body: params });
|
|
688
|
+
}
|
|
689
|
+
/**
|
|
690
|
+
* Submit a quoted 3D Render Pro run.
|
|
691
|
+
*
|
|
692
|
+
* Requires the `quoteId` from {@link quotePro}: no run starts at a price
|
|
693
|
+
* nobody showed. Sends an `Idempotency-Key` — a fresh one per call unless you
|
|
694
|
+
* supply your own, which you should when retrying a call that timed out.
|
|
695
|
+
*
|
|
696
|
+
* Availability is a property of the deployment: `capabilities().pro` says
|
|
697
|
+
* whether this install can serve it, and which controls you may offer.
|
|
698
|
+
*/
|
|
699
|
+
runPro(params, options) {
|
|
700
|
+
return this.client.nodes.run("pro-3d-render", params, {
|
|
701
|
+
idempotencyKey: options?.idempotencyKey ?? newIdempotencyKey()
|
|
702
|
+
});
|
|
703
|
+
}
|
|
704
|
+
/**
|
|
705
|
+
* Quote if needed, run, and wait — the whole operation in one call.
|
|
706
|
+
*
|
|
707
|
+
* Two HTTP requests at most, still ONE paid job: when `quoteId` is absent
|
|
708
|
+
* this quotes the identical body first, so the run is admitted against a
|
|
709
|
+
* hash of exactly what was priced. Pass a `quoteId` to run against a quote
|
|
710
|
+
* you already showed the user.
|
|
711
|
+
*
|
|
712
|
+
* Resolves with the settled result — `videoUrl` (the MP4) and `scenePlan`
|
|
713
|
+
* (the exact composition it was rendered from), plus the revision, poster,
|
|
714
|
+
* validation and renderer metadata. Re-render that same `scenePlan` later
|
|
715
|
+
* with {@link render}, or with a `{kind:'scene'}` source; that costs no
|
|
716
|
+
* authoring.
|
|
717
|
+
*/
|
|
718
|
+
async renderProAndWait(params, options) {
|
|
719
|
+
const quoteId = typeof params.quoteId === "string" ? params.quoteId : (await this.quotePro(params)).quoteId;
|
|
720
|
+
return this.client.nodes.runAndWait("pro-3d-render", { ...params, quoteId }, {
|
|
721
|
+
...options,
|
|
722
|
+
idempotencyKey: options?.idempotencyKey ?? newIdempotencyKey()
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
/** Uses the supplied immutable revision; never starts authoring or a rebuild. */
|
|
726
|
+
render(params) {
|
|
727
|
+
return this.client.nodes.run("render-video", params);
|
|
728
|
+
}
|
|
729
|
+
renderAndWait(params, options) {
|
|
730
|
+
return this.client.nodes.runAndWait("render-video", params, options);
|
|
731
|
+
}
|
|
732
|
+
};
|
|
562
733
|
|
|
563
734
|
// src/resources/developer-apps.ts
|
|
564
735
|
var DeveloperAppsResource = class {
|
|
@@ -2372,6 +2543,245 @@ var RecastResource = class {
|
|
|
2372
2543
|
}
|
|
2373
2544
|
};
|
|
2374
2545
|
|
|
2546
|
+
// src/resources/studio.ts
|
|
2547
|
+
function isStudioGenerateEstimate(result) {
|
|
2548
|
+
return result.dryRun === true;
|
|
2549
|
+
}
|
|
2550
|
+
var StudioProductionsResource = class {
|
|
2551
|
+
constructor(client) {
|
|
2552
|
+
this.client = client;
|
|
2553
|
+
}
|
|
2554
|
+
client;
|
|
2555
|
+
path(productionId, suffix = "") {
|
|
2556
|
+
return `/v1/studio/productions/${encodeURIComponent(productionId)}${suffix}`;
|
|
2557
|
+
}
|
|
2558
|
+
// ── reads ────────────────────────────────────────────────────────────────
|
|
2559
|
+
/**
|
|
2560
|
+
* The authoring guide, the full catalog, the plan's JSON Schema and the
|
|
2561
|
+
* operating guide — rendered server-side from the version that is live, so
|
|
2562
|
+
* they describe the platform you are actually talking to. Free.
|
|
2563
|
+
*/
|
|
2564
|
+
async skill() {
|
|
2565
|
+
const res = await this.client.request(
|
|
2566
|
+
"GET",
|
|
2567
|
+
"/v1/studio/productions/skill"
|
|
2568
|
+
);
|
|
2569
|
+
return res.data;
|
|
2570
|
+
}
|
|
2571
|
+
/**
|
|
2572
|
+
* Check a plan before it becomes anything. Free, persists nothing, and
|
|
2573
|
+
* resolves cast names against YOUR library — loop on `errors` until
|
|
2574
|
+
* `valid: true`, then `create({ plan })`.
|
|
2575
|
+
*/
|
|
2576
|
+
async validatePlan(plan) {
|
|
2577
|
+
const res = await this.client.request(
|
|
2578
|
+
"POST",
|
|
2579
|
+
"/v1/studio/productions/validate",
|
|
2580
|
+
{ body: { plan } }
|
|
2581
|
+
);
|
|
2582
|
+
return res.data;
|
|
2583
|
+
}
|
|
2584
|
+
/** Your productions, newest first. Archived rows are hidden unless asked for. */
|
|
2585
|
+
async list(opts = {}) {
|
|
2586
|
+
const res = await this.client.request(
|
|
2587
|
+
"GET",
|
|
2588
|
+
"/v1/studio/productions",
|
|
2589
|
+
{
|
|
2590
|
+
query: {
|
|
2591
|
+
limit: opts.limit,
|
|
2592
|
+
cursor: opts.cursor,
|
|
2593
|
+
includeArchived: opts.includeArchived
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
);
|
|
2597
|
+
return res.data;
|
|
2598
|
+
}
|
|
2599
|
+
/**
|
|
2600
|
+
* One production. A pure read — it never lands a finished job, so call
|
|
2601
|
+
* {@link reconcile} first if you are waiting on one.
|
|
2602
|
+
*/
|
|
2603
|
+
async get(productionId, opts = {}) {
|
|
2604
|
+
const res = await this.client.request(
|
|
2605
|
+
"GET",
|
|
2606
|
+
this.path(productionId),
|
|
2607
|
+
{ query: { detail: opts.detail, shot_id: opts.shotId } }
|
|
2608
|
+
);
|
|
2609
|
+
return res.data.production;
|
|
2610
|
+
}
|
|
2611
|
+
/**
|
|
2612
|
+
* The ordered steps that assemble the film, with what they will cost. Run
|
|
2613
|
+
* them yourself with the ordinary verbs — nothing here blocks for minutes,
|
|
2614
|
+
* and nothing here spends.
|
|
2615
|
+
*/
|
|
2616
|
+
async exportPlan(productionId, opts = {}) {
|
|
2617
|
+
const res = await this.client.request(
|
|
2618
|
+
"GET",
|
|
2619
|
+
this.path(productionId, "/export-plan"),
|
|
2620
|
+
{ query: { upscale: opts.upscale } }
|
|
2621
|
+
);
|
|
2622
|
+
return res.data;
|
|
2623
|
+
}
|
|
2624
|
+
// ── writes ───────────────────────────────────────────────────────────────
|
|
2625
|
+
/** A new production, optionally landed from a plan in the same call. */
|
|
2626
|
+
async create(input = {}) {
|
|
2627
|
+
const res = await this.client.request(
|
|
2628
|
+
"POST",
|
|
2629
|
+
"/v1/studio/productions",
|
|
2630
|
+
{ body: input }
|
|
2631
|
+
);
|
|
2632
|
+
return res.data;
|
|
2633
|
+
}
|
|
2634
|
+
/**
|
|
2635
|
+
* Apply a batch of operations. Atomic: one bad operation refuses the whole
|
|
2636
|
+
* batch with a `StudioOpError` naming its index, and nothing is written. On
|
|
2637
|
+
* success adopt `production` wholesale and carry `version` forward as the
|
|
2638
|
+
* next `baseVersion`.
|
|
2639
|
+
*/
|
|
2640
|
+
async ops(productionId, input) {
|
|
2641
|
+
const res = await this.client.request(
|
|
2642
|
+
"POST",
|
|
2643
|
+
this.path(productionId, "/ops"),
|
|
2644
|
+
{ body: input }
|
|
2645
|
+
);
|
|
2646
|
+
return res.data;
|
|
2647
|
+
}
|
|
2648
|
+
/**
|
|
2649
|
+
* Land every generation that has finished since you last looked, and report
|
|
2650
|
+
* what is still running. The one call that turns finished jobs into results
|
|
2651
|
+
* without a browser open. It writes only when something actually landed.
|
|
2652
|
+
*/
|
|
2653
|
+
async reconcile(productionId) {
|
|
2654
|
+
const res = await this.client.request(
|
|
2655
|
+
"POST",
|
|
2656
|
+
this.path(productionId, "/reconcile")
|
|
2657
|
+
);
|
|
2658
|
+
return res.data;
|
|
2659
|
+
}
|
|
2660
|
+
/** Add a plan's scenes to a production that already exists. */
|
|
2661
|
+
async importPlan(productionId, plan, opts = {}) {
|
|
2662
|
+
const res = await this.client.request(
|
|
2663
|
+
"POST",
|
|
2664
|
+
this.path(productionId, "/import"),
|
|
2665
|
+
{ body: { plan, mode: opts.mode ?? "append" } }
|
|
2666
|
+
);
|
|
2667
|
+
return res.data;
|
|
2668
|
+
}
|
|
2669
|
+
/**
|
|
2670
|
+
* Turn a brief into scenes. The run is a platform job: poll it, and its
|
|
2671
|
+
* scenes land through {@link reconcile}. The production comes back with the
|
|
2672
|
+
* run recorded on it as a pending draft.
|
|
2673
|
+
*/
|
|
2674
|
+
async describe(productionId, input) {
|
|
2675
|
+
const res = await this.client.request(
|
|
2676
|
+
"POST",
|
|
2677
|
+
this.path(productionId, "/describe"),
|
|
2678
|
+
{ body: input }
|
|
2679
|
+
);
|
|
2680
|
+
return res.data;
|
|
2681
|
+
}
|
|
2682
|
+
async generate(productionId, input) {
|
|
2683
|
+
const res = await this.client.request(
|
|
2684
|
+
"POST",
|
|
2685
|
+
this.path(productionId, "/generate"),
|
|
2686
|
+
{ body: input }
|
|
2687
|
+
);
|
|
2688
|
+
return res.data;
|
|
2689
|
+
}
|
|
2690
|
+
generateStill(productionId, shotId, opts = {}) {
|
|
2691
|
+
return this.generate(productionId, { ...opts, kind: "still", shotId });
|
|
2692
|
+
}
|
|
2693
|
+
generateClip(productionId, shotId, opts = {}) {
|
|
2694
|
+
return this.generate(productionId, { ...opts, kind: "clip", shotId });
|
|
2695
|
+
}
|
|
2696
|
+
// ── media on one shot ────────────────────────────────────────────────────
|
|
2697
|
+
/**
|
|
2698
|
+
* Extract a frame from a shot's active clip and put it where `target` says —
|
|
2699
|
+
* a new shot after this one (the default), this shot's sticky start or end
|
|
2700
|
+
* frame, or another still of the same shot. Seconds, not minutes: this one
|
|
2701
|
+
* waits for the job and answers with the changed production.
|
|
2702
|
+
*/
|
|
2703
|
+
async frame(productionId, input) {
|
|
2704
|
+
const res = await this.client.request(
|
|
2705
|
+
"POST",
|
|
2706
|
+
this.path(productionId, "/frame"),
|
|
2707
|
+
{ body: input }
|
|
2708
|
+
);
|
|
2709
|
+
return res.data;
|
|
2710
|
+
}
|
|
2711
|
+
/** Synthesize a shot's spoken line and record it. Waits for the job. */
|
|
2712
|
+
async voice(productionId, input) {
|
|
2713
|
+
const res = await this.client.request(
|
|
2714
|
+
"POST",
|
|
2715
|
+
this.path(productionId, "/voice"),
|
|
2716
|
+
{ body: input }
|
|
2717
|
+
);
|
|
2718
|
+
return res.data;
|
|
2719
|
+
}
|
|
2720
|
+
/**
|
|
2721
|
+
* Recast the voices of a shot's active clip. Minutes of work, so it answers
|
|
2722
|
+
* `jobId` and the new clip lands as a result through its own marker.
|
|
2723
|
+
*/
|
|
2724
|
+
async revoice(productionId, input) {
|
|
2725
|
+
const res = await this.client.request(
|
|
2726
|
+
"POST",
|
|
2727
|
+
this.path(productionId, "/revoice"),
|
|
2728
|
+
{ body: input }
|
|
2729
|
+
);
|
|
2730
|
+
return res.data;
|
|
2731
|
+
}
|
|
2732
|
+
/** Score the film. The finished track lands through its pending marker. */
|
|
2733
|
+
async music(productionId, input) {
|
|
2734
|
+
const res = await this.client.request(
|
|
2735
|
+
"POST",
|
|
2736
|
+
this.path(productionId, "/music"),
|
|
2737
|
+
{ body: input }
|
|
2738
|
+
);
|
|
2739
|
+
return res.data;
|
|
2740
|
+
}
|
|
2741
|
+
// ── audience and copies ──────────────────────────────────────────────────
|
|
2742
|
+
/**
|
|
2743
|
+
* Open the share-by-link read. Deliberately its own route rather than an
|
|
2744
|
+
* operation: who may see the work is decided by the owner, never as a side
|
|
2745
|
+
* effect of a batch that was editing something else.
|
|
2746
|
+
*/
|
|
2747
|
+
async share(productionId) {
|
|
2748
|
+
const res = await this.client.request(
|
|
2749
|
+
"POST",
|
|
2750
|
+
this.path(productionId, "/share"),
|
|
2751
|
+
{ body: { shared: true } }
|
|
2752
|
+
);
|
|
2753
|
+
return res.data.production;
|
|
2754
|
+
}
|
|
2755
|
+
/** Close it again. Sharing is opt-in AND reversible. */
|
|
2756
|
+
async unshare(productionId) {
|
|
2757
|
+
const res = await this.client.request(
|
|
2758
|
+
"POST",
|
|
2759
|
+
this.path(productionId, "/unshare")
|
|
2760
|
+
);
|
|
2761
|
+
return res.data.production;
|
|
2762
|
+
}
|
|
2763
|
+
/**
|
|
2764
|
+
* Copy a production you own or can see into your own Studio project. The
|
|
2765
|
+
* copy starts PRIVATE and visible — sharing and archiving never travel — and
|
|
2766
|
+
* it is copied through YOUR view of the source, so somebody else's bin does
|
|
2767
|
+
* not come with it.
|
|
2768
|
+
*/
|
|
2769
|
+
async clone(productionId, input = {}) {
|
|
2770
|
+
const res = await this.client.request(
|
|
2771
|
+
"POST",
|
|
2772
|
+
this.path(productionId, "/clone"),
|
|
2773
|
+
{ body: input }
|
|
2774
|
+
);
|
|
2775
|
+
return res.data.production;
|
|
2776
|
+
}
|
|
2777
|
+
};
|
|
2778
|
+
var StudioResource = class {
|
|
2779
|
+
productions;
|
|
2780
|
+
constructor(client) {
|
|
2781
|
+
this.productions = new StudioProductionsResource(client);
|
|
2782
|
+
}
|
|
2783
|
+
};
|
|
2784
|
+
|
|
2375
2785
|
// src/resources/community.ts
|
|
2376
2786
|
var CommunityResource = class {
|
|
2377
2787
|
constructor(client) {
|
|
@@ -2753,7 +3163,7 @@ var WorkspacesResource = class {
|
|
|
2753
3163
|
return this.client.requestText("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts, format: "csv" } });
|
|
2754
3164
|
}
|
|
2755
3165
|
};
|
|
2756
|
-
var SDK_VERSION = "
|
|
3166
|
+
var SDK_VERSION = "2.2.0" ;
|
|
2757
3167
|
var CLIENT_HEADER = "X-Nodaro-Client";
|
|
2758
3168
|
var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
2759
3169
|
var NodaroClient = class _NodaroClient {
|
|
@@ -2780,6 +3190,7 @@ var NodaroClient = class _NodaroClient {
|
|
|
2780
3190
|
videoPro;
|
|
2781
3191
|
executions;
|
|
2782
3192
|
nodes;
|
|
3193
|
+
scene3d;
|
|
2783
3194
|
developerApps;
|
|
2784
3195
|
oauth;
|
|
2785
3196
|
apps;
|
|
@@ -2803,6 +3214,7 @@ var NodaroClient = class _NodaroClient {
|
|
|
2803
3214
|
models;
|
|
2804
3215
|
shots;
|
|
2805
3216
|
recast;
|
|
3217
|
+
studio;
|
|
2806
3218
|
community;
|
|
2807
3219
|
templates;
|
|
2808
3220
|
tutorials;
|
|
@@ -2824,6 +3236,7 @@ var NodaroClient = class _NodaroClient {
|
|
|
2824
3236
|
this.videoPro = new VideoProResource(this);
|
|
2825
3237
|
this.executions = new ExecutionsResource(this);
|
|
2826
3238
|
this.nodes = new NodesResource(this);
|
|
3239
|
+
this.scene3d = new Scene3DResource(this);
|
|
2827
3240
|
this.developerApps = new DeveloperAppsResource(this);
|
|
2828
3241
|
this.oauth = new OAuthResource(this);
|
|
2829
3242
|
this.apps = new AppsResource(this);
|
|
@@ -2847,6 +3260,7 @@ var NodaroClient = class _NodaroClient {
|
|
|
2847
3260
|
this.models = new ModelsResource(this);
|
|
2848
3261
|
this.shots = new ShotsResource(this);
|
|
2849
3262
|
this.recast = new RecastResource(this);
|
|
3263
|
+
this.studio = new StudioResource(this);
|
|
2850
3264
|
this.community = new CommunityResource(this);
|
|
2851
3265
|
this.templates = new TemplatesResource(this);
|
|
2852
3266
|
this.tutorials = new TutorialsResource(this);
|
|
@@ -2896,10 +3310,11 @@ var NodaroClient = class _NodaroClient {
|
|
|
2896
3310
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
2897
3311
|
const ac = new AbortController();
|
|
2898
3312
|
const timeoutId = setTimeout(() => ac.abort(), this.timeoutMs);
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
3313
|
+
const abort = () => ac.abort(options.signal?.reason);
|
|
3314
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
3315
|
+
if (options.signal?.aborted) abort();
|
|
2902
3316
|
try {
|
|
3317
|
+
ac.signal.throwIfAborted();
|
|
2903
3318
|
const res = await this.fetch(url, {
|
|
2904
3319
|
method,
|
|
2905
3320
|
headers,
|
|
@@ -2917,8 +3332,14 @@ var NodaroClient = class _NodaroClient {
|
|
|
2917
3332
|
return await read(res);
|
|
2918
3333
|
} finally {
|
|
2919
3334
|
clearTimeout(timeoutId);
|
|
3335
|
+
options.signal?.removeEventListener("abort", abort);
|
|
2920
3336
|
}
|
|
2921
3337
|
}
|
|
3338
|
+
/** Authenticated, bounded binary reads through the normal timeout/error transport. */
|
|
3339
|
+
async requestBytes(method, path, options) {
|
|
3340
|
+
if (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 1) throw new Error("maxBytes must be a positive integer");
|
|
3341
|
+
return this.send(method, path, options, (response) => readBinaryResponse(response, options.maxBytes));
|
|
3342
|
+
}
|
|
2922
3343
|
async request(method, path, options = {}) {
|
|
2923
3344
|
return this.send(
|
|
2924
3345
|
method,
|
|
@@ -3001,6 +3422,6 @@ function supabaseAuth(supabase) {
|
|
|
3001
3422
|
};
|
|
3002
3423
|
}
|
|
3003
3424
|
|
|
3004
|
-
export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CommunityResource, CreaturesResource, CreditsResource, DeveloperAppsResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, ShotsResource, StaticTokenAuth, StorageExceededError, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, supabaseAuth, throwFromResponse };
|
|
3425
|
+
export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CommunityResource, CreaturesResource, CreditsResource, DeveloperAppsResource, ExecutionsResource, ForbiddenError, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MediaResource, ModelsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, Scene3DResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
|
|
3005
3426
|
//# sourceMappingURL=index.js.map
|
|
3006
3427
|
//# sourceMappingURL=index.js.map
|