@nodaro/sdk 2.19.0 → 2.21.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 CHANGED
@@ -76,7 +76,7 @@ Core pattern (all generation is async; runAndWait submits + polls + resolves):
76
76
  auth: new StaticTokenAuth(process.env.NODARO_ACCESS_TOKEN!),
77
77
  })
78
78
  const img = await client.nodes.runAndWait("generate-image", {
79
- prompt: "…", provider: "nano-banana-2", // fast + cheap, great default
79
+ prompt: "…", provider: "nano-banana-2-1", // fast + cheap, great default
80
80
  })
81
81
  const vid = await client.nodes.runAndWait("generate-video", {
82
82
  prompt: "…", imageUrl: img.imageUrl,
@@ -137,7 +137,7 @@ A proven first build (text in → video out). Paste after the primer:
137
137
 
138
138
  ```text
139
139
  Build a small web app — "animated postcard":
140
- 1. A prompt box. On submit: generate-image (nano-banana-2) with the prompt.
140
+ 1. A prompt box. On submit: generate-image (nano-banana-2-1) with the prompt.
141
141
  2. Show the image IMMEDIATELY when it resolves.
142
142
  3. Then generate-video (seedance-2-fast, duration 4) with that image as
143
143
  imageUrl and prompt "subtle cinematic motion".
package/dist/index.cjs CHANGED
@@ -300,6 +300,34 @@ var WorkflowsResource = class {
300
300
  { body: params }
301
301
  );
302
302
  }
303
+ /**
304
+ * Render final (`renderFinal` on `POST /v1/workflows/:id/run`): run the
305
+ * render at Final for this run only, and every node after it, continuing the
306
+ * execution that stopped at its preview. The server derives the nodes and
307
+ * the override — send nothing else. Quote it first with
308
+ * {@link estimateRenderFinal}. Refused with `render_final_node_not_found`,
309
+ * `render_final_not_a_render`, or a continuation code (see `run`); a run
310
+ * its payer cannot cover throws `InsufficientCreditsError` (with `required`
311
+ * and, when it is yours to see, `available`) before any execution exists.
312
+ */
313
+ renderFinal(id, params) {
314
+ return this.client.request("POST", `/v1/workflows/${encodeURIComponent(id)}/run`, {
315
+ body: {
316
+ renderFinal: { renderNodeId: params.renderNodeId },
317
+ continueFromExecutionId: params.continueFromExecutionId
318
+ }
319
+ });
320
+ }
321
+ /**
322
+ * Quote a Render final (`POST /v1/workflows/:id/render-final/estimate`): the
323
+ * nodes it will run, the override it runs with and its estimated credits.
324
+ * Nothing is created or charged.
325
+ */
326
+ estimateRenderFinal(id, params) {
327
+ return this.client.request("POST", `/v1/workflows/${encodeURIComponent(id)}/render-final/estimate`, {
328
+ body: { renderNodeId: params.renderNodeId, continueFromExecutionId: params.continueFromExecutionId }
329
+ });
330
+ }
303
331
  /**
304
332
  * Export a workflow as a portable JSON bundle.
305
333
  * Pass `opts.assets = true` to include character/object/location entity data.
@@ -2078,13 +2106,21 @@ var VoicesResource = class {
2078
2106
  }
2079
2107
  /**
2080
2108
  * Voice a multi-speaker script as ONE audio file
2081
- * (`POST /v1/text-to-dialogue`, ElevenLabs Dialogue v3). Each `dialogue`
2082
- * line is `{ text, voice }` in speaking order — `voice` is a premade voice
2083
- * name or an ElevenLabs voice UUID (cloned/library voices work too; mixed
2084
- * casts are fine). At most 5,000 characters total across lines (≤2,000
2085
- * recommended for best quality) and 10 unique voices. Line text may carry
2086
- * `[audio tags]` like `[laughs]`. Costs credits and runs async — poll
2087
- * `jobs.get(jobId)` for `output_data.audioUrl`.
2109
+ * (`POST /v1/text-to-dialogue`) on ElevenLabs Dialogue v3 — the default — or
2110
+ * Dialogue v4 (`provider: "elevenlabs-dialogue-v4"`). Each `dialogue` line is
2111
+ * `{ text, voice }` in speaking order — `voice` is a premade voice name or an
2112
+ * ElevenLabs voice UUID (cloned/library voices work too; mixed casts are
2113
+ * fine). At most 5,000 characters total across lines on Dialogue v3 and
2114
+ * 10,000 on Dialogue v4 (≤2,000 recommended for best quality) and 10 unique
2115
+ * voices. Line text may
2116
+ * carry `[audio tags]` like `[laughs]`. Costs credits and runs async — poll
2117
+ * `jobs.get(jobId)` for `output_data.audioUrl` and — on every dialogue model,
2118
+ * since both return timings at no extra credits — `output_data.transcript`, a
2119
+ * `Transcript` (`@nodaro/shared`): `words[]` with `startMs` / `endMs` /
2120
+ * `speaker` and one `segments[]` entry per line, `speaker` being the line's
2121
+ * `voice` as you sent it. Pass `transcript.words` to
2122
+ * `addCaptions({ captions, autoTranscribe: false })` to caption the dialogue
2123
+ * without a second transcription.
2088
2124
  */
2089
2125
  textToDialogue(input) {
2090
2126
  return this.client.request("POST", "/v1/text-to-dialogue", { body: input });
@@ -2440,7 +2476,14 @@ var AudioResource = class {
2440
2476
  /**
2441
2477
  * Layer multiple audio tracks into one (`POST /v1/mix-audio`). `audioUrls`
2442
2478
  * (2–20) are summed; optional `trackVolumes` (0–200% each, positionally) set
2443
- * per-track level.
2479
+ * per-track level. `duck` puts a music bed under speech: every track EXCEPT
2480
+ * `duck.under` (the 0-based index of the voice track) dips while that track
2481
+ * is loud and rises back in its pauses (sidechain compression). `amount`
2482
+ * (0–100, default 75) is how hard; `thresholdDb` (-60–0, default -30),
2483
+ * `ratio` (1–20, overrides `amount`), `attackMs` (1–2000, default 20) and
2484
+ * `releaseMs` (10–9000, default 500) are optional fine controls. A ducked mix
2485
+ * sums its tracks rather than averaging them, so the voice keeps its level;
2486
+ * the price is the same with or without a duck.
2444
2487
  */
2445
2488
  mix(input) {
2446
2489
  return this.client.request("POST", "/v1/mix-audio", { body: input });
@@ -2655,6 +2698,66 @@ var SavedPostsResource = class {
2655
2698
  }
2656
2699
  };
2657
2700
 
2701
+ // src/resources/collections.ts
2702
+ var CollectionsResource = class {
2703
+ constructor(client) {
2704
+ this.client = client;
2705
+ }
2706
+ client;
2707
+ /** `GET /v1/collections` → your collections with their record counts, whether the server has collections at all, and your caps. */
2708
+ list() {
2709
+ return this.client.request("GET", "/v1/collections");
2710
+ }
2711
+ /** `GET /v1/collections/:id` → one collection. */
2712
+ get(id) {
2713
+ return this.client.request("GET", `/v1/collections/${encodeURIComponent(id)}`);
2714
+ }
2715
+ /** `POST /v1/collections` → a new collection (`409 name_taken` when you have one by that name, `403 collection_limit_reached` at your cap). */
2716
+ create(input) {
2717
+ return this.client.request("POST", "/v1/collections", { body: input });
2718
+ }
2719
+ /** `PATCH /v1/collections/:id` → rename or re-describe a collection. */
2720
+ update(id, input) {
2721
+ return this.client.request("PATCH", `/v1/collections/${encodeURIComponent(id)}`, { body: input });
2722
+ }
2723
+ /** `DELETE /v1/collections/:id` → remove a collection and every record in it. */
2724
+ async delete(id) {
2725
+ await this.client.request("DELETE", `/v1/collections/${encodeURIComponent(id)}`);
2726
+ }
2727
+ /** `GET /v1/collections/:id/records` → the records, newest first. Narrow with `q` (words) and `since` (ISO); page with `cursor` / `limit` (1-100, default 50). */
2728
+ records(id, params = {}) {
2729
+ return this.client.request("GET", `/v1/collections/${encodeURIComponent(id)}/records`, {
2730
+ query: { q: params.q, since: params.since, cursor: params.cursor, limit: params.limit }
2731
+ });
2732
+ }
2733
+ /**
2734
+ * `POST /v1/collections/:id/records` → save one record. Give the fields, or
2735
+ * `item` (any JSON — a feed post, a search result) and let the server map it;
2736
+ * explicit fields win. `outcome` is `inserted`, `duplicate` (the same link or
2737
+ * dedupe key is already there — the existing record comes back) or `replayed`
2738
+ * (a write with the same `idempotencyKey` already happened).
2739
+ */
2740
+ addRecord(id, input, opts = {}) {
2741
+ return this.client.request("POST", `/v1/collections/${encodeURIComponent(id)}/records`, {
2742
+ body: input,
2743
+ ...opts.idempotencyKey ? { headers: { "Idempotency-Key": opts.idempotencyKey } } : {}
2744
+ });
2745
+ }
2746
+ /** `DELETE /v1/collections/:id/records/:recordId` → remove one record. */
2747
+ async deleteRecord(id, recordId) {
2748
+ await this.client.request(
2749
+ "DELETE",
2750
+ `/v1/collections/${encodeURIComponent(id)}/records/${encodeURIComponent(recordId)}`
2751
+ );
2752
+ }
2753
+ /** `GET /v1/collections/:id/export` → the whole collection as CSV (default) or JSON text, newest first; `since` and `q` narrow it. */
2754
+ export(id, params = {}) {
2755
+ return this.client.requestText("GET", `/v1/collections/${encodeURIComponent(id)}/export`, {
2756
+ query: { format: params.format, since: params.since, q: params.q }
2757
+ });
2758
+ }
2759
+ };
2760
+
2658
2761
  // src/resources/competitors.ts
2659
2762
  var CompetitorsResource = class {
2660
2763
  constructor(client) {
@@ -2663,12 +2766,37 @@ var CompetitorsResource = class {
2663
2766
  client;
2664
2767
  /** `GET /v1/competitors` → every tracked brand. */
2665
2768
  async list() {
2666
- const res = await this.client.request("GET", "/v1/competitors");
2667
- return res.data;
2769
+ const res = await this.listWithPlan();
2770
+ return [...res.data];
2668
2771
  }
2669
- /** `GET /v1/competitors/:id` → one brand with its latest scan (posts and cards) and its scan history. */
2670
- get(id) {
2671
- return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}`);
2772
+ /** `GET /v1/competitors` → every tracked brand, with how many months of scans your plan keeps. */
2773
+ listWithPlan() {
2774
+ return this.client.request("GET", "/v1/competitors");
2775
+ }
2776
+ /**
2777
+ * `GET /v1/competitors/:id` → one brand with its latest scan (posts and
2778
+ * cards) and its scan history; with `scan`, the brand as of that scan.
2779
+ */
2780
+ get(id, options = {}) {
2781
+ const query = options.scan ? `?scan=${encodeURIComponent(options.scan)}` : "";
2782
+ return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}${query}`);
2783
+ }
2784
+ /** `GET /v1/competitors/:id/history` → the brand's scans oldest first, per platform what each found and read (free). */
2785
+ history(id) {
2786
+ return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}/history`);
2787
+ }
2788
+ /**
2789
+ * `GET /v1/competitors/:id/compare` → the brand over a period, and over a
2790
+ * second one to compare with (free). A post belongs to a period by its
2791
+ * publish date; a period is at most a year.
2792
+ */
2793
+ compare(id, input) {
2794
+ const params = new URLSearchParams({ from: input.from, to: input.to });
2795
+ if (input.vsFrom !== void 0 && input.vsTo !== void 0) {
2796
+ params.set("vsFrom", input.vsFrom);
2797
+ params.set("vsTo", input.vsTo);
2798
+ }
2799
+ return this.client.request("GET", `/v1/competitors/${encodeURIComponent(id)}/compare?${params.toString()}`);
2672
2800
  }
2673
2801
  /** `POST /v1/competitors` → track a brand. Accounts take handles or links. */
2674
2802
  create(input) {
@@ -3761,6 +3889,8 @@ var EditResource = class {
3761
3889
  ...input.output !== void 0 ? { output: input.output } : {},
3762
3890
  ...input.quality !== void 0 ? { quality: input.quality } : {},
3763
3891
  ...input.crossfadeMs !== void 0 ? { crossfadeMs: input.crossfadeMs } : {},
3892
+ ...input.clipKey !== void 0 ? { clipKey: input.clipKey } : {},
3893
+ ...input.planBasis !== void 0 ? { planBasis: input.planBasis } : {},
3764
3894
  ...input.workflowId !== void 0 ? { workflowId: input.workflowId } : {}
3765
3895
  }
3766
3896
  });
@@ -3769,8 +3899,8 @@ var EditResource = class {
3769
3899
  * Plan a transcript-driven cut (`POST /v1/edit-plan`). Reads a timed
3770
3900
  * transcript (plus optional silence ranges) and the media sources, and plans
3771
3901
  * the edit. The finished job's `output_data` holds the plan: an `Edl`
3772
- * (`"tighten"`), an {@link EdlClipSet} (`"clips"`), or a {@link ChapterSet}
3773
- * (`"chapters"`) — normalize it with {@link unwrapEditPlanOutput}.
3902
+ * (`"tighten"` or `"trailer"`), an {@link EdlClipSet} (`"clips"`), or a
3903
+ * {@link ChapterSet} (`"chapters"`) — normalize it with {@link unwrapEditPlanOutput}.
3774
3904
  *
3775
3905
  * On a self-hosted install the request relays to nodaro.ai and needs the
3776
3906
  * install connected (a 503 `code: "nodaro_connection_required"` otherwise);
@@ -3845,7 +3975,7 @@ var EditResource = class {
3845
3975
  return shared.remapTranscriptThroughEdl(edl, transcript);
3846
3976
  }
3847
3977
  };
3848
- var SDK_VERSION = "2.19.0" ;
3978
+ var SDK_VERSION = "2.21.0" ;
3849
3979
  var CLIENT_HEADER = "X-Nodaro-Client";
3850
3980
  var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
3851
3981
  var NodaroClient = class _NodaroClient {
@@ -3892,6 +4022,7 @@ var NodaroClient = class _NodaroClient {
3892
4022
  library;
3893
4023
  presets;
3894
4024
  savedPosts;
4025
+ collections;
3895
4026
  competitors;
3896
4027
  pickerCatalogs;
3897
4028
  catalogs;
@@ -3942,6 +4073,7 @@ var NodaroClient = class _NodaroClient {
3942
4073
  this.library = new LibraryResource(this);
3943
4074
  this.presets = new PresetsResource(this);
3944
4075
  this.savedPosts = new SavedPostsResource(this);
4076
+ this.collections = new CollectionsResource(this);
3945
4077
  this.competitors = new CompetitorsResource(this);
3946
4078
  this.pickerCatalogs = new PickerCatalogsResource(this);
3947
4079
  this.catalogs = new CatalogsResource(this);
@@ -4218,6 +4350,7 @@ exports.CREATURE_ASSET_TYPES = CREATURE_ASSET_TYPES;
4218
4350
  exports.CallbackAuth = CallbackAuth;
4219
4351
  exports.CatalogsResource = CatalogsResource;
4220
4352
  exports.CharactersResource = CharactersResource;
4353
+ exports.CollectionsResource = CollectionsResource;
4221
4354
  exports.CommunityResource = CommunityResource;
4222
4355
  exports.CompetitorsResource = CompetitorsResource;
4223
4356
  exports.CopilotResource = CopilotResource;