@nodaro/sdk 2.1.0 → 2.4.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 +158 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +413 -5
- package/dist/index.d.ts +413 -5
- package/dist/index.js +158 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -538,13 +538,19 @@ var NodesResource = class {
|
|
|
538
538
|
get(type) {
|
|
539
539
|
return this.client.request("GET", `/v1/nodes/${encodeURIComponent(type)}`);
|
|
540
540
|
}
|
|
541
|
-
run(type, params = {}) {
|
|
541
|
+
run(type, params = {}, options = {}) {
|
|
542
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)}`;
|
|
543
|
-
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
|
+
});
|
|
544
550
|
}
|
|
545
551
|
async runAndWait(type, params = {}, opts = {}) {
|
|
546
552
|
if (opts.signal?.aborted) throw new JobAbortedError();
|
|
547
|
-
const result = await this.run(type, params);
|
|
553
|
+
const result = await this.run(type, params, { idempotencyKey: opts.idempotencyKey });
|
|
548
554
|
const jobId = extractJobId(result, type);
|
|
549
555
|
return this.pollJob(jobId, type, opts);
|
|
550
556
|
}
|
|
@@ -605,6 +611,10 @@ var NodesResource = class {
|
|
|
605
611
|
}
|
|
606
612
|
}
|
|
607
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
|
+
}
|
|
608
618
|
var Scene3DResource = class {
|
|
609
619
|
constructor(client) {
|
|
610
620
|
this.client = client;
|
|
@@ -613,6 +623,22 @@ var Scene3DResource = class {
|
|
|
613
623
|
capabilities() {
|
|
614
624
|
return this.client.request("GET", "/v1/3d-scene/capabilities");
|
|
615
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 > shared.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
|
+
}
|
|
616
642
|
/** Persist deterministic overlays without an LLM or a generation charge. */
|
|
617
643
|
applyEdits(revisionId, params) {
|
|
618
644
|
return this.client.request("POST", `/v1/3d-scene/revisions/${encodeURIComponent(revisionId)}/edits`, { body: params });
|
|
@@ -649,6 +675,53 @@ var Scene3DResource = class {
|
|
|
649
675
|
editAndWait(params, options) {
|
|
650
676
|
return this.client.nodes.runAndWait("edit-3d-scene", params, options);
|
|
651
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
|
+
}
|
|
652
725
|
/** Uses the supplied immutable revision; never starts authoring or a rebuild. */
|
|
653
726
|
render(params) {
|
|
654
727
|
return this.client.nodes.run("render-video", params);
|
|
@@ -2470,7 +2543,7 @@ var RecastResource = class {
|
|
|
2470
2543
|
}
|
|
2471
2544
|
};
|
|
2472
2545
|
|
|
2473
|
-
// src/resources/studio.ts
|
|
2546
|
+
// src/resources/studio-productions.ts
|
|
2474
2547
|
function isStudioGenerateEstimate(result) {
|
|
2475
2548
|
return result.dryRun === true;
|
|
2476
2549
|
}
|
|
@@ -2702,11 +2775,80 @@ var StudioProductionsResource = class {
|
|
|
2702
2775
|
return res.data.production;
|
|
2703
2776
|
}
|
|
2704
2777
|
};
|
|
2778
|
+
|
|
2779
|
+
// src/resources/studio.ts
|
|
2780
|
+
var root = "/v1/studio/productions";
|
|
2781
|
+
var path = (id) => `${root}/${encodeURIComponent(id)}`;
|
|
2705
2782
|
var StudioResource = class {
|
|
2706
|
-
productions;
|
|
2707
2783
|
constructor(client) {
|
|
2784
|
+
this.client = client;
|
|
2708
2785
|
this.productions = new StudioProductionsResource(client);
|
|
2709
2786
|
}
|
|
2787
|
+
client;
|
|
2788
|
+
productions;
|
|
2789
|
+
capabilities() {
|
|
2790
|
+
return this.client.request("GET", `${root}/capabilities`);
|
|
2791
|
+
}
|
|
2792
|
+
skill() {
|
|
2793
|
+
return this.client.request("GET", `${root}/skill`);
|
|
2794
|
+
}
|
|
2795
|
+
list(options = {}) {
|
|
2796
|
+
return this.client.request("GET", root, { query: options });
|
|
2797
|
+
}
|
|
2798
|
+
get(id, options = {}) {
|
|
2799
|
+
return this.client.request("GET", path(id), { query: { detail: options.detail, shot_id: options.shotId } });
|
|
2800
|
+
}
|
|
2801
|
+
validatePlan(plan) {
|
|
2802
|
+
return this.client.request("POST", `${root}/validate`, { body: { plan } });
|
|
2803
|
+
}
|
|
2804
|
+
create(input) {
|
|
2805
|
+
return this.client.request("POST", root, { body: input });
|
|
2806
|
+
}
|
|
2807
|
+
/** Import a portable document through the compatible server writer.
|
|
2808
|
+
* Retained frame media requires an authorized source; acceptance never transfers. */
|
|
2809
|
+
importBundle(input) {
|
|
2810
|
+
return this.client.request("POST", `${root}/import-bundle`, { body: input });
|
|
2811
|
+
}
|
|
2812
|
+
/** Append a bundle's scenes and frame closure under an exact destination revision. */
|
|
2813
|
+
appendBundle(id, input) {
|
|
2814
|
+
return this.client.request("POST", `${path(id)}/import-bundle`, { body: input });
|
|
2815
|
+
}
|
|
2816
|
+
/** Copy a saved production. Linked copies retain verified inputs, remap
|
|
2817
|
+
* dependencies and require fresh frame acceptance; they start no media jobs. */
|
|
2818
|
+
clone(id, input = {}) {
|
|
2819
|
+
return this.client.request("POST", `${path(id)}/clone`, { body: input });
|
|
2820
|
+
}
|
|
2821
|
+
edit(id, input) {
|
|
2822
|
+
return this.client.request("POST", `${path(id)}/ops`, { body: input });
|
|
2823
|
+
}
|
|
2824
|
+
/** Audience-authorized sharing; an expected revision prevents publication
|
|
2825
|
+
* of concurrent edits the caller has not reviewed. */
|
|
2826
|
+
setShared(id, input) {
|
|
2827
|
+
return this.client.request("POST", `${path(id)}/share`, { body: input });
|
|
2828
|
+
}
|
|
2829
|
+
/** Save ordinary editor fields against the loaded revision. Protected frame
|
|
2830
|
+
* and job state can only change through their dedicated semantic actions. */
|
|
2831
|
+
saveEditorState(id, input) {
|
|
2832
|
+
return this.edit(id, {
|
|
2833
|
+
baseVersion: input.expectedVersion,
|
|
2834
|
+
strict: true,
|
|
2835
|
+
...input.clientRequestId ? { clientRequestId: input.clientRequestId } : {},
|
|
2836
|
+
ops: [{ op: "save_editor_state", expectedVersion: input.expectedVersion, graph: input.graph }]
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
generateKeyframe(id, input) {
|
|
2840
|
+
return this.client.request("POST", `${path(id)}/generate`, { body: { ...input, kind: "keyframe" } });
|
|
2841
|
+
}
|
|
2842
|
+
generateShot(id, input) {
|
|
2843
|
+
return this.client.request("POST", `${path(id)}/generate`, { body: input });
|
|
2844
|
+
}
|
|
2845
|
+
/** A separate explicit review action; generation never calls this method. */
|
|
2846
|
+
acceptKeyframe(id, input, concurrency = {}) {
|
|
2847
|
+
return this.edit(id, { ...concurrency, ops: [{ ...input, op: "accept_keyframe_result" }] });
|
|
2848
|
+
}
|
|
2849
|
+
reconcile(id) {
|
|
2850
|
+
return this.client.request("POST", `${path(id)}/reconcile`, { body: {} });
|
|
2851
|
+
}
|
|
2710
2852
|
};
|
|
2711
2853
|
|
|
2712
2854
|
// src/resources/community.ts
|
|
@@ -3090,7 +3232,7 @@ var WorkspacesResource = class {
|
|
|
3090
3232
|
return this.client.requestText("GET", `/v1/workspaces/${encodeURIComponent(id)}/usage`, { query: { ...opts, format: "csv" } });
|
|
3091
3233
|
}
|
|
3092
3234
|
};
|
|
3093
|
-
var SDK_VERSION = "2.
|
|
3235
|
+
var SDK_VERSION = "2.4.0" ;
|
|
3094
3236
|
var CLIENT_HEADER = "X-Nodaro-Client";
|
|
3095
3237
|
var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
|
|
3096
3238
|
var NodaroClient = class _NodaroClient {
|
|
@@ -3222,8 +3364,8 @@ var NodaroClient = class _NodaroClient {
|
|
|
3222
3364
|
* stalled CSV stream aborts, it does not hang forever). Both the JSON path
|
|
3223
3365
|
* ({@link request}) and the text path ({@link requestText}) go through here.
|
|
3224
3366
|
*/
|
|
3225
|
-
async send(method,
|
|
3226
|
-
const url = this.buildUrl(
|
|
3367
|
+
async send(method, path2, options, read) {
|
|
3368
|
+
const url = this.buildUrl(path2, options.query);
|
|
3227
3369
|
const token = await this.auth.getToken();
|
|
3228
3370
|
const isFormData = typeof FormData !== "undefined" && options.body instanceof FormData;
|
|
3229
3371
|
const headers = {
|
|
@@ -3263,14 +3405,14 @@ var NodaroClient = class _NodaroClient {
|
|
|
3263
3405
|
}
|
|
3264
3406
|
}
|
|
3265
3407
|
/** Authenticated, bounded binary reads through the normal timeout/error transport. */
|
|
3266
|
-
async requestBytes(method,
|
|
3408
|
+
async requestBytes(method, path2, options) {
|
|
3267
3409
|
if (!Number.isSafeInteger(options.maxBytes) || options.maxBytes < 1) throw new Error("maxBytes must be a positive integer");
|
|
3268
|
-
return this.send(method,
|
|
3410
|
+
return this.send(method, path2, options, (response) => readBinaryResponse(response, options.maxBytes));
|
|
3269
3411
|
}
|
|
3270
|
-
async request(method,
|
|
3412
|
+
async request(method, path2, options = {}) {
|
|
3271
3413
|
return this.send(
|
|
3272
3414
|
method,
|
|
3273
|
-
|
|
3415
|
+
path2,
|
|
3274
3416
|
options,
|
|
3275
3417
|
async (res) => (
|
|
3276
3418
|
// 204 No Content
|
|
@@ -3283,8 +3425,8 @@ var NodaroClient = class _NodaroClient {
|
|
|
3283
3425
|
* are still the JSON envelope and throw the same typed errors, and the read is
|
|
3284
3426
|
* bounded by the same timeout as the request.
|
|
3285
3427
|
*/
|
|
3286
|
-
async requestText(method,
|
|
3287
|
-
return this.send(method,
|
|
3428
|
+
async requestText(method, path2, options = {}) {
|
|
3429
|
+
return this.send(method, path2, options, (res) => res.text());
|
|
3288
3430
|
}
|
|
3289
3431
|
/**
|
|
3290
3432
|
* `GET /v1/me` → the authenticated user's identity (see {@link UserIdentity}).
|
|
@@ -3303,9 +3445,9 @@ var NodaroClient = class _NodaroClient {
|
|
|
3303
3445
|
const res = await this.request("GET", "/v1/me");
|
|
3304
3446
|
return res.data;
|
|
3305
3447
|
}
|
|
3306
|
-
buildUrl(
|
|
3448
|
+
buildUrl(path2, query) {
|
|
3307
3449
|
const base = this.baseUrl || (typeof window !== "undefined" ? window.location.origin : "http://placeholder");
|
|
3308
|
-
const url = new URL(
|
|
3450
|
+
const url = new URL(path2, base);
|
|
3309
3451
|
const fullUrl = this.baseUrl ? url.toString() : url.pathname + url.search;
|
|
3310
3452
|
if (query) {
|
|
3311
3453
|
const u = new URL(this.baseUrl ? fullUrl : fullUrl, base);
|