@nodaro/sdk 2.27.0 → 2.29.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.js CHANGED
@@ -190,36 +190,57 @@ var JobHeldError = class extends NodaroError {
190
190
  }
191
191
  jobId;
192
192
  };
193
+ var finite = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
194
+ var BARE_CODE = /^[a-z][a-z0-9_]*$/;
195
+ var nonEmpty = (v) => typeof v === "string" && v.length > 0 ? v : void 0;
196
+ function readErrorBody(status, body) {
197
+ const raw = body.error;
198
+ const envelope = raw && typeof raw === "object" ? raw : {};
199
+ const bare = typeof raw === "string" ? raw : void 0;
200
+ const bareCode = bare !== void 0 && BARE_CODE.test(bare) ? bare : void 0;
201
+ const bareSentence = bare !== void 0 && bareCode === void 0 && /\s/.test(bare.trim()) ? bare : void 0;
202
+ const code = nonEmpty(envelope.code) ?? bareCode ?? (status === 400 && raw === void 0 && Array.isArray(body.issues) ? "validation_error" : void 0);
203
+ const outside = status >= 500 ? void 0 : nonEmpty(body.message) ?? nonEmpty(body.error_description) ?? bareSentence;
204
+ const message = nonEmpty(envelope.message) ?? outside;
205
+ return { code, message, envelope };
206
+ }
193
207
  function throwFromResponse(status, body) {
194
- const code = body.error?.code ?? "internal_error";
195
- const message = body.error?.message ?? "Request failed";
196
- if (status === 401) throw new UnauthorizedError(message);
208
+ const parsed = body && typeof body === "object" ? body : {};
209
+ const read = readErrorBody(status, parsed);
210
+ const envelope = read.envelope;
211
+ const code = read.code ?? "internal_error";
212
+ const message = read.message ?? (read.code ? read.code : "Request failed");
213
+ if (status === 401) throw new UnauthorizedError(read.message);
197
214
  if (status === 409 && (code === "workflow_conflict" || code === "production_busy")) {
198
215
  throw new WorkflowConflictError(
199
- message,
200
- body.error?.currentUpdatedAt,
201
- body.error?.currentVersion,
202
- body.error?.currentRecord,
216
+ read.message,
217
+ envelope.currentUpdatedAt,
218
+ envelope.currentVersion,
219
+ envelope.currentRecord,
203
220
  code
204
221
  );
205
222
  }
206
- if (status >= 400 && status < 500 && typeof body.error?.opIndex === "number") {
207
- throw new StudioOpError(message, code, status, body.error.opIndex);
223
+ if (status >= 400 && status < 500 && typeof envelope.opIndex === "number") {
224
+ throw new StudioOpError(message, code, status, envelope.opIndex);
208
225
  }
209
- if (status === 409 && CONTINUATION_REFUSAL_CODES.has(code) && typeof body.jobId === "string") {
210
- throw new ContinuationRefusedError(message, code, body.jobId);
226
+ if (status === 409 && CONTINUATION_REFUSAL_CODES.has(code) && typeof parsed.jobId === "string") {
227
+ throw new ContinuationRefusedError(message, code, parsed.jobId);
211
228
  }
212
- if (status === 422 && code === "job_blocked") throw new JobBlockedError(message);
229
+ if (status === 422 && code === "job_blocked") throw new JobBlockedError(read.message);
213
230
  if (status === 403 && code === "insufficient_scope") {
214
- throw new ForbiddenError(message, body.error?.missingScope);
231
+ throw new ForbiddenError(read.message, envelope.missingScope);
215
232
  }
216
- if (status === 403) throw new ForbiddenError(message);
217
- if (status === 404) throw new NotFoundError(body.error?.message ?? (typeof body.message === "string" ? body.message : void 0));
218
- if (status === 429) throw new RateLimitedError(message);
233
+ if (status === 403) throw new ForbiddenError(read.message);
234
+ if (status === 404) throw new NotFoundError(read.message);
235
+ if (status === 429) throw new RateLimitedError(read.message);
219
236
  if (status === 402) {
220
- throw new InsufficientCreditsError(message, body.error?.required, body.error?.available);
237
+ throw new InsufficientCreditsError(
238
+ read.message,
239
+ finite(envelope.required) ?? finite(parsed.required),
240
+ finite(envelope.available) ?? finite(parsed.balance)
241
+ );
221
242
  }
222
- if (status === 413) throw new StorageExceededError(message, body.error?.limitBytes);
243
+ if (status === 413) throw new StorageExceededError(read.message, envelope.limitBytes);
223
244
  throw new NodaroError(message, code, status);
224
245
  }
225
246
 
@@ -449,7 +470,70 @@ var ProjectsResource = class {
449
470
  }
450
471
  };
451
472
 
473
+ // src/resources/sessions.ts
474
+ var SessionsResource = class {
475
+ constructor(client) {
476
+ this.client = client;
477
+ }
478
+ client;
479
+ /**
480
+ * Create a session. Send its `id` as `sessionId` on a generation request
481
+ * (`nodes.run("generate-image", { sessionId, … })`, video, speech, music) and
482
+ * the job is born in it.
483
+ */
484
+ create(input) {
485
+ return this.client.request("POST", "/v1/sessions", { body: input });
486
+ }
487
+ /** Your sessions, newest first. */
488
+ list(params = {}) {
489
+ const query = {};
490
+ if (params.projectId) query.projectId = params.projectId;
491
+ if (params.tool) query.tool = params.tool;
492
+ if (params.includeArchived) query.includeArchived = "true";
493
+ if (params.limit !== void 0) query.limit = String(params.limit);
494
+ if (params.cursor) query.cursor = params.cursor;
495
+ return this.client.request("GET", "/v1/sessions", { query });
496
+ }
497
+ get(id) {
498
+ return this.client.request("GET", `/v1/sessions/${encodeURIComponent(id)}`);
499
+ }
500
+ /** Rename or archive a session. Its project cannot change. */
501
+ update(id, input) {
502
+ return this.client.request("PATCH", `/v1/sessions/${encodeURIComponent(id)}`, { body: input });
503
+ }
504
+ /** Delete a session and its links. Its jobs are kept, and stay in every other session holding them. */
505
+ delete(id) {
506
+ return this.client.request("DELETE", `/v1/sessions/${encodeURIComponent(id)}`);
507
+ }
508
+ /** The session's items, born-in and imported, newest first. */
509
+ items(id, params = {}) {
510
+ const query = {};
511
+ if (params.limit !== void 0) query.limit = String(params.limit);
512
+ if (params.cursor) query.cursor = params.cursor;
513
+ return this.client.request("GET", `/v1/sessions/${encodeURIComponent(id)}/items`, { query });
514
+ }
515
+ /**
516
+ * Import some of your own jobs into a session — a link, not a copy (up to 100
517
+ * a call). All-or-nothing: if any id is not one of your jobs, nothing is
518
+ * imported and the call fails with 404. Items already there are left as they are.
519
+ */
520
+ importItems(id, input) {
521
+ return this.client.request("POST", `/v1/sessions/${encodeURIComponent(id)}/items`, { body: input });
522
+ }
523
+ /** Remove one item from a session. Only the link goes: the job, and every other session holding it, stay. */
524
+ removeItem(id, jobId) {
525
+ return this.client.request(
526
+ "DELETE",
527
+ `/v1/sessions/${encodeURIComponent(id)}/items/${encodeURIComponent(jobId)}`
528
+ );
529
+ }
530
+ };
531
+
452
532
  // src/resources/jobs.ts
533
+ function listParam(value) {
534
+ if (value === void 0) return void 0;
535
+ return typeof value === "string" ? value : value.join(",");
536
+ }
453
537
  var JobsResource = class {
454
538
  constructor(client) {
455
539
  this.client = client;
@@ -463,9 +547,26 @@ var JobsResource = class {
463
547
  * Your jobs, newest first (`GET /v1/jobs`), cursor-paginated. `type` and
464
548
  * `origin` filter on the job's own `input_data`, which every job carries —
465
549
  * a client app lists its runs with `{ type: "llm-structured", origin: "studio" }`.
550
+ * `status` and `type` take one value or a list; `favorited` and `rating`
551
+ * filter on your own marks. Every filter combines with AND, and each job
552
+ * carries `favorited` and `rating`.
466
553
  */
467
554
  list(params = {}) {
468
- return this.client.request("GET", "/v1/jobs", { query: { ...params } });
555
+ const { status, type, ...rest } = params;
556
+ return this.client.request("GET", "/v1/jobs", {
557
+ query: { ...rest, status: listParam(status), type: listParam(type) }
558
+ });
559
+ }
560
+ /**
561
+ * Rate one of your jobs `"good"` or `"bad"`, or clear the rating with
562
+ * `null` (`PUT /v1/jobs/:id/rating`). Only the job's owner rates it — anyone
563
+ * else's job is a `NotFoundError`. The rating reads back as `Job.rating`
564
+ * and filters {@link list}. OAuth apps need the `assets:write` scope.
565
+ */
566
+ rate(id, rating) {
567
+ return this.client.request("PUT", `/v1/jobs/${encodeURIComponent(id)}/rating`, {
568
+ body: { rating }
569
+ });
469
570
  }
470
571
  /**
471
572
  * Get the lean status of a single job (poll-loop friendly).
@@ -592,6 +693,26 @@ function extractJobId(result, label) {
592
693
  }
593
694
  throw new JobFailedError(`${label} did not return a jobId`, "");
594
695
  }
696
+ function isImageBatchRequest(type, params) {
697
+ if (type !== "generate-image") return false;
698
+ return typeof params.count === "number" && params.count > 1 || Array.isArray(params.models);
699
+ }
700
+ function batchJobIds(result) {
701
+ const ids = result?.jobIds;
702
+ return Array.isArray(ids) && ids.every((id) => typeof id === "string") ? ids : null;
703
+ }
704
+ function batchRefusal(detail) {
705
+ return new NodaroError(
706
+ `${detail}: this waits for one job \u2014 use nodes.runBatchAndWait() for a batch (count above 1, or models).`,
707
+ "batch_requires_run_batch_and_wait",
708
+ 0
709
+ );
710
+ }
711
+ function batchResultOf(result) {
712
+ const r = result;
713
+ if (!r || typeof r.batchId !== "string" || !batchJobIds(result) || !Array.isArray(r.groups)) return null;
714
+ return r;
715
+ }
595
716
  var NodesResource = class {
596
717
  constructor(client) {
597
718
  this.client = client;
@@ -624,10 +745,55 @@ var NodesResource = class {
624
745
  }
625
746
  async runAndWait(type, params = {}, opts = {}) {
626
747
  if (opts.signal?.aborted) throw new JobAbortedError();
748
+ if (isImageBatchRequest(type, params)) throw batchRefusal(`${type} with count above 1 or models makes several jobs`);
627
749
  const result = await this.run(type, params, { idempotencyKey: opts.idempotencyKey });
750
+ const ids = batchJobIds(result);
751
+ if (ids && ids.length > 1) throw batchRefusal(`${type} started ${ids.length} jobs (${ids.join(", ")}), which keep running`);
628
752
  const jobId = extractJobId(result, type);
629
753
  return this.pollJob(jobId, type, opts);
630
754
  }
755
+ /**
756
+ * Run a generate-image BATCH — `count` above 1 and/or `models` — to the end:
757
+ * submit it once ({@link run}, with your `idempotencyKey` if any), then wait
758
+ * for every job at once, each the way {@link runAndWait} waits.
759
+ *
760
+ * Resolves `{ batch, results }`: the submit's answer
761
+ * ({@link GenerateImageBatchResult} — ids, groups by model, credits) and one
762
+ * {@link BatchJobOutcome} per job, in `batch.jobIds` order — its output, or the
763
+ * typed error that ended the wait for it. One image failing never discards the
764
+ * others. Rejects only before any job exists (the submit's own errors, e.g.
765
+ * `InsufficientCreditsError` with the batch total as `required`), and on
766
+ * `signal` ({@link JobAbortedError}; `cancelOnAbort` cancels every job).
767
+ *
768
+ * A request for one image is refused before anything is sent (code
769
+ * `not_a_batch`) — wait for it with {@link runAndWait}.
770
+ */
771
+ async runBatchAndWait(type, params, opts = {}) {
772
+ if (opts.signal?.aborted) throw new JobAbortedError();
773
+ if (!isImageBatchRequest(type, params)) {
774
+ throw new NodaroError(
775
+ "runBatchAndWait waits for a batch \u2014 count above 1, or models; wait for one image with nodes.runAndWait().",
776
+ "not_a_batch",
777
+ 0
778
+ );
779
+ }
780
+ const result = await this.run(type, params, { idempotencyKey: opts.idempotencyKey });
781
+ const batch = batchResultOf(result);
782
+ if (!batch) throw new JobFailedError(`${type} did not answer with a batch`, "");
783
+ const modelOf = new Map(batch.groups.flatMap((group) => group.jobIds.map((id) => [id, group.model])));
784
+ const results = await Promise.all(
785
+ batch.jobIds.map(async (jobId) => {
786
+ const model = modelOf.get(jobId) ?? "";
787
+ try {
788
+ return { jobId, model, status: "completed", output: await this.pollJob(jobId, type, opts) };
789
+ } catch (err) {
790
+ if (err instanceof JobAbortedError || !(err instanceof NodaroError)) throw err;
791
+ return { jobId, model, status: "error", error: err };
792
+ }
793
+ })
794
+ );
795
+ return { batch, results };
796
+ }
631
797
  /**
632
798
  * Fan out N async runs of the same node `type` to completion concurrently —
633
799
  * the candidate-grid path (generate N stills/clips in parallel). Each runs
@@ -643,6 +809,9 @@ var NodesResource = class {
643
809
  */
644
810
  async runMany(type, paramsList, opts = {}) {
645
811
  if (opts.signal?.aborted) throw new JobAbortedError();
812
+ if (paramsList.some((params) => isImageBatchRequest(type, params))) {
813
+ throw batchRefusal(`a ${type} entry with count above 1 or models makes several jobs`);
814
+ }
646
815
  return Promise.all(
647
816
  paramsList.map(async (params) => {
648
817
  if (opts.signal?.aborted) throw new JobAbortedError();
@@ -959,6 +1128,66 @@ var OAuthResource = class {
959
1128
  }
960
1129
  };
961
1130
 
1131
+ // src/resources/webhooks.ts
1132
+ var WebhooksResource = class {
1133
+ constructor(client) {
1134
+ this.client = client;
1135
+ }
1136
+ client;
1137
+ /** `POST /v1/webhook-endpoints` → the endpoint and its signing secret (shown this once). */
1138
+ create(input) {
1139
+ return this.client.request("POST", "/v1/webhook-endpoints", { body: input });
1140
+ }
1141
+ /** `GET /v1/webhook-endpoints` → your endpoints, newest first. Never a secret. */
1142
+ list() {
1143
+ return this.client.request("GET", "/v1/webhook-endpoints");
1144
+ }
1145
+ /** `GET /v1/webhook-endpoints/:id`. */
1146
+ get(id) {
1147
+ return this.client.request("GET", `/v1/webhook-endpoints/${encodeURIComponent(id)}`);
1148
+ }
1149
+ /** `PATCH /v1/webhook-endpoints/:id` → change the address, events, description; switch on or off. */
1150
+ update(id, input) {
1151
+ return this.client.request("PATCH", `/v1/webhook-endpoints/${encodeURIComponent(id)}`, { body: input });
1152
+ }
1153
+ /** `DELETE /v1/webhook-endpoints/:id` → the endpoint and its delivery log. */
1154
+ delete(id) {
1155
+ return this.client.request("DELETE", `/v1/webhook-endpoints/${encodeURIComponent(id)}`);
1156
+ }
1157
+ /**
1158
+ * `POST /v1/webhook-endpoints/:id/rotate-secret` → a new signing secret,
1159
+ * shown this once. It signs every delivery from now on (retries included);
1160
+ * the one it replaces keeps signing beside it for `gracePeriodSeconds` (a
1161
+ * day by default), so update your receiver within that time.
1162
+ */
1163
+ rotateSecret(id, input = {}) {
1164
+ return this.client.request("POST", `/v1/webhook-endpoints/${encodeURIComponent(id)}/rotate-secret`, {
1165
+ body: input
1166
+ });
1167
+ }
1168
+ /** `GET /v1/webhook-endpoints/:id/deliveries` → the delivery log, newest first (kept 30 days). */
1169
+ deliveries(id, params = {}) {
1170
+ return this.client.request("GET", `/v1/webhook-endpoints/${encodeURIComponent(id)}/deliveries`, {
1171
+ query: { status: params.status, limit: params.limit, cursor: params.cursor }
1172
+ });
1173
+ }
1174
+ /** `GET /v1/webhook-endpoints/:id/deliveries/:deliveryId` → one delivery (`test()` returns its id). */
1175
+ getDelivery(id, deliveryId) {
1176
+ return this.client.request(
1177
+ "GET",
1178
+ `/v1/webhook-endpoints/${encodeURIComponent(id)}/deliveries/${encodeURIComponent(deliveryId)}`
1179
+ );
1180
+ }
1181
+ /**
1182
+ * `POST /v1/webhook-endpoints/:id/test` → queue a `ping` (sent within
1183
+ * seconds, tried once — even to an endpoint that is switched off). Follow
1184
+ * it with `deliveries()`.
1185
+ */
1186
+ test(id) {
1187
+ return this.client.request("POST", `/v1/webhook-endpoints/${encodeURIComponent(id)}/test`);
1188
+ }
1189
+ };
1190
+
962
1191
  // src/resources/apps.ts
963
1192
  var AppsResource = class {
964
1193
  constructor(client) {
@@ -1032,7 +1261,7 @@ var CharactersResource = class {
1032
1261
  * List the caller's characters. By default returns active characters only;
1033
1262
  * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1034
1263
  * When `projectId` is set, only characters belonging to that project are
1035
- * returned.
1264
+ * returned; `q` keeps the ones whose name or description contains it.
1036
1265
  *
1037
1266
  * Cursor-paginated: a response carrying a non-null `nextCursor` means more
1038
1267
  * rows exist. Pass it back as `cursor` to fetch the next page, and keep going
@@ -1054,6 +1283,7 @@ var CharactersResource = class {
1054
1283
  const query = {};
1055
1284
  if (params.projectId) query.projectId = params.projectId;
1056
1285
  if (params.archived) query.archived = "true";
1286
+ if (params.q) query.q = params.q;
1057
1287
  if (params.limit !== void 0) query.limit = String(params.limit);
1058
1288
  if (params.cursor) query.cursor = params.cursor;
1059
1289
  return this.client.request("GET", "/v1/characters", { query });
@@ -1186,6 +1416,41 @@ var CharactersResource = class {
1186
1416
  `/v1/characters/${encodeURIComponent(id)}/llm-caption`
1187
1417
  );
1188
1418
  }
1419
+ /**
1420
+ * Start training a high-fidelity model of the character on its own images
1421
+ * (Nodaro Cloud only — other editions answer `NotFoundError`). Reserves the
1422
+ * training price up front and refunds it if the training fails or is
1423
+ * cancelled. Resolves at once (202); a training takes about 15 minutes —
1424
+ * follow it with {@link trainingStatus}. Once it succeeds, a workflow's
1425
+ * Generate Image node whose prompt @-mentions this one character runs on the
1426
+ * trained model.
1427
+ *
1428
+ * An OAuth app token needs the `assets:write` scope (`ForbiddenError`
1429
+ * otherwise, before anything is reserved); a session or personal API key
1430
+ * needs none. Refusals are `NodaroError`s whose `code` is a
1431
+ * {@link TrainCharacterRefusalCode}; rate-limited to 3 calls a minute.
1432
+ */
1433
+ train(id, input = {}) {
1434
+ return this.client.request("POST", `/v1/characters/${encodeURIComponent(id)}/train`, { body: input });
1435
+ }
1436
+ /**
1437
+ * The character's training record (Nodaro Cloud only). Poll it while
1438
+ * `status` is `queued` or `training` — every 10 s or so is plenty.
1439
+ */
1440
+ trainingStatus(id) {
1441
+ return this.client.request("GET", `/v1/characters/${encodeURIComponent(id)}/training`);
1442
+ }
1443
+ /**
1444
+ * Remove the character's trained model (Nodaro Cloud only): cancels a
1445
+ * training in flight and refunds its reservation, deletes the model, and
1446
+ * clears the training record (`trainingStatus` then reads `untrained`).
1447
+ * Generations go back to reference images. Cannot be undone — a new model
1448
+ * means a new, paid training. An OAuth app token needs the `assets:write`
1449
+ * scope (`ForbiddenError` otherwise), like deleting the character.
1450
+ */
1451
+ async deleteLora(id) {
1452
+ await this.client.request("DELETE", `/v1/characters/${encodeURIComponent(id)}/lora`);
1453
+ }
1189
1454
  };
1190
1455
  function buildPersonSeedPrompt(value) {
1191
1456
  return buildPersonHints(value).join(", ");
@@ -1197,11 +1462,13 @@ var LocationsResource = class {
1197
1462
  client;
1198
1463
  /**
1199
1464
  * List the caller's locations. By default returns active locations only;
1200
- * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1465
+ * pass `archived: true` to fetch soft-deleted rows for an "archive" view,
1466
+ * and `q` to keep the ones whose name or description contains it.
1201
1467
  */
1202
1468
  list(params = {}) {
1203
1469
  const query = {};
1204
1470
  if (params.archived) query.archived = "true";
1471
+ if (params.q) query.q = params.q;
1205
1472
  if (params.limit !== void 0) query.limit = String(params.limit);
1206
1473
  if (params.cursor) query.cursor = params.cursor;
1207
1474
  return this.client.request("GET", "/v1/locations", { query });
@@ -1375,12 +1642,14 @@ var ObjectsResource = class {
1375
1642
  /**
1376
1643
  * List the caller's objects. By default returns active objects only;
1377
1644
  * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1378
- * Optional `projectId` scopes the result to a single project.
1645
+ * Optional `projectId` scopes the result to a single project; `q` keeps the
1646
+ * objects whose name or description contains it.
1379
1647
  */
1380
1648
  list(params = {}) {
1381
1649
  const query = {};
1382
1650
  if (params.archived) query.archived = "true";
1383
1651
  if (params.projectId) query.projectId = params.projectId;
1652
+ if (params.q) query.q = params.q;
1384
1653
  if (params.limit !== void 0) query.limit = String(params.limit);
1385
1654
  if (params.cursor) query.cursor = params.cursor;
1386
1655
  return this.client.request("GET", "/v1/objects", { query });
@@ -1561,12 +1830,14 @@ var CreaturesResource = class {
1561
1830
  /**
1562
1831
  * List the caller's creatures. By default returns active creatures only;
1563
1832
  * pass `archived: true` to fetch soft-deleted rows for an "archive" view.
1564
- * Optional `projectId` scopes the result to a single project.
1833
+ * Optional `projectId` scopes the result to a single project; `q` keeps the
1834
+ * creatures whose name or description contains it.
1565
1835
  */
1566
1836
  list(params = {}) {
1567
1837
  const query = {};
1568
1838
  if (params.archived) query.archived = "true";
1569
1839
  if (params.projectId) query.projectId = params.projectId;
1840
+ if (params.q) query.q = params.q;
1570
1841
  if (params.limit !== void 0) query.limit = String(params.limit);
1571
1842
  if (params.cursor) query.cursor = params.cursor;
1572
1843
  return this.client.request("GET", "/v1/creatures", { query });
@@ -2690,6 +2961,53 @@ var CreditsResource = class {
2690
2961
  // a consumer needs it, shaped to that need.
2691
2962
  };
2692
2963
 
2964
+ // src/resources/billing.ts
2965
+ var BillingResource = class {
2966
+ constructor(client) {
2967
+ this.client = client;
2968
+ }
2969
+ client;
2970
+ /**
2971
+ * `GET /v1/billing/plans` → the plans and credit packs on sale, with their
2972
+ * prices. Public: works with no credential, the same for every caller.
2973
+ * Nodaro Cloud only — a self-hosted instance answers 404. Throws on `403
2974
+ * self_serve_disabled` (this deployment does not sell to its users) and on
2975
+ * `503` (`stripe_not_configured`, or prices briefly unavailable).
2976
+ */
2977
+ plans() {
2978
+ return this.client.request("GET", "/v1/billing/plans");
2979
+ }
2980
+ /**
2981
+ * `GET /v1/billing/subscription` → the account's latest subscription
2982
+ * (`null` when it never subscribed) and the tier its entitlements follow.
2983
+ * Match `effectiveTier` to a {@link BillingPlan} `id` to mark the current
2984
+ * plan (no match: pay-as-you-go, or a tier not on sale). Needs a signed-in
2985
+ * session, a personal API token without a workflow limit, or an app's OAuth
2986
+ * token. Nodaro Cloud only — a self-hosted instance answers 404.
2987
+ */
2988
+ subscription() {
2989
+ return this.client.request("GET", "/v1/billing/subscription");
2990
+ }
2991
+ /**
2992
+ * `GET /v1/billing/surface` → how this deployment bills: whether it meters
2993
+ * at all (`providerId !== "none"`) and in which unit costs display. Public,
2994
+ * every edition.
2995
+ */
2996
+ async surface() {
2997
+ const res = await this.client.request("GET", "/v1/billing/surface");
2998
+ return res.data;
2999
+ }
3000
+ /**
3001
+ * `GET /v1/billing/account` → the caller's plan and balance as the
3002
+ * deployment's billing provider reports them, in its display unit. `null`
3003
+ * when the provider could not answer — not a zero balance. Every edition.
3004
+ */
3005
+ async account() {
3006
+ const res = await this.client.request("GET", "/v1/billing/account");
3007
+ return res.data;
3008
+ }
3009
+ };
3010
+
2693
3011
  // src/resources/uploads.ts
2694
3012
  var UploadsResource = class {
2695
3013
  constructor(client) {
@@ -2725,14 +3043,15 @@ var LibraryResource = class {
2725
3043
  /**
2726
3044
  * `GET /v1/library` → a page of the caller's media assets (newest first) plus
2727
3045
  * a `nextCursor`. Pass the returned `nextCursor` back as `cursor` for the next
2728
- * page. Filter by `type` and a filename `search`; `owned: true` returns the
2729
- * full Storage set (uploads + generations), the default only library-saved +
2730
- * shared items.
3046
+ * page. Filter by `type` and search the filename with `q`; `owned: true`
3047
+ * returns the full Storage set (uploads + generations), the default only
3048
+ * library-saved + shared items.
2731
3049
  */
2732
3050
  list(params = {}) {
2733
3051
  const qs = new URLSearchParams();
2734
3052
  if (params.type) qs.set("type", params.type);
2735
- if (params.search) qs.set("search", params.search);
3053
+ if (params.q) qs.set("q", params.q);
3054
+ else if (params.search) qs.set("search", params.search);
2736
3055
  if (params.limit !== void 0) qs.set("limit", String(params.limit));
2737
3056
  if (params.cursor) qs.set("cursor", params.cursor);
2738
3057
  if (params.owned !== void 0) qs.set("owned", String(params.owned));
@@ -2742,6 +3061,46 @@ var LibraryResource = class {
2742
3061
  }
2743
3062
  };
2744
3063
 
3064
+ // src/resources/gallery.ts
3065
+ var GalleryResource = class {
3066
+ constructor(client) {
3067
+ this.client = client;
3068
+ }
3069
+ client;
3070
+ /**
3071
+ * `GET /v1/gallery` → a page of the public gallery, newest first (no auth
3072
+ * needed), or one person's work with `userId`.
3073
+ */
3074
+ browse(params = {}) {
3075
+ return this.client.request("GET", "/v1/gallery", {
3076
+ query: {
3077
+ type: params.type,
3078
+ userId: params.userId,
3079
+ favoritesOnly: params.favoritesOnly,
3080
+ limit: params.limit,
3081
+ cursor: params.cursor
3082
+ }
3083
+ });
3084
+ }
3085
+ /**
3086
+ * Favorite a job, or un-favorite it when it already is
3087
+ * (`POST /v1/gallery/favorite`). You can favorite your own jobs and public
3088
+ * ones; another person's private job is a `NotFoundError`. OAuth apps need
3089
+ * the `assets:write` scope.
3090
+ */
3091
+ toggleFavorite(jobId) {
3092
+ return this.client.request("POST", "/v1/gallery/favorite", { body: { jobId } });
3093
+ }
3094
+ /**
3095
+ * Your favorited job ids, newest first (`GET /v1/gallery/favorites`). OAuth
3096
+ * apps need the `assets:read` or `jobs:read` scope.
3097
+ */
3098
+ async favorites() {
3099
+ const res = await this.client.request("GET", "/v1/gallery/favorites");
3100
+ return res.data;
3101
+ }
3102
+ };
3103
+
2745
3104
  // src/resources/node-presets.ts
2746
3105
  var PresetsResource = class {
2747
3106
  constructor(client) {
@@ -2777,6 +3136,76 @@ var PresetsResource = class {
2777
3136
  `/v1/node-presets/factory?nodeType=${encodeURIComponent(nodeType)}`
2778
3137
  );
2779
3138
  }
3139
+ /** `POST /v1/node-presets` → the new preset. */
3140
+ async create(input) {
3141
+ const res = await this.client.request("POST", "/v1/node-presets", { body: input });
3142
+ return res.data;
3143
+ }
3144
+ /**
3145
+ * `PATCH /v1/node-presets/:id` → the updated preset. Pass the `updatedAt` you
3146
+ * read as `expectedUpdatedAt` to refuse (409 `conflict`) a change made
3147
+ * elsewhere since.
3148
+ */
3149
+ async update(id, patch, opts = {}) {
3150
+ const body = opts.expectedUpdatedAt ? { ...patch, expectedUpdatedAt: opts.expectedUpdatedAt } : patch;
3151
+ const res = await this.client.request("PATCH", `/v1/node-presets/${encodeURIComponent(id)}`, { body });
3152
+ return res.data;
3153
+ }
3154
+ /** `DELETE /v1/node-presets/:id` (404 when it is not yours). `expectedUpdatedAt` as on `update`. */
3155
+ async delete(id, opts = {}) {
3156
+ const res = await this.client.request("DELETE", `/v1/node-presets/${encodeURIComponent(id)}`, {
3157
+ query: { expectedUpdatedAt: opts.expectedUpdatedAt }
3158
+ });
3159
+ return res.data;
3160
+ }
3161
+ /**
3162
+ * `POST /v1/node-presets/import` — up to 500 presets in one call. A name you
3163
+ * already use gets an "(imported N)" suffix; a preset whose data is empty
3164
+ * after stripping runtime keys is skipped.
3165
+ */
3166
+ async import(presets) {
3167
+ const res = await this.client.request("POST", "/v1/node-presets/import", { body: { presets } });
3168
+ return res.data;
3169
+ }
3170
+ /** `POST /v1/node-presets/reorder` — positions (and group membership) for many presets and groups at once. */
3171
+ async reorder(input) {
3172
+ const res = await this.client.request("POST", "/v1/node-presets/reorder", { body: input });
3173
+ return res.data;
3174
+ }
3175
+ /** `GET /v1/node-presets/favorites` → your favorite preset ids for `nodeType`, newest first. */
3176
+ async favorites(nodeType) {
3177
+ const res = await this.client.request("GET", "/v1/node-presets/favorites", { query: { nodeType } });
3178
+ return res.data;
3179
+ }
3180
+ /** `POST /v1/node-presets/favorites` — idempotent. */
3181
+ async addFavorite(input) {
3182
+ const res = await this.client.request("POST", "/v1/node-presets/favorites", { body: input });
3183
+ return res.data;
3184
+ }
3185
+ /** `DELETE /v1/node-presets/favorites` — idempotent. */
3186
+ async removeFavorite(input) {
3187
+ const res = await this.client.request("DELETE", "/v1/node-presets/favorites", {
3188
+ query: { nodeType: input.nodeType, presetId: input.presetId }
3189
+ });
3190
+ return res.data;
3191
+ }
3192
+ /** `POST /v1/node-preset-groups` → the new folder or section. */
3193
+ async createGroup(input) {
3194
+ const res = await this.client.request("POST", "/v1/node-preset-groups", { body: input });
3195
+ return res.data;
3196
+ }
3197
+ /** `PATCH /v1/node-preset-groups/:id` → the renamed or moved group. */
3198
+ async updateGroup(id, patch) {
3199
+ const res = await this.client.request("PATCH", `/v1/node-preset-groups/${encodeURIComponent(id)}`, {
3200
+ body: patch
3201
+ });
3202
+ return res.data;
3203
+ }
3204
+ /** `DELETE /v1/node-preset-groups/:id` — its presets move out of the group; none are deleted. */
3205
+ async deleteGroup(id) {
3206
+ const res = await this.client.request("DELETE", `/v1/node-preset-groups/${encodeURIComponent(id)}`);
3207
+ return res.data;
3208
+ }
2780
3209
  };
2781
3210
 
2782
3211
  // src/resources/saved-posts.ts
@@ -2917,6 +3346,68 @@ var CollectionsResource = class {
2917
3346
  }
2918
3347
  };
2919
3348
 
3349
+ // src/resources/palettes.ts
3350
+ var PALETTE_DIRECTION_PREFIX = "palette:";
3351
+ function paletteDirectionId(id) {
3352
+ return `${PALETTE_DIRECTION_PREFIX}${id}`;
3353
+ }
3354
+ var PalettesResource = class {
3355
+ constructor(client) {
3356
+ this.client = client;
3357
+ }
3358
+ client;
3359
+ /** Your palettes, newest first. Page with `nextCursor`. */
3360
+ list(params = {}) {
3361
+ return this.client.request("GET", "/v1/palettes", {
3362
+ query: { limit: params.limit, cursor: params.cursor }
3363
+ });
3364
+ }
3365
+ get(id) {
3366
+ return this.client.request("GET", `/v1/palettes/${encodeURIComponent(id)}`);
3367
+ }
3368
+ create(input) {
3369
+ return this.client.request("POST", "/v1/palettes", { body: input });
3370
+ }
3371
+ update(id, input) {
3372
+ return this.client.request("PATCH", `/v1/palettes/${encodeURIComponent(id)}`, { body: input });
3373
+ }
3374
+ /** A run that still names the palette answers 404 `direction_not_found`. */
3375
+ async delete(id) {
3376
+ await this.client.request("DELETE", `/v1/palettes/${encodeURIComponent(id)}`);
3377
+ }
3378
+ };
3379
+
3380
+ // src/resources/moodboards.ts
3381
+ var MOODBOARD_DIRECTION_PREFIX = "moodboard:";
3382
+ function moodboardDirectionId(id) {
3383
+ return `${MOODBOARD_DIRECTION_PREFIX}${id}`;
3384
+ }
3385
+ var MoodboardsResource = class {
3386
+ constructor(client) {
3387
+ this.client = client;
3388
+ }
3389
+ client;
3390
+ /** Your moodboards, newest first. Page with `nextCursor`. */
3391
+ list(params = {}) {
3392
+ return this.client.request("GET", "/v1/moodboards", {
3393
+ query: { limit: params.limit, cursor: params.cursor }
3394
+ });
3395
+ }
3396
+ get(id) {
3397
+ return this.client.request("GET", `/v1/moodboards/${encodeURIComponent(id)}`);
3398
+ }
3399
+ create(input) {
3400
+ return this.client.request("POST", "/v1/moodboards", { body: input });
3401
+ }
3402
+ update(id, input) {
3403
+ return this.client.request("PATCH", `/v1/moodboards/${encodeURIComponent(id)}`, { body: input });
3404
+ }
3405
+ /** Deletes the moodboard only; the images it links to are untouched. */
3406
+ async delete(id) {
3407
+ await this.client.request("DELETE", `/v1/moodboards/${encodeURIComponent(id)}`);
3408
+ }
3409
+ };
3410
+
2920
3411
  // src/resources/competitors.ts
2921
3412
  var CompetitorsResource = class {
2922
3413
  constructor(client) {
@@ -4177,7 +4668,7 @@ var EditResource = class {
4177
4668
  return remapTranscriptThroughEdl(edl, transcript);
4178
4669
  }
4179
4670
  };
4180
- var SDK_VERSION = "2.27.0" ;
4671
+ var SDK_VERSION = "2.29.0" ;
4181
4672
  var CLIENT_HEADER = "X-Nodaro-Client";
4182
4673
  var isBrowser = () => typeof window !== "undefined" && typeof window.document !== "undefined";
4183
4674
  var NodaroClient = class _NodaroClient {
@@ -4200,6 +4691,8 @@ var NodaroClient = class _NodaroClient {
4200
4691
  }
4201
4692
  workflows;
4202
4693
  projects;
4694
+ /** Generation sessions inside projects (Create Image / Video / Music). */
4695
+ sessions;
4203
4696
  jobs;
4204
4697
  videoPro;
4205
4698
  executions;
@@ -4207,6 +4700,8 @@ var NodaroClient = class _NodaroClient {
4207
4700
  scene3d;
4208
4701
  developerApps;
4209
4702
  oauth;
4703
+ /** Outbound webhooks: endpoints that receive your job.completed / job.failed. */
4704
+ webhooks;
4210
4705
  apps;
4211
4706
  characters;
4212
4707
  locations;
@@ -4220,11 +4715,19 @@ var NodaroClient = class _NodaroClient {
4220
4715
  media;
4221
4716
  audio;
4222
4717
  credits;
4718
+ /** Plans and prices, the subscription, and how this deployment bills. */
4719
+ billing;
4223
4720
  uploads;
4224
4721
  library;
4722
+ /** The public gallery and your favorites. */
4723
+ gallery;
4225
4724
  presets;
4226
4725
  savedPosts;
4227
4726
  collections;
4727
+ /** Your colour palettes — a generate-image direction (`direction.colorLook: paletteDirectionId(id)`). */
4728
+ palettes;
4729
+ /** Your moodboards — a generate-image direction (`direction.style: moodboardDirectionId(id)`). */
4730
+ moodboards;
4228
4731
  competitors;
4229
4732
  pickerCatalogs;
4230
4733
  catalogs;
@@ -4251,6 +4754,7 @@ var NodaroClient = class _NodaroClient {
4251
4754
  this.sendClientHeader = opts.clientLabel !== void 0 || !isBrowser();
4252
4755
  this.workflows = new WorkflowsResource(this);
4253
4756
  this.projects = new ProjectsResource(this);
4757
+ this.sessions = new SessionsResource(this);
4254
4758
  this.jobs = new JobsResource(this);
4255
4759
  this.videoPro = new VideoProResource(this);
4256
4760
  this.executions = new ExecutionsResource(this);
@@ -4258,6 +4762,7 @@ var NodaroClient = class _NodaroClient {
4258
4762
  this.scene3d = new Scene3DResource(this);
4259
4763
  this.developerApps = new DeveloperAppsResource(this);
4260
4764
  this.oauth = new OAuthResource(this);
4765
+ this.webhooks = new WebhooksResource(this);
4261
4766
  this.apps = new AppsResource(this);
4262
4767
  this.characters = new CharactersResource(this);
4263
4768
  this.locations = new LocationsResource(this);
@@ -4271,11 +4776,15 @@ var NodaroClient = class _NodaroClient {
4271
4776
  this.media = new MediaResource(this);
4272
4777
  this.audio = new AudioResource(this);
4273
4778
  this.credits = new CreditsResource(this);
4779
+ this.billing = new BillingResource(this);
4274
4780
  this.uploads = new UploadsResource(this);
4275
4781
  this.library = new LibraryResource(this);
4782
+ this.gallery = new GalleryResource(this);
4276
4783
  this.presets = new PresetsResource(this);
4277
4784
  this.savedPosts = new SavedPostsResource(this);
4278
4785
  this.collections = new CollectionsResource(this);
4786
+ this.palettes = new PalettesResource(this);
4787
+ this.moodboards = new MoodboardsResource(this);
4279
4788
  this.competitors = new CompetitorsResource(this);
4280
4789
  this.pickerCatalogs = new PickerCatalogsResource(this);
4281
4790
  this.catalogs = new CatalogsResource(this);
@@ -4400,6 +4909,32 @@ var NodaroClient = class _NodaroClient {
4400
4909
  const res = await this.request("GET", "/v1/me");
4401
4910
  return res.data;
4402
4911
  }
4912
+ /**
4913
+ * `GET /v1/me/connected-apps` → every app with access to the signed-in
4914
+ * user's account (see {@link ConnectedApp}), newest grant first.
4915
+ *
4916
+ * **A signed-in browser session only.** The route answers a Supabase
4917
+ * session token (`supabaseAuth(…)`, `createSharedSupabaseClient`, or a
4918
+ * `StaticTokenAuth` holding one) and refuses every other credential with
4919
+ * `UnauthorizedError` ("Sign in required"): an app token or an API key must
4920
+ * not list the grants it lives under. Build your "Connected apps" settings
4921
+ * screen on this; a server-side integration cannot call it.
4922
+ */
4923
+ async connectedApps() {
4924
+ const res = await this.request("GET", "/v1/me/connected-apps");
4925
+ return res.apps;
4926
+ }
4927
+ /**
4928
+ * `POST /v1/me/connected-apps/:authorizationId/revoke` — ends an app's
4929
+ * access: the grant and every token issued under it, at once (the app's next
4930
+ * call is a 401). Resolves when done.
4931
+ *
4932
+ * A signed-in browser session only, like {@link connectedApps}. Throws
4933
+ * `NotFoundError` when the grant is not the user's or is already revoked.
4934
+ */
4935
+ async revokeConnectedApp(authorizationId) {
4936
+ await this.request("POST", `/v1/me/connected-apps/${encodeURIComponent(authorizationId)}/revoke`);
4937
+ }
4403
4938
  buildUrl(path2, query) {
4404
4939
  const base = this.baseUrl || (typeof window !== "undefined" ? window.location.origin : "http://placeholder");
4405
4940
  const url = new URL(path2, base);
@@ -4446,6 +4981,96 @@ function supabaseAuth(supabase) {
4446
4981
  };
4447
4982
  }
4448
4983
 
4449
- export { AppsResource, AudioResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CollectionsResource, CommunityResource, CompetitorsResource, ContinuationRefusedError, CopilotResource, CreaturesResource, CreditsResource, DeveloperAppsResource, EditResource, 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, SCENE3D_DELIVERY_ASSET_USAGE, SavedPostsResource, Scene3DResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, supabaseAuth, throwFromResponse };
4984
+ // src/webhook-signature.ts
4985
+ var WebhookSignatureError = class extends Error {
4986
+ code;
4987
+ constructor(code, message) {
4988
+ super(message);
4989
+ this.name = "WebhookSignatureError";
4990
+ this.code = code;
4991
+ }
4992
+ };
4993
+ var DEFAULT_TOLERANCE_SECONDS = 300;
4994
+ var HEX_SIGNATURE = /^[0-9a-f]{64}$/;
4995
+ function toBytes(payload) {
4996
+ if (typeof payload === "string") return new TextEncoder().encode(payload);
4997
+ if (payload instanceof Uint8Array) return payload;
4998
+ return new Uint8Array(payload);
4999
+ }
5000
+ function hexToBytes(hex) {
5001
+ const out = new Uint8Array(hex.length / 2);
5002
+ for (let i = 0; i < out.length; i++) out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
5003
+ return out;
5004
+ }
5005
+ function constantTimeEqual(a, b) {
5006
+ if (a.length !== b.length) return false;
5007
+ let diff = 0;
5008
+ for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
5009
+ return diff === 0;
5010
+ }
5011
+ function parseHeader(raw) {
5012
+ let timestamp = null;
5013
+ const signatures = [];
5014
+ for (const part of raw.split(",")) {
5015
+ const eq = part.indexOf("=");
5016
+ if (eq <= 0) continue;
5017
+ const key = part.slice(0, eq).trim();
5018
+ const value = part.slice(eq + 1).trim();
5019
+ if (key === "t") {
5020
+ if (!/^\d{1,15}$/.test(value)) {
5021
+ throw new WebhookSignatureError("malformed_header", "Nodaro-Signature has no valid timestamp (t=)");
5022
+ }
5023
+ timestamp = Number(value);
5024
+ } else if (key === "v1") {
5025
+ signatures.push(value.toLowerCase());
5026
+ }
5027
+ }
5028
+ if (timestamp === null) throw new WebhookSignatureError("malformed_header", "Nodaro-Signature has no timestamp (t=)");
5029
+ if (signatures.length === 0) throw new WebhookSignatureError("malformed_header", "Nodaro-Signature has no v1 signature");
5030
+ return { timestamp, signatures };
5031
+ }
5032
+ async function verifyWebhookSignature(options) {
5033
+ const { payload, secret } = options;
5034
+ const tolerance = options.toleranceSeconds ?? DEFAULT_TOLERANCE_SECONDS;
5035
+ if (typeof tolerance !== "number" || !Number.isFinite(tolerance) || tolerance < 0) {
5036
+ throw new RangeError("toleranceSeconds must be a finite number of seconds, 0 or more");
5037
+ }
5038
+ if (!secret) throw new WebhookSignatureError("missing_secret", "No signing secret was given");
5039
+ const header = typeof options.header === "string" ? options.header : options.header?.[0];
5040
+ if (!header || !header.trim()) throw new WebhookSignatureError("missing_header", "The request has no Nodaro-Signature header");
5041
+ const { timestamp, signatures } = parseHeader(header);
5042
+ const subtle = globalThis.crypto?.subtle;
5043
+ if (!subtle) throw new WebhookSignatureError("crypto_unavailable", "Web Crypto (crypto.subtle) is not available in this runtime");
5044
+ const body = toBytes(payload);
5045
+ const prefix = new TextEncoder().encode(`${timestamp}.`);
5046
+ const message = new Uint8Array(prefix.length + body.length);
5047
+ message.set(prefix, 0);
5048
+ message.set(body, prefix.length);
5049
+ const key = await subtle.importKey("raw", new TextEncoder().encode(secret), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
5050
+ const expected = new Uint8Array(await subtle.sign("HMAC", key, message));
5051
+ let matched = false;
5052
+ for (const candidate of signatures) {
5053
+ const wellFormed = HEX_SIGNATURE.test(candidate);
5054
+ const bytes = wellFormed ? hexToBytes(candidate) : new Uint8Array(expected.length);
5055
+ if (constantTimeEqual(bytes, expected) && wellFormed) matched = true;
5056
+ }
5057
+ if (!matched) throw new WebhookSignatureError("signature_mismatch", "The Nodaro-Signature does not match the body");
5058
+ if (tolerance > 0) {
5059
+ const now = Math.floor(Date.now() / 1e3);
5060
+ if (Math.abs(now - timestamp) > tolerance) {
5061
+ throw new WebhookSignatureError(
5062
+ "timestamp_outside_tolerance",
5063
+ `The signature's timestamp is more than ${tolerance} seconds from now`
5064
+ );
5065
+ }
5066
+ }
5067
+ try {
5068
+ return JSON.parse(new TextDecoder().decode(body));
5069
+ } catch {
5070
+ throw new WebhookSignatureError("invalid_payload", "The signed body is not JSON");
5071
+ }
5072
+ }
5073
+
5074
+ export { AppsResource, AudioResource, BillingResource, CREATURE_ASSET_TYPES, CallbackAuth, CatalogsResource, CharactersResource, CollectionsResource, CommunityResource, CompetitorsResource, ContinuationRefusedError, CopilotResource, CreaturesResource, CreditsResource, DeveloperAppsResource, EditResource, ExecutionsResource, ForbiddenError, GalleryResource, InsufficientCreditsError, JobAbortedError, JobBlockedError, JobFailedError, JobHeldError, JobTimeoutError, JobsResource, LibraryResource, LlmResource, LocationsResource, MOODBOARD_DIRECTION_PREFIX, MediaResource, ModelsResource, MoodboardsResource, NodaroClient, NodaroError, NodesResource, NotFoundError, OAuthResource, ObjectsResource, OrganizationsResource, PALETTE_DIRECTION_PREFIX, PalettesResource, PickerCatalogsResource, PipelinesResource, PresetsResource, ProjectsResource, PromptHelperResource, RateLimitedError, RecastResource, ReduceResource, SCENE3D_DELIVERY_ASSET_USAGE, SavedPostsResource, Scene3DResource, SessionsResource, ShotsResource, StaticTokenAuth, StorageExceededError, StudioOpError, StudioPreviewAppliedError, StudioPreviewUnavailable, StudioProductionsResource, StudioResource, TemplatesResource, TutorialsResource, UnauthorizedError, UploadsResource, VideoProResource, VoicesResource, WebhookSignatureError, WebhooksResource, WorkflowConflictError, WorkflowsResource, WorkspacesResource, buildPersonSeedPrompt, createClient, isStudioGenerateEstimate, moodboardDirectionId, paletteDirectionId, supabaseAuth, throwFromResponse, verifyWebhookSignature };
4450
5075
  //# sourceMappingURL=index.js.map
4451
5076
  //# sourceMappingURL=index.js.map