@nodaro/sdk 2.55.0 → 2.57.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.
Files changed (97) hide show
  1. package/dist/{chunk-XALPYUZI.cjs → chunk-3Y5TDB5K.cjs} +4 -4
  2. package/dist/{chunk-XALPYUZI.cjs.map → chunk-3Y5TDB5K.cjs.map} +1 -1
  3. package/dist/{chunk-DV6GTEX5.js → chunk-4SZUSZXK.js} +2 -2
  4. package/dist/{chunk-DV6GTEX5.js.map → chunk-4SZUSZXK.js.map} +1 -1
  5. package/dist/{chunk-HRV3VX22.cjs → chunk-7PYZCNLH.cjs} +5 -5
  6. package/dist/{chunk-HRV3VX22.cjs.map → chunk-7PYZCNLH.cjs.map} +1 -1
  7. package/dist/{chunk-47ULSVO2.js → chunk-ALDXFMD7.js} +3 -3
  8. package/dist/chunk-ALDXFMD7.js.map +1 -0
  9. package/dist/{chunk-SF2CMKWA.cjs → chunk-DOMNKVKA.cjs} +9 -9
  10. package/dist/{chunk-SF2CMKWA.cjs.map → chunk-DOMNKVKA.cjs.map} +1 -1
  11. package/dist/{chunk-WY4QRJZW.js → chunk-DTYN7QAZ.js} +25 -2
  12. package/dist/chunk-DTYN7QAZ.js.map +1 -0
  13. package/dist/{chunk-LUHAB7UJ.js → chunk-EDSODRRY.js} +10 -10
  14. package/dist/{chunk-LUHAB7UJ.js.map → chunk-EDSODRRY.js.map} +1 -1
  15. package/dist/{chunk-OSMKIRKI.cjs → chunk-GDUEOKBF.cjs} +4 -4
  16. package/dist/{chunk-OSMKIRKI.cjs.map → chunk-GDUEOKBF.cjs.map} +1 -1
  17. package/dist/{chunk-65VIIZEF.cjs → chunk-GJH73EGF.cjs} +2 -2
  18. package/dist/{chunk-65VIIZEF.cjs.map → chunk-GJH73EGF.cjs.map} +1 -1
  19. package/dist/{chunk-FM2KM5TY.cjs → chunk-GSE7SB3I.cjs} +25 -6
  20. package/dist/chunk-GSE7SB3I.cjs.map +1 -0
  21. package/dist/{chunk-VHTDOACT.cjs → chunk-GWTKYJJO.cjs} +22 -22
  22. package/dist/chunk-GWTKYJJO.cjs.map +1 -0
  23. package/dist/{chunk-L6T44A3G.js → chunk-JJMQ2EVL.js} +24 -7
  24. package/dist/chunk-JJMQ2EVL.js.map +1 -0
  25. package/dist/{chunk-I6Q4UDS2.cjs → chunk-JX3GYLV3.cjs} +18 -18
  26. package/dist/{chunk-I6Q4UDS2.cjs.map → chunk-JX3GYLV3.cjs.map} +1 -1
  27. package/dist/{chunk-FRQJNGJS.cjs → chunk-KU3UITCU.cjs} +5 -5
  28. package/dist/{chunk-FRQJNGJS.cjs.map → chunk-KU3UITCU.cjs.map} +1 -1
  29. package/dist/{chunk-RBX3QTKB.js → chunk-MUHRK4OI.js} +3 -3
  30. package/dist/{chunk-RBX3QTKB.js.map → chunk-MUHRK4OI.js.map} +1 -1
  31. package/dist/{chunk-24JE54FQ.js → chunk-ND7JMM5H.js} +3 -3
  32. package/dist/{chunk-24JE54FQ.js.map → chunk-ND7JMM5H.js.map} +1 -1
  33. package/dist/{chunk-JTOEHQQJ.cjs → chunk-NOZWIS7M.cjs} +25 -2
  34. package/dist/chunk-NOZWIS7M.cjs.map +1 -0
  35. package/dist/{chunk-D2ILCSOQ.js → chunk-RCD4HDBI.js} +3 -3
  36. package/dist/{chunk-D2ILCSOQ.js.map → chunk-RCD4HDBI.js.map} +1 -1
  37. package/dist/{chunk-CV2ZZAUO.js → chunk-SOR6K3XZ.js} +4 -4
  38. package/dist/{chunk-CV2ZZAUO.js.map → chunk-SOR6K3XZ.js.map} +1 -1
  39. package/dist/{chunk-NKH2UFSD.cjs → chunk-TSM3S2QS.cjs} +5 -5
  40. package/dist/{chunk-NKH2UFSD.cjs.map → chunk-TSM3S2QS.cjs.map} +1 -1
  41. package/dist/{chunk-AUKHMT53.js → chunk-VTL4DBX4.js} +3 -3
  42. package/dist/{chunk-AUKHMT53.js.map → chunk-VTL4DBX4.js.map} +1 -1
  43. package/dist/{chunk-7CUWAVWB.js → chunk-YYMX3VN7.js} +3 -3
  44. package/dist/{chunk-7CUWAVWB.js.map → chunk-YYMX3VN7.js.map} +1 -1
  45. package/dist/entries/cast-swap.cjs +2 -2
  46. package/dist/entries/cast-swap.d.cts +12 -0
  47. package/dist/entries/cast-swap.d.ts +12 -0
  48. package/dist/entries/cast-swap.js +1 -1
  49. package/dist/entries/characters.d.cts +1 -1
  50. package/dist/entries/characters.d.ts +1 -1
  51. package/dist/entries/client.cjs +16 -16
  52. package/dist/entries/client.d.cts +1 -1
  53. package/dist/entries/client.d.ts +1 -1
  54. package/dist/entries/client.js +11 -11
  55. package/dist/entries/copilot.cjs +4 -4
  56. package/dist/entries/copilot.js +3 -3
  57. package/dist/entries/core.cjs +6 -6
  58. package/dist/entries/core.js +2 -2
  59. package/dist/entries/creatures.d.cts +1 -1
  60. package/dist/entries/creatures.d.ts +1 -1
  61. package/dist/entries/edit.cjs +7 -7
  62. package/dist/entries/edit.js +2 -2
  63. package/dist/entries/errors.cjs +32 -24
  64. package/dist/entries/errors.d.cts +38 -3
  65. package/dist/entries/errors.d.ts +38 -3
  66. package/dist/entries/errors.js +1 -1
  67. package/dist/entries/locations.d.cts +1 -1
  68. package/dist/entries/locations.d.ts +1 -1
  69. package/dist/entries/media.cjs +4 -4
  70. package/dist/entries/media.js +3 -3
  71. package/dist/entries/nodes.cjs +3 -3
  72. package/dist/entries/nodes.d.cts +1 -1
  73. package/dist/entries/nodes.d.ts +1 -1
  74. package/dist/entries/nodes.js +2 -2
  75. package/dist/entries/objects.d.cts +1 -1
  76. package/dist/entries/objects.d.ts +1 -1
  77. package/dist/entries/scene3d.d.cts +2 -2
  78. package/dist/entries/scene3d.d.ts +2 -2
  79. package/dist/entries/studio.cjs +5 -5
  80. package/dist/entries/studio.js +2 -2
  81. package/dist/entries/uploads.cjs +2 -2
  82. package/dist/entries/uploads.d.cts +41 -1
  83. package/dist/entries/uploads.d.ts +41 -1
  84. package/dist/entries/uploads.js +1 -1
  85. package/dist/index.cjs +61 -53
  86. package/dist/index.d.cts +3 -3
  87. package/dist/index.d.ts +3 -3
  88. package/dist/index.js +11 -11
  89. package/dist/{nodes-B74WaY9r.d.ts → nodes-1u7MPrD5.d.ts} +10 -0
  90. package/dist/{nodes-Ceetyyh0.d.cts → nodes-BZavad1T.d.cts} +10 -0
  91. package/package.json +1 -1
  92. package/dist/chunk-47ULSVO2.js.map +0 -1
  93. package/dist/chunk-FM2KM5TY.cjs.map +0 -1
  94. package/dist/chunk-JTOEHQQJ.cjs.map +0 -1
  95. package/dist/chunk-L6T44A3G.js.map +0 -1
  96. package/dist/chunk-VHTDOACT.cjs.map +0 -1
  97. package/dist/chunk-WY4QRJZW.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/resources/uploads.ts"],"names":[],"mappings":";AA4BO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUpB,MAAM,OAAO,IAAA,EAAmC;AAC9C,IAAA,MAAM,IAAA,GAAO,IAAI,QAAA,EAAS;AAC1B,IAAA,IAAA,CAAK,MAAA,CAAO,QAAQ,IAAI,CAAA;AACxB,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA;AAAA,MAC5B,MAAA;AAAA,MACA,YAAA;AAAA,MACA,EAAE,MAAM,IAAA;AAAK,KACf;AACA,IAAA,OAAO,GAAA,CAAI,IAAA;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,MAAM,UAAU,GAAA,EAAuC;AACrD,IAAA,MAAM,MAAM,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAAmC,QAAQ,sBAAA,EAAwB;AAAA,MAC/F,IAAA,EAAM,EAAE,GAAA;AAAI,KACb,CAAA;AACD,IAAA,OAAO,GAAA,CAAI,IAAA;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,WAAW,IAAA,EAA+E;AACxF,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA0B,MAAA,EAAQ,mBAAmB,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,EACxF;AACF","file":"chunk-DTYN7QAZ.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Result of a successful `POST /v1/upload`. Mirrors the route's `data` envelope\n * (`backend/src/routes/upload.ts`), the source of truth — keep in sync if that\n * response changes. The route also returns loosely-typed extracted `metadata`;\n * it is omitted here until a consumer needs a typed shape (add it shaped to\n * that need rather than inventing `Record<string, unknown>` surface now).\n */\nexport interface UploadResult {\n /** Public R2 URL of the stored asset (always present on success). */\n readonly url: string\n /** Storage row id; `null` when no asset row was written (e.g. unauthenticated). */\n readonly assetId: string | null\n /** Generated thumbnail URL (images/video); `null` for audio or on failure. */\n readonly thumbnailUrl: string | null\n /** Server-classified asset category (e.g. \"image\" | \"video\" | \"audio\"). */\n readonly category: string\n /** Display filename (server override or the original). */\n readonly filename: string\n /** Final MIME type after server normalization. */\n readonly mimeType: string\n /** Stored byte size. */\n readonly sizeBytes: number\n /** R2 object key. */\n readonly r2Key: string\n}\n\nexport class UploadsResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Upload one file (`POST /v1/upload`, multipart — the file rides the `file`\n * field). The SDK's `request` detects the `FormData` body and lets the\n * runtime set the multipart boundary. Returns the persisted asset's public\n * URL + storage metadata (unwraps the `{ data }` envelope). Throws\n * `StorageExceededError` (413) over the storage cap and the SDK's other typed\n * errors on the usual statuses.\n */\n async upload(file: File): Promise<UploadResult> {\n const form = new FormData()\n form.append(\"file\", file)\n const res = await this.client.request<{ data: UploadResult }>(\n \"POST\",\n \"/v1/upload\",\n { body: form },\n )\n return res.data\n }\n\n /**\n * Copy a picture from a web address into your storage\n * (`POST /v1/media/import-url`, body `{ url }`). The platform fetches it\n * (http(s) only, never a private address, up to 20 MB), keeps it only if it\n * decodes as an image (JPEG, PNG, WebP, GIF; HEIC/HEIF and AVIF are\n * converted to JPEG or PNG), and stores it as an upload of yours, so its address serves\n * the pixels to the browser (a canvas can read it). Returns the stored\n * picture (unwraps the `{ data }` envelope).\n *\n * Throws `StorageExceededError` on a 413, its `reason` telling the two\n * apart: `storage_limit_exceeded` is a full storage (the quota is in\n * `details` — `usedBytes`, `quotaBytes`, `remainingBytes`, `tier`), and\n * `file_too_large` a picture over 20 MB. Throws a `NodaroError` with `code`\n * `validation_error` (400: not an http(s) address, or not an image) or\n * `fetch_failed` (422: the address could not be reached or answered with an\n * error).\n */\n async importUrl(url: string): Promise<ImportUrlResult> {\n const res = await this.client.request<{ data: ImportUrlResult }>(\"POST\", \"/v1/media/import-url\", {\n body: { url },\n })\n return res.data\n }\n\n /**\n * Store a JSON document (`POST /v1/upload-json`, up to 25 MB) and get its\n * public URL — e.g. an image editor's design state, passed to\n * `client.jobs.fromUpload` as `editStateUrl` so the edit can be reopened.\n * The URL is unguessable but public: never store a secret in it. Creates no\n * library item.\n */\n uploadJson(json: Record<string, unknown> | readonly unknown[]): Promise<UploadJsonResult> {\n return this.client.request<UploadJsonResult>(\"POST\", \"/v1/upload-json\", { body: json })\n }\n}\n\n/** Result of {@link UploadsResource.uploadJson}. */\nexport interface UploadJsonResult {\n /** Public URL of the stored JSON document. */\n readonly url: string\n}\n\n/**\n * Result of {@link UploadsResource.importUrl}. Mirrors the route's `data`:\n * the fields of {@link UploadResult} it shares, plus the picture's size.\n */\nexport interface ImportUrlResult {\n /** Public URL of the stored picture. */\n readonly url: string\n /** Generated thumbnail URL; `null` when it could not be made. */\n readonly thumbnailUrl: string | null\n /** Storage row id; `null` when no asset row was written. */\n readonly assetId: string | null\n /** Final MIME type (a HEIC/HEIF or AVIF source is stored as JPEG or PNG). */\n readonly mimeType: string\n /** Stored byte size. */\n readonly sizeBytes: number\n /** Display filename: the address's last path segment, else `imported-<id>.<ext>`. */\n readonly filename: string\n /** Width in pixels; 0 when it could not be read. */\n readonly width: number\n /** Height in pixels; 0 when it could not be read. */\n readonly height: number\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { TutorialsResource } from './chunk-HPXE3NZW.js';
2
- import { UploadsResource } from './chunk-WY4QRJZW.js';
2
+ import { UploadsResource } from './chunk-DTYN7QAZ.js';
3
3
  import { UserSettingsResource } from './chunk-LR5TGCJP.js';
4
4
  import { VideoProResource } from './chunk-ERLXU47J.js';
5
5
  import { VoicesResource } from './chunk-T7N7DFQJ.js';
@@ -10,7 +10,7 @@ import { SavedPostsResource } from './chunk-NCCBS6GU.js';
10
10
  import { Scene3DResource } from './chunk-NNHWH7ER.js';
11
11
  import { SessionsResource } from './chunk-WS4ZQ4AA.js';
12
12
  import { ShotsResource } from './chunk-WVFAQBS7.js';
13
- import { StudioResource } from './chunk-AUKHMT53.js';
13
+ import { StudioResource } from './chunk-VTL4DBX4.js';
14
14
  import { TemplatesResource } from './chunk-M7VSFZMV.js';
15
15
  import { TrashResource } from './chunk-2SQ7V6EX.js';
16
16
  import { TrendsResource } from './chunk-HFYNZ4SO.js';
@@ -23,14 +23,14 @@ import { PromptHelperResource } from './chunk-OIPPTBW4.js';
23
23
  import { RecastResource } from './chunk-AJVSMNPZ.js';
24
24
  import { ReduceResource } from './chunk-IHKIYVZQ.js';
25
25
  import { LocationsResource } from './chunk-XZPSJG2X.js';
26
- import { MediaResource } from './chunk-24JE54FQ.js';
26
+ import { MediaResource } from './chunk-ND7JMM5H.js';
27
27
  import { ModelsResource } from './chunk-Y6V6CBY5.js';
28
28
  import { MoodboardsResource } from './chunk-YVU2M7MI.js';
29
29
  import { PresetsResource } from './chunk-AEUPH7EE.js';
30
- import { NodesResource } from './chunk-47ULSVO2.js';
30
+ import { NodesResource } from './chunk-ALDXFMD7.js';
31
31
  import { OAuthResource } from './chunk-Z7LGWNI7.js';
32
32
  import { ObjectsResource } from './chunk-GIQDM2MH.js';
33
- import { EditResource } from './chunk-RBX3QTKB.js';
33
+ import { EditResource } from './chunk-MUHRK4OI.js';
34
34
  import { ExecutionsResource } from './chunk-Z3ZKFI2M.js';
35
35
  import { GalleryResource } from './chunk-JDEZHITT.js';
36
36
  import { JobsResource } from './chunk-HJLSOT5C.js';
@@ -40,15 +40,15 @@ import { LlmResource } from './chunk-E37CVHWW.js';
40
40
  import { CollectionsResource } from './chunk-4WRDR4GN.js';
41
41
  import { CommunityResource } from './chunk-SFB4YLCS.js';
42
42
  import { CompetitorsResource } from './chunk-BU5A6K4C.js';
43
- import { CopilotResource } from './chunk-D2ILCSOQ.js';
44
- import { NodaroClientCore } from './chunk-CV2ZZAUO.js';
43
+ import { CopilotResource } from './chunk-RCD4HDBI.js';
44
+ import { NodaroClientCore } from './chunk-SOR6K3XZ.js';
45
45
  import { CreaturesResource } from './chunk-HUYI5G3D.js';
46
46
  import { CreditsResource } from './chunk-7QK2NXJA.js';
47
47
  import { DeveloperAppsResource } from './chunk-65E3JBFZ.js';
48
48
  import { AppsResource } from './chunk-7LODCIQK.js';
49
49
  import { AudioResource } from './chunk-3QFTP5P5.js';
50
50
  import { BillingResource } from './chunk-ZVKEPVDQ.js';
51
- import { CastSwapResource } from './chunk-DV6GTEX5.js';
51
+ import { CastSwapResource } from './chunk-4SZUSZXK.js';
52
52
  import { CatalogsResource } from './chunk-KG4R454Z.js';
53
53
  import { CharactersResource } from './chunk-CBDUHYTR.js';
54
54
 
@@ -200,5 +200,5 @@ function createClient(opts) {
200
200
  }
201
201
 
202
202
  export { NodaroClient, createClient };
203
- //# sourceMappingURL=chunk-LUHAB7UJ.js.map
204
- //# sourceMappingURL=chunk-LUHAB7UJ.js.map
203
+ //# sourceMappingURL=chunk-EDSODRRY.js.map
204
+ //# sourceMappingURL=chunk-EDSODRRY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,gBAAA,CAAiB;AAAA,EACxC,SAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,KAAA;AAAA,EACA,IAAA;AAAA,EACA,QAAA;AAAA,EACA,UAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA,EACA,aAAA;AAAA,EACA,KAAA;AAAA;AAAA,EAEA,QAAA;AAAA,EACA,IAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,MAAA;AAAA,EACA,YAAA;AAAA,EACA,MAAA;AAAA,EACA,GAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,OAAA;AAAA;AAAA,EAEA,YAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA;AAAA,EAEA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA,WAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,UAAA;AAAA,EACA,WAAA;AAAA,EACA,cAAA;AAAA,EACA,QAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,MAAA;AAAA;AAAA,EAEA,QAAA;AAAA;AAAA,EAEA,MAAA;AAAA,EACA,MAAA;AAAA,EACA,OAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,SAAA;AAAA,EACA,aAAA;AAAA,EACA,UAAA;AAAA,EACA,IAAA;AAAA,EAET,YAAY,IAAA,EAAqB;AAC/B,IAAA,KAAA,CAAM,IAAI,CAAA;AAEV,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AACjC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,kBAAA,CAAmB,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAI,qBAAA,CAAsB,IAAI,CAAA;AACnD,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AACjC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,kBAAA,CAAmB,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,oBAAA,CAAqB,IAAI,CAAA;AACjD,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,GAAA,GAAM,IAAI,WAAA,CAAY,IAAI,CAAA;AAC/B,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,YAAA,GAAe,IAAI,oBAAA,CAAqB,IAAI,CAAA;AACjD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,kBAAA,CAAmB,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,mBAAA,CAAoB,IAAI,CAAA;AAC/C,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,kBAAA,CAAmB,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,mBAAA,CAAoB,IAAI,CAAA;AAC/C,IAAA,IAAA,CAAK,cAAA,GAAiB,IAAI,sBAAA,CAAuB,IAAI,CAAA;AACrD,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,KAAA,GAAQ,IAAI,aAAA,CAAc,IAAI,CAAA;AACnC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,QAAA,GAAW,IAAI,gBAAA,CAAiB,IAAI,CAAA;AACzC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,IAAI,CAAA;AACrC,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,IAAI,CAAA;AACvC,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,aAAA,GAAgB,IAAI,qBAAA,CAAsB,IAAI,CAAA;AACnD,IAAA,IAAA,CAAK,UAAA,GAAa,IAAI,kBAAA,CAAmB,IAAI,CAAA;AAC7C,IAAA,IAAA,CAAK,IAAA,GAAO,IAAI,YAAA,CAAa,IAAI,CAAA;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,cAAc,WAAA,EAA0C;AAMtD,IAAA,MAAM,aAAA,GAAgB,KAAK,eAAe,CAAA;AAC1C,IAAA,OAAO,IAAI,aAAA,CAAa;AAAA,MACtB,SAAS,IAAA,CAAK,OAAA;AAAA,MACd,MAAM,IAAA,CAAK,IAAA;AAAA,MACX,WAAW,IAAA,CAAK,SAAA;AAAA,MAChB,GAAI,aAAA,GAAgB,EAAE,KAAA,EAAO,aAAA,KAAkB,EAAC;AAAA,MAChD,GAAI,KAAK,kBAAkB,CAAA,GAAI,EAAE,WAAA,EAAa,IAAA,CAAK,WAAA,EAAY,GAAI,EAAC;AAAA,MACpE,GAAI,WAAA,GAAc,EAAE,WAAA,KAAgB;AAAC,KACtC,CAAA;AAAA,EACH;AACF;AAGO,SAAS,aAAa,IAAA,EAAmC;AAC9D,EAAA,OAAO,IAAI,aAAa,IAAI,CAAA;AAC9B","file":"chunk-LUHAB7UJ.js","sourcesContent":["import { WorkflowsResource } from \"./resources/workflows.js\"\nimport { ProjectsResource } from \"./resources/projects.js\"\nimport { SessionsResource } from \"./resources/sessions.js\"\nimport { TrashResource } from \"./resources/trash.js\"\nimport { JobsResource } from \"./resources/jobs.js\"\nimport { VideoProResource } from \"./resources/video-pro.js\"\nimport { ExecutionsResource } from \"./resources/executions.js\"\nimport { NodesResource } from \"./resources/nodes.js\"\nimport { Scene3DResource } from \"./resources/scene3d.js\"\nimport { DeveloperAppsResource } from \"./resources/developer-apps.js\"\nimport { OAuthResource } from \"./resources/oauth.js\"\nimport { WebhooksResource } from \"./resources/webhooks.js\"\nimport { AppsResource } from \"./resources/apps.js\"\nimport { CharactersResource } from \"./resources/characters.js\"\nimport { LocationsResource } from \"./resources/locations.js\"\nimport { ObjectsResource } from \"./resources/objects.js\"\nimport { CreaturesResource } from \"./resources/creatures.js\"\nimport { KeepersResource } from \"./resources/keepers.js\"\nimport { PipelinesResource } from \"./resources/pipelines.js\"\nimport { ReduceResource } from \"./resources/reduce.js\"\nimport { PromptHelperResource } from \"./resources/prompt-helper.js\"\nimport { VoicesResource } from \"./resources/voices.js\"\nimport { LlmResource } from \"./resources/llm.js\"\nimport { MediaResource } from \"./resources/media.js\"\nimport { AudioResource } from \"./resources/audio.js\"\nimport { CreditsResource } from \"./resources/credits.js\"\nimport { BillingResource } from \"./resources/billing.js\"\nimport { UserSettingsResource } from \"./resources/user-settings.js\"\nimport { UploadsResource } from \"./resources/uploads.js\"\nimport { LibraryResource } from \"./resources/library.js\"\nimport { GalleryResource } from \"./resources/gallery.js\"\nimport { PresetsResource } from \"./resources/node-presets.js\"\nimport { SavedPostsResource } from \"./resources/saved-posts.js\"\nimport { CollectionsResource } from \"./resources/collections.js\"\nimport { PalettesResource } from \"./resources/palettes.js\"\nimport { MoodboardsResource } from \"./resources/moodboards.js\"\nimport { CompetitorsResource } from \"./resources/competitors.js\"\nimport { PickerCatalogsResource } from \"./resources/picker-catalogs.js\"\nimport { CatalogsResource } from \"./resources/catalogs.js\"\nimport { ModelsResource } from \"./resources/models.js\"\nimport { ShotsResource } from \"./resources/shots.js\"\nimport { RecastResource } from \"./resources/recast.js\"\nimport { CastSwapResource } from \"./resources/cast-swap.js\"\nimport { TrendsResource } from \"./resources/trends.js\"\nimport { StudioResource } from \"./resources/studio.js\"\nimport { CopilotResource } from \"./resources/copilot.js\"\nimport { CommunityResource } from \"./resources/community.js\"\nimport { TemplatesResource } from \"./resources/templates.js\"\nimport { TutorialsResource } from \"./resources/tutorials.js\"\nimport { OrganizationsResource } from \"./resources/organizations.js\"\nimport { WorkspacesResource } from \"./resources/workspaces.js\"\nimport { EditResource } from \"./resources/edit.js\"\nimport { NodaroClientCore, type ClientOptions } from \"./core.js\"\n\nexport { CLIENT_HEADER } from \"./core.js\"\nexport type { ClientOptions, UserIdentity, ConnectedApp } from \"./core.js\"\n\n/**\n * The full client: the core (`./core.ts` — config, transport, identity) and\n * every resource.\n */\nexport class NodaroClient extends NodaroClientCore {\n readonly workflows: WorkflowsResource\n readonly projects: ProjectsResource\n /** Generation sessions inside projects (Create Image / Video / Music). */\n readonly sessions: SessionsResource\n /** Your Trash: items removed from sessions and deleted jobs. */\n readonly trash: TrashResource\n readonly jobs: JobsResource\n readonly videoPro: VideoProResource\n readonly executions: ExecutionsResource\n readonly nodes: NodesResource\n readonly scene3d: Scene3DResource\n readonly developerApps: DeveloperAppsResource\n readonly oauth: OAuthResource\n /** Outbound webhooks: endpoints that receive your job.completed / job.failed. */\n readonly webhooks: WebhooksResource\n readonly apps: AppsResource\n readonly characters: CharactersResource\n readonly locations: LocationsResource\n readonly objects: ObjectsResource\n readonly creatures: CreaturesResource\n /** The shared Nodaro Keepers catalog of characters, creatures, locations and objects. */\n readonly keepers: KeepersResource\n readonly pipelines: PipelinesResource\n readonly reduce: ReduceResource\n readonly promptHelper: PromptHelperResource\n readonly voices: VoicesResource\n readonly llm: LlmResource\n readonly media: MediaResource\n readonly audio: AudioResource\n readonly credits: CreditsResource\n /** The signed-in person's own settings (the interface language, the monthly statement opt-in, …). */\n readonly userSettings: UserSettingsResource\n /** Plans and prices, the subscription, and how this deployment bills. */\n readonly billing: BillingResource\n readonly uploads: UploadsResource\n readonly library: LibraryResource\n /** The public gallery and your favorites. */\n readonly gallery: GalleryResource\n readonly presets: PresetsResource\n readonly savedPosts: SavedPostsResource\n readonly collections: CollectionsResource\n /** Your colour palettes — a generate-image direction (`direction.colorLook: paletteDirectionId(id)`). */\n readonly palettes: PalettesResource\n /** Your moodboards — a generate-image direction (`direction.style: moodboardDirectionId(id)`). */\n readonly moodboards: MoodboardsResource\n readonly competitors: CompetitorsResource\n readonly pickerCatalogs: PickerCatalogsResource\n readonly catalogs: CatalogsResource\n readonly models: ModelsResource\n readonly shots: ShotsResource\n readonly recast: RecastResource\n /** Cast Swap: replace the people and/or location in a short video (Cloud). */\n readonly castSwap: CastSwapResource\n /** Trends: ready-made Cast Swap recipes you fill with your own pictures (Cloud). */\n readonly trends: TrendsResource\n readonly studio: StudioResource\n readonly copilot: CopilotResource\n readonly community: CommunityResource\n readonly templates: TemplatesResource\n readonly tutorials: TutorialsResource\n readonly organizations: OrganizationsResource\n readonly workspaces: WorkspacesResource\n readonly edit: EditResource\n\n constructor(opts: ClientOptions) {\n super(opts)\n\n this.workflows = new WorkflowsResource(this)\n this.projects = new ProjectsResource(this)\n this.sessions = new SessionsResource(this)\n this.trash = new TrashResource(this)\n this.jobs = new JobsResource(this)\n this.videoPro = new VideoProResource(this)\n this.executions = new ExecutionsResource(this)\n this.nodes = new NodesResource(this)\n this.scene3d = new Scene3DResource(this)\n this.developerApps = new DeveloperAppsResource(this)\n this.oauth = new OAuthResource(this)\n this.webhooks = new WebhooksResource(this)\n this.apps = new AppsResource(this)\n this.characters = new CharactersResource(this)\n this.locations = new LocationsResource(this)\n this.objects = new ObjectsResource(this)\n this.creatures = new CreaturesResource(this)\n this.keepers = new KeepersResource(this)\n this.pipelines = new PipelinesResource(this)\n this.reduce = new ReduceResource(this)\n this.promptHelper = new PromptHelperResource(this)\n this.voices = new VoicesResource(this)\n this.llm = new LlmResource(this)\n this.media = new MediaResource(this)\n this.audio = new AudioResource(this)\n this.credits = new CreditsResource(this)\n this.userSettings = new UserSettingsResource(this)\n this.billing = new BillingResource(this)\n this.uploads = new UploadsResource(this)\n this.library = new LibraryResource(this)\n this.gallery = new GalleryResource(this)\n this.presets = new PresetsResource(this)\n this.savedPosts = new SavedPostsResource(this)\n this.collections = new CollectionsResource(this)\n this.palettes = new PalettesResource(this)\n this.moodboards = new MoodboardsResource(this)\n this.competitors = new CompetitorsResource(this)\n this.pickerCatalogs = new PickerCatalogsResource(this)\n this.catalogs = new CatalogsResource(this)\n this.models = new ModelsResource(this)\n this.shots = new ShotsResource(this)\n this.recast = new RecastResource(this)\n this.castSwap = new CastSwapResource(this)\n this.trends = new TrendsResource(this)\n this.studio = new StudioResource(this)\n this.copilot = new CopilotResource(this)\n this.community = new CommunityResource(this)\n this.templates = new TemplatesResource(this)\n this.tutorials = new TutorialsResource(this)\n this.organizations = new OrganizationsResource(this)\n this.workspaces = new WorkspacesResource(this)\n this.edit = new EditResource(this)\n }\n\n /**\n * A client that acts in `workspaceId`, sharing this one's auth and config.\n *\n * A NEW client rather than a setter, deliberately. A mutable selection is\n * the bug this whole axis exists to prevent: two concurrent operations\n * against one client would race over which workspace they were in, and the\n * loser would create work in the wrong place with nothing failing. A\n * per-workspace client cannot be raced.\n *\n * Pass `null` for the personal space.\n */\n withWorkspace(workspaceId: string | null): NodaroClient {\n // The two private settings are read by bracket access, which TypeScript\n // allows on a subclass and which adds no member to the declarations. Read\n // through `this` (not a side table keyed by the instance), so a client\n // wrapped in a Proxy (Vue/Pinia `reactive()`) or reached through\n // `Object.create(client)` still works.\n const fetchOverride = this[\"fetchOverride\"]\n return new NodaroClient({\n baseUrl: this.baseUrl,\n auth: this.auth,\n timeoutMs: this.timeoutMs,\n ...(fetchOverride ? { fetch: fetchOverride } : {}),\n ...(this[\"sendClientHeader\"] ? { clientLabel: this.clientLabel } : {}),\n ...(workspaceId ? { workspaceId } : {}),\n })\n }\n}\n\n/** Factory function — preferred entry point. */\nexport function createClient(opts: ClientOptions): NodaroClient {\n return new NodaroClient(opts)\n}\n"]}
1
+ {"version":3,"sources":["../src/client.ts"],"names":[],"mappings":"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","file":"chunk-EDSODRRY.js","sourcesContent":["import { WorkflowsResource } from \"./resources/workflows.js\"\nimport { ProjectsResource } from \"./resources/projects.js\"\nimport { SessionsResource } from \"./resources/sessions.js\"\nimport { TrashResource } from \"./resources/trash.js\"\nimport { JobsResource } from \"./resources/jobs.js\"\nimport { VideoProResource } from \"./resources/video-pro.js\"\nimport { ExecutionsResource } from \"./resources/executions.js\"\nimport { NodesResource } from \"./resources/nodes.js\"\nimport { Scene3DResource } from \"./resources/scene3d.js\"\nimport { DeveloperAppsResource } from \"./resources/developer-apps.js\"\nimport { OAuthResource } from \"./resources/oauth.js\"\nimport { WebhooksResource } from \"./resources/webhooks.js\"\nimport { AppsResource } from \"./resources/apps.js\"\nimport { CharactersResource } from \"./resources/characters.js\"\nimport { LocationsResource } from \"./resources/locations.js\"\nimport { ObjectsResource } from \"./resources/objects.js\"\nimport { CreaturesResource } from \"./resources/creatures.js\"\nimport { KeepersResource } from \"./resources/keepers.js\"\nimport { PipelinesResource } from \"./resources/pipelines.js\"\nimport { ReduceResource } from \"./resources/reduce.js\"\nimport { PromptHelperResource } from \"./resources/prompt-helper.js\"\nimport { VoicesResource } from \"./resources/voices.js\"\nimport { LlmResource } from \"./resources/llm.js\"\nimport { MediaResource } from \"./resources/media.js\"\nimport { AudioResource } from \"./resources/audio.js\"\nimport { CreditsResource } from \"./resources/credits.js\"\nimport { BillingResource } from \"./resources/billing.js\"\nimport { UserSettingsResource } from \"./resources/user-settings.js\"\nimport { UploadsResource } from \"./resources/uploads.js\"\nimport { LibraryResource } from \"./resources/library.js\"\nimport { GalleryResource } from \"./resources/gallery.js\"\nimport { PresetsResource } from \"./resources/node-presets.js\"\nimport { SavedPostsResource } from \"./resources/saved-posts.js\"\nimport { CollectionsResource } from \"./resources/collections.js\"\nimport { PalettesResource } from \"./resources/palettes.js\"\nimport { MoodboardsResource } from \"./resources/moodboards.js\"\nimport { CompetitorsResource } from \"./resources/competitors.js\"\nimport { PickerCatalogsResource } from \"./resources/picker-catalogs.js\"\nimport { CatalogsResource } from \"./resources/catalogs.js\"\nimport { ModelsResource } from \"./resources/models.js\"\nimport { ShotsResource } from \"./resources/shots.js\"\nimport { RecastResource } from \"./resources/recast.js\"\nimport { CastSwapResource } from \"./resources/cast-swap.js\"\nimport { TrendsResource } from \"./resources/trends.js\"\nimport { StudioResource } from \"./resources/studio.js\"\nimport { CopilotResource } from \"./resources/copilot.js\"\nimport { CommunityResource } from \"./resources/community.js\"\nimport { TemplatesResource } from \"./resources/templates.js\"\nimport { TutorialsResource } from \"./resources/tutorials.js\"\nimport { OrganizationsResource } from \"./resources/organizations.js\"\nimport { WorkspacesResource } from \"./resources/workspaces.js\"\nimport { EditResource } from \"./resources/edit.js\"\nimport { NodaroClientCore, type ClientOptions } from \"./core.js\"\n\nexport { CLIENT_HEADER } from \"./core.js\"\nexport type { ClientOptions, UserIdentity, ConnectedApp } from \"./core.js\"\n\n/**\n * The full client: the core (`./core.ts` — config, transport, identity) and\n * every resource.\n */\nexport class NodaroClient extends NodaroClientCore {\n readonly workflows: WorkflowsResource\n readonly projects: ProjectsResource\n /** Generation sessions inside projects (Create Image / Video / Music). */\n readonly sessions: SessionsResource\n /** Your Trash: items removed from sessions and deleted jobs. */\n readonly trash: TrashResource\n readonly jobs: JobsResource\n readonly videoPro: VideoProResource\n readonly executions: ExecutionsResource\n readonly nodes: NodesResource\n readonly scene3d: Scene3DResource\n readonly developerApps: DeveloperAppsResource\n readonly oauth: OAuthResource\n /** Outbound webhooks: endpoints that receive your job.completed / job.failed. */\n readonly webhooks: WebhooksResource\n readonly apps: AppsResource\n readonly characters: CharactersResource\n readonly locations: LocationsResource\n readonly objects: ObjectsResource\n readonly creatures: CreaturesResource\n /** The shared Nodaro Keepers catalog of characters, creatures, locations and objects. */\n readonly keepers: KeepersResource\n readonly pipelines: PipelinesResource\n readonly reduce: ReduceResource\n readonly promptHelper: PromptHelperResource\n readonly voices: VoicesResource\n readonly llm: LlmResource\n readonly media: MediaResource\n readonly audio: AudioResource\n readonly credits: CreditsResource\n /** The signed-in person's own settings (the interface language, the monthly statement opt-in, …). */\n readonly userSettings: UserSettingsResource\n /** Plans and prices, the subscription, and how this deployment bills. */\n readonly billing: BillingResource\n readonly uploads: UploadsResource\n readonly library: LibraryResource\n /** The public gallery and your favorites. */\n readonly gallery: GalleryResource\n readonly presets: PresetsResource\n readonly savedPosts: SavedPostsResource\n readonly collections: CollectionsResource\n /** Your colour palettes — a generate-image direction (`direction.colorLook: paletteDirectionId(id)`). */\n readonly palettes: PalettesResource\n /** Your moodboards — a generate-image direction (`direction.style: moodboardDirectionId(id)`). */\n readonly moodboards: MoodboardsResource\n readonly competitors: CompetitorsResource\n readonly pickerCatalogs: PickerCatalogsResource\n readonly catalogs: CatalogsResource\n readonly models: ModelsResource\n readonly shots: ShotsResource\n readonly recast: RecastResource\n /** Cast Swap: replace the people and/or location in a short video (Cloud). */\n readonly castSwap: CastSwapResource\n /** Trends: ready-made Cast Swap recipes you fill with your own pictures (Cloud). */\n readonly trends: TrendsResource\n readonly studio: StudioResource\n readonly copilot: CopilotResource\n readonly community: CommunityResource\n readonly templates: TemplatesResource\n readonly tutorials: TutorialsResource\n readonly organizations: OrganizationsResource\n readonly workspaces: WorkspacesResource\n readonly edit: EditResource\n\n constructor(opts: ClientOptions) {\n super(opts)\n\n this.workflows = new WorkflowsResource(this)\n this.projects = new ProjectsResource(this)\n this.sessions = new SessionsResource(this)\n this.trash = new TrashResource(this)\n this.jobs = new JobsResource(this)\n this.videoPro = new VideoProResource(this)\n this.executions = new ExecutionsResource(this)\n this.nodes = new NodesResource(this)\n this.scene3d = new Scene3DResource(this)\n this.developerApps = new DeveloperAppsResource(this)\n this.oauth = new OAuthResource(this)\n this.webhooks = new WebhooksResource(this)\n this.apps = new AppsResource(this)\n this.characters = new CharactersResource(this)\n this.locations = new LocationsResource(this)\n this.objects = new ObjectsResource(this)\n this.creatures = new CreaturesResource(this)\n this.keepers = new KeepersResource(this)\n this.pipelines = new PipelinesResource(this)\n this.reduce = new ReduceResource(this)\n this.promptHelper = new PromptHelperResource(this)\n this.voices = new VoicesResource(this)\n this.llm = new LlmResource(this)\n this.media = new MediaResource(this)\n this.audio = new AudioResource(this)\n this.credits = new CreditsResource(this)\n this.userSettings = new UserSettingsResource(this)\n this.billing = new BillingResource(this)\n this.uploads = new UploadsResource(this)\n this.library = new LibraryResource(this)\n this.gallery = new GalleryResource(this)\n this.presets = new PresetsResource(this)\n this.savedPosts = new SavedPostsResource(this)\n this.collections = new CollectionsResource(this)\n this.palettes = new PalettesResource(this)\n this.moodboards = new MoodboardsResource(this)\n this.competitors = new CompetitorsResource(this)\n this.pickerCatalogs = new PickerCatalogsResource(this)\n this.catalogs = new CatalogsResource(this)\n this.models = new ModelsResource(this)\n this.shots = new ShotsResource(this)\n this.recast = new RecastResource(this)\n this.castSwap = new CastSwapResource(this)\n this.trends = new TrendsResource(this)\n this.studio = new StudioResource(this)\n this.copilot = new CopilotResource(this)\n this.community = new CommunityResource(this)\n this.templates = new TemplatesResource(this)\n this.tutorials = new TutorialsResource(this)\n this.organizations = new OrganizationsResource(this)\n this.workspaces = new WorkspacesResource(this)\n this.edit = new EditResource(this)\n }\n\n /**\n * A client that acts in `workspaceId`, sharing this one's auth and config.\n *\n * A NEW client rather than a setter, deliberately. A mutable selection is\n * the bug this whole axis exists to prevent: two concurrent operations\n * against one client would race over which workspace they were in, and the\n * loser would create work in the wrong place with nothing failing. A\n * per-workspace client cannot be raced.\n *\n * Pass `null` for the personal space.\n */\n withWorkspace(workspaceId: string | null): NodaroClient {\n // The two private settings are read by bracket access, which TypeScript\n // allows on a subclass and which adds no member to the declarations. Read\n // through `this` (not a side table keyed by the instance), so a client\n // wrapped in a Proxy (Vue/Pinia `reactive()`) or reached through\n // `Object.create(client)` still works.\n const fetchOverride = this[\"fetchOverride\"]\n return new NodaroClient({\n baseUrl: this.baseUrl,\n auth: this.auth,\n timeoutMs: this.timeoutMs,\n ...(fetchOverride ? { fetch: fetchOverride } : {}),\n ...(this[\"sendClientHeader\"] ? { clientLabel: this.clientLabel } : {}),\n ...(workspaceId ? { workspaceId } : {}),\n })\n }\n}\n\n/** Factory function — preferred entry point. */\nexport function createClient(opts: ClientOptions): NodaroClient {\n return new NodaroClient(opts)\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkFRQJNGJS_cjs = require('./chunk-FRQJNGJS.cjs');
3
+ var chunkKU3UITCU_cjs = require('./chunk-KU3UITCU.cjs');
4
4
 
5
5
  // src/resources/copilot.ts
6
6
  var COPILOT_FRAME_TYPES = /* @__PURE__ */ new Set([
@@ -93,12 +93,12 @@ var CopilotResource = class {
93
93
  }),
94
94
  signal: opts.signal
95
95
  });
96
- for await (const value of chunkFRQJNGJS_cjs.readSseStream(res, { label: "copilot stream" })) {
96
+ for await (const value of chunkKU3UITCU_cjs.readSseStream(res, { label: "copilot stream" })) {
97
97
  if (isCopilotFrame(value)) yield value;
98
98
  }
99
99
  }
100
100
  };
101
101
 
102
102
  exports.CopilotResource = CopilotResource;
103
- //# sourceMappingURL=chunk-OSMKIRKI.cjs.map
104
- //# sourceMappingURL=chunk-OSMKIRKI.cjs.map
103
+ //# sourceMappingURL=chunk-GDUEOKBF.cjs.map
104
+ //# sourceMappingURL=chunk-GDUEOKBF.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/resources/copilot.ts"],"names":["readSseStream"],"mappings":"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","file":"chunk-OSMKIRKI.cjs","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { readSseStream } from \"../sse.js\"\n\n/**\n * The assistant's conversation surface (`/v1/copilot/*`) — threads, and one\n * turn as a live stream.\n *\n * A thread is the conversation; a TURN is one message and everything the\n * assistant does in answer to it. `stream` is the only method that spends: it\n * POSTs the message and yields the turn's frames as they arrive, so a caller\n * renders prose, tool activity and proposals live instead of waiting for a\n * finished answer.\n *\n * Two shapes here are deliberately TOLERANT of a deployment that predates a\n * field, because the SDK ships ahead of every instance it talks to:\n * - `surface` is optional on both {@link CopilotThread} and the `metadata`\n * frame — absent is a value (\"this deployment does not say\"), never a\n * default this package invents.\n * - An event kind this package does not model is IGNORED, not thrown: a\n * newer server may emit frames a caller was built before.\n */\n\n/** How this thread runs what it proposes: ask first, or run within a budget. */\nexport type CopilotRunMode = \"ask\" | \"auto\"\n\n/** The thread's model rung. Absent from a server that predates it. */\nexport type CopilotModelTier = \"economy\" | \"standard\" | \"premium\"\n\n/**\n * Which product the conversation belongs to.\n *\n * NO deployment sends this today — nothing in the platform emits it yet — and\n * it is typed here so that the day one does, a caller reads what the server\n * said. That is why it is OPTIONAL everywhere it appears: absent is a value\n * (\"this deployment does not say\"), never a default this package invents.\n */\nexport type CopilotSurface = \"studio\" | \"workflow\"\n\nexport interface CopilotThread {\n id: string\n workflowId: string\n runMode: CopilotRunMode\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n /** Whether this thread may build nodes that publish to connected accounts. */\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n autoRunLimitCredits: number\n userTurnCount: number\n lastMessageAt: string | null\n createdAt: string\n /** Only on {@link CopilotResource.get} — derived from a live turn. */\n status?: \"running\" | \"idle\"\n activeTurnId?: string | null\n}\n\n/** The workflow a thread was opened on, as `create` answers it. */\nexport interface CopilotThreadWorkflow {\n id: string\n projectId: string\n name: string\n version: number\n}\n\nexport type CopilotMessagePart =\n | { kind: \"text\"; text: string }\n | { kind: \"tool_call\"; id: string; name: string; label: string; status: \"finished\" | \"failed\" }\n\nexport interface CopilotMessage {\n id: string\n seq: number\n turnId: string\n role: \"user\" | \"assistant\"\n createdAt: string\n parts: CopilotMessagePart[]\n}\n\n/** Open a thread on an existing workflow, or on one this call creates. */\nexport interface CreateCopilotThreadInput {\n /** The workflow to work on. Give this OR `prompt`. */\n workflowId?: string\n /** Start from nothing: the server creates a workflow seeded by this prompt. */\n prompt?: string\n /** Name for a workflow created by `prompt` (defaults to the prompt's head). */\n name?: string\n}\n\nexport interface CopilotStreamOptions {\n /** The user's turn. */\n message: string\n /** The workflow version this message was composed against — a newer one 409s. */\n baseVersion?: number\n /** The composer's echo of the thread's rung; the thread row stays authoritative. */\n tier?: CopilotModelTier\n /**\n * Ends the stream. The client's request timeout is NOT applied to a turn.\n *\n * Aborting REJECTS the iteration — with the platform's raw `AbortError`, not\n * a `NodaroError` — whether it fires before the first frame or between two of\n * them. Wrap the loop in `try`/`catch` if a cancelled turn is an ordinary\n * ending in your UI. (`media.downloadVideoProgress` behaves the same way.)\n */\n signal?: AbortSignal\n}\n\nexport interface CopilotToolCallFrameData {\n id: string\n name: string\n label: string\n status: \"started\" | \"finished\" | \"failed\"\n summary?: string\n}\n\nexport interface CopilotWorkflowUpdateFrameData {\n workflowId: string\n version: number\n updatedAt?: string\n note?: string | null\n addedNodeIds: string[]\n updatedNodeIds: string[]\n removedNodeIds: string[]\n addedNodeTypes: string[]\n nodeCount: number\n edgeCount: number\n adjustments: string[]\n}\n\n/** A file the turn wired onto a node — named on the run card, never counted. */\nexport interface CopilotWiredAsset {\n id: string\n kind: string\n filename: string\n nodeId: string\n}\n\nexport interface CopilotRunProposalNode {\n id: string\n type: string\n graphVersion: number\n label: string\n}\n\nexport interface CopilotRunProposalFrameData {\n workflowId: string\n addedNodeTypes: string[]\n wiredAssets?: CopilotWiredAsset[]\n note: string | null\n /** Present when ONE node was proposed rather than the whole graph. */\n node?: CopilotRunProposalNode | null\n}\n\n/** A workflow the turn created — a different one from the open canvas. */\nexport interface CopilotWorkflowCreatedFrameData {\n workflowId: string\n name: string\n projectId: string\n}\n\n/** One thing the assistant saved to memory this turn. */\nexport interface CopilotMemorySavedFrameData {\n id: string\n content: string\n}\n\nexport interface CopilotMetadataFrameData {\n threadId: string\n turnId: string\n jobId: string\n model: string\n baseVersion: number | null\n runMode: CopilotRunMode\n autoRunLimitCredits: number\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n}\n\n/**\n * One frame of a turn.\n *\n * The union covers the frame KINDS; a frame's `data` is passed through\n * untouched, so a field this package does not model still reaches the caller\n * rather than being stripped on the way.\n */\nexport type CopilotStreamFrame =\n | { type: \"metadata\"; data: CopilotMetadataFrameData }\n | { type: \"token\"; data: { text: string } }\n | { type: \"tool_call\"; data: CopilotToolCallFrameData }\n | { type: \"workflow_updated\"; data: CopilotWorkflowUpdateFrameData }\n | { type: \"workflow_created\"; data: CopilotWorkflowCreatedFrameData }\n | { type: \"run_proposed\"; data: CopilotRunProposalFrameData }\n | { type: \"memory_saved\"; data: CopilotMemorySavedFrameData }\n | { type: \"usage\"; data: { inputTokens: number; outputTokens: number; cacheReadTokens: number; creditsCharged: number | null } }\n | { type: \"done\"; data: { turnId: string; messageId: string | null; status: \"completed\" | \"capped\" | \"cancelled\"; finalVersion: number | null } }\n | { type: \"error\"; data: { code: string; message: string } }\n\n/** The kinds above, as the wire spells them — the whole of what `stream` yields. */\nconst COPILOT_FRAME_TYPES: ReadonlySet<string> = new Set([\n \"metadata\",\n \"token\",\n \"tool_call\",\n \"workflow_updated\",\n \"workflow_created\",\n \"run_proposed\",\n \"memory_saved\",\n \"usage\",\n \"done\",\n \"error\",\n])\n\nfunction isCopilotFrame(value: unknown): value is CopilotStreamFrame {\n if (typeof value !== \"object\" || value === null) return false\n const type = (value as { type?: unknown }).type\n return typeof type === \"string\" && COPILOT_FRAME_TYPES.has(type)\n}\n\nexport class CopilotResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Open a conversation (`POST /v1/copilot/threads`) — on `workflowId`, or on\n * a workflow the server creates from `prompt`. Re-opening a workflow that\n * already has an active thread answers THAT thread rather than a second one.\n */\n create(input: CreateCopilotThreadInput): Promise<{ data: { thread: CopilotThread; workflow: CopilotThreadWorkflow } }> {\n return this.client.request(\"POST\", \"/v1/copilot/threads\", { body: input })\n }\n\n /**\n * The active thread for a workflow (`GET /v1/copilot/threads?workflowId=…`),\n * or `null` when the user has none open on it.\n */\n list(params: { workflowId: string }): Promise<{ data: { thread: CopilotThread | null } }> {\n return this.client.request(\"GET\", \"/v1/copilot/threads\", { query: { workflowId: params.workflowId } })\n }\n\n /**\n * One thread with its messages (`GET /v1/copilot/threads/:id`). `after` reads\n * only what followed that sequence number (the panel's catch-up); `limit`\n * caps the page at the server's own ceiling.\n */\n get(\n id: string,\n opts: { after?: number; limit?: number } = {},\n ): Promise<{ data: { thread: CopilotThread; messages: CopilotMessage[] } }> {\n return this.client.request(\"GET\", `/v1/copilot/threads/${encodeURIComponent(id)}`, {\n query: { ...(opts.after !== undefined ? { after: opts.after } : {}), ...(opts.limit !== undefined ? { limit: opts.limit } : {}) },\n })\n }\n\n /**\n * Close a conversation (`DELETE /v1/copilot/threads/:id`). Archival, not\n * deletion — the messages stay readable. Refused while a turn is running.\n */\n archive(id: string): Promise<{ data: { archived: true } }> {\n return this.client.request(\"DELETE\", `/v1/copilot/threads/${encodeURIComponent(id)}`)\n }\n\n /**\n * Stop the running turn (`POST /v1/copilot/threads/:id/cancel`). Answers the\n * turn it asked to stop; the turn's own stream ends with a `done` frame.\n */\n cancel(id: string): Promise<{ data: { cancelling: true; turnId: string } }> {\n return this.client.request(\"POST\", `/v1/copilot/threads/${encodeURIComponent(id)}/cancel`)\n }\n\n /**\n * Send one message and iterate the turn's frames\n * (`POST /v1/copilot/threads/:id/messages`, server-sent events).\n *\n * Deliberately NOT routed through `client.request`: that path arms an abort\n * timer around the whole exchange, and a turn legitimately runs for minutes —\n * inheriting `timeoutMs` would cut the assistant off mid-answer. The caller\n * owns the lifetime instead: pass `signal` to end the stream, or stop\n * iterating (the reader cancels the body, which ends the request).\n *\n * A frame kind this package does not model is skipped rather than thrown, so\n * a newer server cannot break an older caller.\n */\n async *stream(threadId: string, opts: CopilotStreamOptions): AsyncGenerator<CopilotStreamFrame, void, undefined> {\n const url = `${this.client.baseUrl}/v1/copilot/threads/${encodeURIComponent(threadId)}/messages`\n const token = await this.client.auth.getToken()\n const res = await this.client.fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n body: JSON.stringify({\n message: opts.message,\n ...(opts.baseVersion !== undefined ? { baseVersion: opts.baseVersion } : {}),\n ...(opts.tier ? { tier: opts.tier } : {}),\n }),\n signal: opts.signal,\n })\n for await (const value of readSseStream<unknown>(res, { label: \"copilot stream\" })) {\n if (isCopilotFrame(value)) yield value\n }\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/resources/copilot.ts"],"names":["readSseStream"],"mappings":";;;;;AAsMA,IAAM,mBAAA,uBAA+C,GAAA,CAAI;AAAA,EACvD,UAAA;AAAA,EACA,OAAA;AAAA,EACA,WAAA;AAAA,EACA,kBAAA;AAAA,EACA,kBAAA;AAAA,EACA,cAAA;AAAA,EACA,cAAA;AAAA,EACA,OAAA;AAAA,EACA,MAAA;AAAA,EACA;AACF,CAAC,CAAA;AAED,SAAS,eAAe,KAAA,EAA6C;AACnE,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,MAAM,OAAO,KAAA;AACxD,EAAA,MAAM,OAAQ,KAAA,CAA6B,IAAA;AAC3C,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,IAAY,mBAAA,CAAoB,IAAI,IAAI,CAAA;AACjE;AAEO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOpB,OAAO,KAAA,EAAgH;AACrH,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,MAAA,EAAQ,uBAAuB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,KAAK,MAAA,EAAqF;AACxF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,qBAAA,EAAuB,EAAE,KAAA,EAAO,EAAE,UAAA,EAAY,MAAA,CAAO,UAAA,EAAW,EAAG,CAAA;AAAA,EACvG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,GAAA,CACE,EAAA,EACA,IAAA,GAA2C,EAAC,EAC8B;AAC1E,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,KAAA,EAAO,uBAAuB,kBAAA,CAAmB,EAAE,CAAC,CAAA,CAAA,EAAI;AAAA,MACjF,KAAA,EAAO,EAAE,GAAI,IAAA,CAAK,UAAU,MAAA,GAAY,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,EAAM,GAAI,EAAC,EAAI,GAAI,IAAA,CAAK,KAAA,KAAU,MAAA,GAAY,EAAE,OAAO,IAAA,CAAK,KAAA,EAAM,GAAI,EAAC;AAAG,KACjI,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,EAAA,EAAmD;AACzD,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,QAAA,EAAU,uBAAuB,kBAAA,CAAmB,EAAE,CAAC,CAAA,CAAE,CAAA;AAAA,EACtF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,EAAA,EAAqE;AAC1E,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,MAAA,EAAQ,uBAAuB,kBAAA,CAAmB,EAAE,CAAC,CAAA,OAAA,CAAS,CAAA;AAAA,EAC3F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,OAAO,MAAA,CAAO,QAAA,EAAkB,IAAA,EAAiF;AAC/G,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,oBAAA,EAAuB,kBAAA,CAAmB,QAAQ,CAAC,CAAA,SAAA,CAAA;AACrF,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,KAAK,QAAA,EAAS;AAC9C,IAAA,MAAM,GAAA,GAAM,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,GAAA,EAAK;AAAA,MACvC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA,EAAS;AAAA,QACP,cAAA,EAAgB,kBAAA;AAAA,QAChB,GAAI,QAAQ,EAAE,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA,KAAO;AAAC,OACtD;AAAA,MACA,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,GAAI,KAAK,WAAA,KAAgB,MAAA,GAAY,EAAE,WAAA,EAAa,IAAA,CAAK,WAAA,EAAY,GAAI,EAAC;AAAA,QAC1E,GAAI,KAAK,IAAA,GAAO,EAAE,MAAM,IAAA,CAAK,IAAA,KAAS;AAAC,OACxC,CAAA;AAAA,MACD,QAAQ,IAAA,CAAK;AAAA,KACd,CAAA;AACD,IAAA,WAAA,MAAiB,SAASA,+BAAA,CAAuB,GAAA,EAAK,EAAE,KAAA,EAAO,gBAAA,EAAkB,CAAA,EAAG;AAClF,MAAA,IAAI,cAAA,CAAe,KAAK,CAAA,EAAG,MAAM,KAAA;AAAA,IACnC;AAAA,EACF;AACF","file":"chunk-GDUEOKBF.cjs","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { readSseStream } from \"../sse.js\"\n\n/**\n * The assistant's conversation surface (`/v1/copilot/*`) — threads, and one\n * turn as a live stream.\n *\n * A thread is the conversation; a TURN is one message and everything the\n * assistant does in answer to it. `stream` is the only method that spends: it\n * POSTs the message and yields the turn's frames as they arrive, so a caller\n * renders prose, tool activity and proposals live instead of waiting for a\n * finished answer.\n *\n * Two shapes here are deliberately TOLERANT of a deployment that predates a\n * field, because the SDK ships ahead of every instance it talks to:\n * - `surface` is optional on both {@link CopilotThread} and the `metadata`\n * frame — absent is a value (\"this deployment does not say\"), never a\n * default this package invents.\n * - An event kind this package does not model is IGNORED, not thrown: a\n * newer server may emit frames a caller was built before.\n */\n\n/** How this thread runs what it proposes: ask first, or run within a budget. */\nexport type CopilotRunMode = \"ask\" | \"auto\"\n\n/** The thread's model rung. Absent from a server that predates it. */\nexport type CopilotModelTier = \"economy\" | \"standard\" | \"premium\"\n\n/**\n * Which product the conversation belongs to.\n *\n * NO deployment sends this today — nothing in the platform emits it yet — and\n * it is typed here so that the day one does, a caller reads what the server\n * said. That is why it is OPTIONAL everywhere it appears: absent is a value\n * (\"this deployment does not say\"), never a default this package invents.\n */\nexport type CopilotSurface = \"studio\" | \"workflow\"\n\nexport interface CopilotThread {\n id: string\n workflowId: string\n runMode: CopilotRunMode\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n /** Whether this thread may build nodes that publish to connected accounts. */\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n autoRunLimitCredits: number\n userTurnCount: number\n lastMessageAt: string | null\n createdAt: string\n /** Only on {@link CopilotResource.get} — derived from a live turn. */\n status?: \"running\" | \"idle\"\n activeTurnId?: string | null\n}\n\n/** The workflow a thread was opened on, as `create` answers it. */\nexport interface CopilotThreadWorkflow {\n id: string\n projectId: string\n name: string\n version: number\n}\n\nexport type CopilotMessagePart =\n | { kind: \"text\"; text: string }\n | { kind: \"tool_call\"; id: string; name: string; label: string; status: \"finished\" | \"failed\" }\n\nexport interface CopilotMessage {\n id: string\n seq: number\n turnId: string\n role: \"user\" | \"assistant\"\n createdAt: string\n parts: CopilotMessagePart[]\n}\n\n/** Open a thread on an existing workflow, or on one this call creates. */\nexport interface CreateCopilotThreadInput {\n /** The workflow to work on. Give this OR `prompt`. */\n workflowId?: string\n /** Start from nothing: the server creates a workflow seeded by this prompt. */\n prompt?: string\n /** Name for a workflow created by `prompt` (defaults to the prompt's head). */\n name?: string\n}\n\nexport interface CopilotStreamOptions {\n /** The user's turn. */\n message: string\n /** The workflow version this message was composed against — a newer one 409s. */\n baseVersion?: number\n /** The composer's echo of the thread's rung; the thread row stays authoritative. */\n tier?: CopilotModelTier\n /**\n * Ends the stream. The client's request timeout is NOT applied to a turn.\n *\n * Aborting REJECTS the iteration — with the platform's raw `AbortError`, not\n * a `NodaroError` — whether it fires before the first frame or between two of\n * them. Wrap the loop in `try`/`catch` if a cancelled turn is an ordinary\n * ending in your UI. (`media.downloadVideoProgress` behaves the same way.)\n */\n signal?: AbortSignal\n}\n\nexport interface CopilotToolCallFrameData {\n id: string\n name: string\n label: string\n status: \"started\" | \"finished\" | \"failed\"\n summary?: string\n}\n\nexport interface CopilotWorkflowUpdateFrameData {\n workflowId: string\n version: number\n updatedAt?: string\n note?: string | null\n addedNodeIds: string[]\n updatedNodeIds: string[]\n removedNodeIds: string[]\n addedNodeTypes: string[]\n nodeCount: number\n edgeCount: number\n adjustments: string[]\n}\n\n/** A file the turn wired onto a node — named on the run card, never counted. */\nexport interface CopilotWiredAsset {\n id: string\n kind: string\n filename: string\n nodeId: string\n}\n\nexport interface CopilotRunProposalNode {\n id: string\n type: string\n graphVersion: number\n label: string\n}\n\nexport interface CopilotRunProposalFrameData {\n workflowId: string\n addedNodeTypes: string[]\n wiredAssets?: CopilotWiredAsset[]\n note: string | null\n /** Present when ONE node was proposed rather than the whole graph. */\n node?: CopilotRunProposalNode | null\n}\n\n/** A workflow the turn created — a different one from the open canvas. */\nexport interface CopilotWorkflowCreatedFrameData {\n workflowId: string\n name: string\n projectId: string\n}\n\n/** One thing the assistant saved to memory this turn. */\nexport interface CopilotMemorySavedFrameData {\n id: string\n content: string\n}\n\nexport interface CopilotMetadataFrameData {\n threadId: string\n turnId: string\n jobId: string\n model: string\n baseVersion: number | null\n runMode: CopilotRunMode\n autoRunLimitCredits: number\n allowPublishing?: boolean\n modelTier?: CopilotModelTier\n /** See {@link CopilotSurface} — absent means the server did not say. */\n surface?: CopilotSurface\n}\n\n/**\n * One frame of a turn.\n *\n * The union covers the frame KINDS; a frame's `data` is passed through\n * untouched, so a field this package does not model still reaches the caller\n * rather than being stripped on the way.\n */\nexport type CopilotStreamFrame =\n | { type: \"metadata\"; data: CopilotMetadataFrameData }\n | { type: \"token\"; data: { text: string } }\n | { type: \"tool_call\"; data: CopilotToolCallFrameData }\n | { type: \"workflow_updated\"; data: CopilotWorkflowUpdateFrameData }\n | { type: \"workflow_created\"; data: CopilotWorkflowCreatedFrameData }\n | { type: \"run_proposed\"; data: CopilotRunProposalFrameData }\n | { type: \"memory_saved\"; data: CopilotMemorySavedFrameData }\n | { type: \"usage\"; data: { inputTokens: number; outputTokens: number; cacheReadTokens: number; creditsCharged: number | null } }\n | { type: \"done\"; data: { turnId: string; messageId: string | null; status: \"completed\" | \"capped\" | \"cancelled\"; finalVersion: number | null } }\n | { type: \"error\"; data: { code: string; message: string } }\n\n/** The kinds above, as the wire spells them — the whole of what `stream` yields. */\nconst COPILOT_FRAME_TYPES: ReadonlySet<string> = new Set([\n \"metadata\",\n \"token\",\n \"tool_call\",\n \"workflow_updated\",\n \"workflow_created\",\n \"run_proposed\",\n \"memory_saved\",\n \"usage\",\n \"done\",\n \"error\",\n])\n\nfunction isCopilotFrame(value: unknown): value is CopilotStreamFrame {\n if (typeof value !== \"object\" || value === null) return false\n const type = (value as { type?: unknown }).type\n return typeof type === \"string\" && COPILOT_FRAME_TYPES.has(type)\n}\n\nexport class CopilotResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Open a conversation (`POST /v1/copilot/threads`) — on `workflowId`, or on\n * a workflow the server creates from `prompt`. Re-opening a workflow that\n * already has an active thread answers THAT thread rather than a second one.\n */\n create(input: CreateCopilotThreadInput): Promise<{ data: { thread: CopilotThread; workflow: CopilotThreadWorkflow } }> {\n return this.client.request(\"POST\", \"/v1/copilot/threads\", { body: input })\n }\n\n /**\n * The active thread for a workflow (`GET /v1/copilot/threads?workflowId=…`),\n * or `null` when the user has none open on it.\n */\n list(params: { workflowId: string }): Promise<{ data: { thread: CopilotThread | null } }> {\n return this.client.request(\"GET\", \"/v1/copilot/threads\", { query: { workflowId: params.workflowId } })\n }\n\n /**\n * One thread with its messages (`GET /v1/copilot/threads/:id`). `after` reads\n * only what followed that sequence number (the panel's catch-up); `limit`\n * caps the page at the server's own ceiling.\n */\n get(\n id: string,\n opts: { after?: number; limit?: number } = {},\n ): Promise<{ data: { thread: CopilotThread; messages: CopilotMessage[] } }> {\n return this.client.request(\"GET\", `/v1/copilot/threads/${encodeURIComponent(id)}`, {\n query: { ...(opts.after !== undefined ? { after: opts.after } : {}), ...(opts.limit !== undefined ? { limit: opts.limit } : {}) },\n })\n }\n\n /**\n * Close a conversation (`DELETE /v1/copilot/threads/:id`). Archival, not\n * deletion — the messages stay readable. Refused while a turn is running.\n */\n archive(id: string): Promise<{ data: { archived: true } }> {\n return this.client.request(\"DELETE\", `/v1/copilot/threads/${encodeURIComponent(id)}`)\n }\n\n /**\n * Stop the running turn (`POST /v1/copilot/threads/:id/cancel`). Answers the\n * turn it asked to stop; the turn's own stream ends with a `done` frame.\n */\n cancel(id: string): Promise<{ data: { cancelling: true; turnId: string } }> {\n return this.client.request(\"POST\", `/v1/copilot/threads/${encodeURIComponent(id)}/cancel`)\n }\n\n /**\n * Send one message and iterate the turn's frames\n * (`POST /v1/copilot/threads/:id/messages`, server-sent events).\n *\n * Deliberately NOT routed through `client.request`: that path arms an abort\n * timer around the whole exchange, and a turn legitimately runs for minutes —\n * inheriting `timeoutMs` would cut the assistant off mid-answer. The caller\n * owns the lifetime instead: pass `signal` to end the stream, or stop\n * iterating (the reader cancels the body, which ends the request).\n *\n * A frame kind this package does not model is skipped rather than thrown, so\n * a newer server cannot break an older caller.\n */\n async *stream(threadId: string, opts: CopilotStreamOptions): AsyncGenerator<CopilotStreamFrame, void, undefined> {\n const url = `${this.client.baseUrl}/v1/copilot/threads/${encodeURIComponent(threadId)}/messages`\n const token = await this.client.auth.getToken()\n const res = await this.client.fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n ...(token ? { Authorization: `Bearer ${token}` } : {}),\n },\n body: JSON.stringify({\n message: opts.message,\n ...(opts.baseVersion !== undefined ? { baseVersion: opts.baseVersion } : {}),\n ...(opts.tier ? { tier: opts.tier } : {}),\n }),\n signal: opts.signal,\n })\n for await (const value of readSseStream<unknown>(res, { label: \"copilot stream\" })) {\n if (isCopilotFrame(value)) yield value\n }\n }\n}\n"]}
@@ -59,5 +59,5 @@ var CastSwapResource = class {
59
59
  };
60
60
 
61
61
  exports.CastSwapResource = CastSwapResource;
62
- //# sourceMappingURL=chunk-65VIIZEF.cjs.map
63
- //# sourceMappingURL=chunk-65VIIZEF.cjs.map
62
+ //# sourceMappingURL=chunk-GJH73EGF.cjs.map
63
+ //# sourceMappingURL=chunk-GJH73EGF.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/resources/cast-swap.ts"],"names":["nodaroMotionEngineFrom"],"mappings":";;;;;AAoeO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,GAAA,CAAI,QAAwB,OAAA,EAA6E;AACvG,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,eAAA,EAAiB;AAAA,MAClD,IAAA,EAAM,MAAA;AAAA,MACN,GAAI,OAAA,EAAS,cAAA,GAAiB,EAAE,OAAA,EAAS,EAAE,iBAAA,EAAmB,OAAA,CAAQ,cAAA,EAAe,EAAE,GAAI;AAAC,KAC7F,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAS,MAAA,EAAmD;AAChE,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAA0B,QAAQ,wBAAA,EAA0B,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAE5G,IAAA,MAAM,MAAA,GAASA,6BAAA,CAAuB,KAAA,EAAO,MAAM,CAAA;AACnD,IAAA,OAAO,MAAA,IAAU,WAAW,KAAA,CAAM,MAAA,GAAS,EAAE,GAAG,KAAA,EAAO,QAAO,GAAI,KAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,oBAAoB,KAAA,EAAqD;AACvE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,sBAAA,CAAA,EAA0B,EAAE,IAAA,EAAM,IAAI,CAAA;AAAA,EACrH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAA,CAAY,KAAA,EAAe,MAAA,GAAoC,EAAC,EAAuC;AACrG,IAAA,MAAM,IAAA,GAAO,OAAO,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU,GAAI,EAAC;AACjF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,aAAA,CAAA,EAAiB,EAAE,IAAA,EAAM,CAAA;AAAA,EACxG;AACF","file":"chunk-65VIIZEF.cjs","sourcesContent":["import { nodaroMotionEngineFrom } from \"@nodaro/shared/models\"\nimport type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Nodaro Motion (the `castSwap` resource; routes `/v1/cast-swap`) — replace\n * the people, pets, products and/or the location in a short video with your\n * own references, keeping its motion, framing, timing and sound (the clip's\n * audio is kept, and the result is the clip's length).\n *\n * Before the video, each person, pet and product role's photos are turned\n * into one clean reference picture by an image model. This costs extra\n * credits (`breakdown.references` in the estimate), charged when it runs, even\n * if the video then fails; it adds about a minute, falls back to your own\n * photos if it fails, and is turned off with `prepareReferences: false`.\n * Locations are not prepared.\n *\n * Engines: a run is made on Nodaro Motion Prism (`engine` left out, or\n * `\"motion-prism\"`) or Nodaro Motion Pulse (`\"motion-pulse\"`). Pulse renders 720p\n * (its default) or 1080p and has no draft; it makes a new take guided by the\n * clip and pictures, so its Full Quality is a new take at 1080p rather than\n * the same take re-rendered (`CastSwapFullQualityEstimate.kind`).\n *\n * How the clip is prepared for the video model (for one, whether faces are\n * hidden first, and whether a refused clip is retried) is set by Nodaro for\n * each engine; a run cannot change it. `faceMasking` is no longer read\n * (deprecated: accepted and ignored).\n *\n * Cloud edition only: `/v1/cast-swap` is served by the cloud plugin and 404s\n * on self-hosted installs. `run()` answers 202 with a job id; follow it with\n * `client.jobs.get(jobId)` / `client.jobs.getStatus(jobId)` like any other job.\n *\n * Repeats: pass `{ idempotencyKey }` to `run()` and it is sent as the\n * `Idempotency-Key` header. A repeat with the same key within the credit\n * guard's dedup window (about 10 s) answers 200 `{ jobId, deduped: true }` with\n * an `X-Dedup-Hit` header; a later one answers 202 with the first run's\n * `jobId`. Nothing new is started or charged.\n *\n * Refusals (thrown as a `NodaroError` subclass; body `{ error: { code, message } }`), before\n * anything is charged: 400 `validation_error` (the body: no role with images,\n * no reference and no `prePrompt` or `postPrompt`, more roles of a kind\n * than allowed, more than 30 images in all, `draft: true` above 480p, a\n * `prePrompt` or `postPrompt` over 4,000 characters); on Nodaro Motion Pulse,\n * `draft_unsupported` (`draft: true`), `resolution_unsupported` (480p),\n * `output_format_unsupported` (a MOV edit output) and `too_many_images` (more\n * than 10 images in the run, across every role and fixed reference);\n * `raw_reference_token` (also in a reference's `line`),\n * `invalid_role_mention` (also any `{role:N}` in a reference's `line`),\n * `unsafe_url`, `video_unreadable`, `clip_out_of_range` (4–30 s),\n * `preview_out_of_range`, `no_roles_in_preview` (a preview with every role\n * `inPreview: false`, always refused even with a prompt, or with no role kept\n * in it that has images and no `prePrompt` or `postPrompt`), `prompt_too_long`\n * (the prompt would build too long: a `{role:N}` reads as the role's name when\n * it sends no images; Nodaro Motion Pulse's cap is 8,000 characters); 401; 402 `insufficient_credits` (`run()` only); 404\n * (a `sessionId` you may not use, `run()` only); 422 `job_blocked` (`run()`\n * only); 503 `host_too_old` (both); 503 `estimate_unavailable` (`estimate()`\n * only).\n */\n\n/**\n * The engine a Nodaro Motion run is made on, by its public id. Left out =\n * `\"motion-prism\"`.\n *\n * - `\"motion-prism\"` (Nodaro Motion Prism): 480p (the default, a draft unless\n * `draft: false`), 720p or 1080p; Full Quality re-renders a draft's own take\n * at 1080p.\n * - `\"motion-pulse\"` (Nodaro Motion Pulse): 720p (the default) or 1080p, never a\n * draft (`draft: true` answers 400 `draft_unsupported`); Full Quality makes a\n * new take at 1080p from a completed 720p run's inputs. A preview is still\n * 4 s from `previewStart`.\n */\nexport type CastSwapEngine = \"motion-prism\" | \"motion-pulse\"\n\n/**\n * The engine ids an older client sent: the earlier public ids (`\"motion-pro\"`\n * = `\"motion-prism\"`, `\"motion-lite\"` = `\"motion-pulse\"`) and the internal\n * ones (`\"seedance-2-5\"`, `\"kling-4\"`). Still accepted in a request; never\n * returned.\n * @deprecated use {@link CastSwapEngine}.\n */\nexport type CastSwapEngineLegacyId = \"motion-pro\" | \"motion-lite\" | \"seedance-2-5\" | \"kling-4\"\n\n/**\n * How a run follows its clip. Left out = `\"precise\"`.\n *\n * - `\"precise\"`: follows the clip exactly.\n * - `\"motion\"`: follows the clip's movement and takes the looks from your\n * photos, more freely than `\"precise\"`. Its price may differ from\n * `\"precise\"`'s: the estimate shows the exact price.\n */\nexport type CastSwapStyle = \"precise\" | \"motion\"\n\n/**\n * Where a Nodaro Motion Pulse run cuts the clip to whole seconds (Pulse renders\n * whole seconds; asked for more than the clip, it would stretch the motion):\n * - `\"cut-end\"` (the default): drop the fraction of a second at its end;\n * - `\"cut-start\"`: drop it at its start.\n */\nexport type CastSwapMotionLength = \"cut-end\" | \"cut-start\"\n\n/** @deprecated use {@link CastSwapMotionLength}. */\nexport type CastSwapKlingLength = CastSwapMotionLength\n\n/** Whether a swapped subject takes this trait from the references (`\"new\"`) or keeps the video's (`\"original\"`). */\nexport type CastSwapTraitSource = \"new\" | \"original\"\n\n/**\n * Preview-only settings, on every role kind; a full run (`preview` not `true`)\n * ignores both.\n */\nexport interface CastSwapRolePreviewSettings {\n /** The name used instead of `name` in a preview. Same rules as `name` (1–200 characters). */\n previewName?: string\n /**\n * `false` leaves this role out of the preview: its reference images are not\n * sent, not prepared and not charged, and a `{role:N}` naming it reads as its\n * `previewName`, else its `name`. Default `true`. A preview with every role\n * left out (always refused, even with a prompt), or with no role kept in it\n * that has images and no pre / post prompt, answers 400 `no_roles_in_preview`.\n */\n inPreview?: boolean\n}\n\n/** A person in the video to recast. */\nexport interface CastSwapPersonRole extends CastSwapRolePreviewSettings {\n kind: \"person\"\n /** How the person is told apart in the video, e.g. `\"the woman that attacks\"`. */\n name: string\n /** 0–3 images of ONE person. Empty or `null` keeps the original person. */\n images: string[] | null\n /** Body from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Outfit from the references or the video. Default `\"new\"`. */\n outfit?: CastSwapTraitSource\n /** Hairstyle and haircut from the references or the video. Default `\"new\"`. */\n hair?: CastSwapTraitSource\n}\n\n/** The place the video happens in. */\nexport interface CastSwapLocationRole extends CastSwapRolePreviewSettings {\n kind: \"location\"\n /** How the place is named. Default `\"the setting\"`. */\n name?: string\n /** 0–3 images of ONE place. Empty or `null` keeps the original place. */\n images: string[] | null\n}\n\n/** An animal in the video to recast. */\nexport interface CastSwapPetRole extends CastSwapRolePreviewSettings {\n kind: \"pet\"\n /** How the animal is told apart in the video, e.g. `\"the dog\"`. */\n name: string\n /** 0–3 images of ONE animal. Empty or `null` keeps the original animal. */\n images: string[] | null\n /** Body (shape, size and build) from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Coat (fur, colors and markings) from the references or the video. Default `\"new\"`. */\n coat?: CastSwapTraitSource\n}\n\n/** An object in the video to recast. */\nexport interface CastSwapProductRole extends CastSwapRolePreviewSettings {\n kind: \"product\"\n /** How the object is told apart in the video, e.g. `\"the can\"`. */\n name: string\n /** 0–3 images of ONE product. Empty or `null` keeps the original object. */\n images: string[] | null\n /** Shape and proportions from the references or the video. Default `\"new\"`. */\n shape?: CastSwapTraitSource\n /** Finish (colors, materials, label and markings) from the references or the video. Default `\"new\"`. */\n finish?: CastSwapTraitSource\n}\n\nexport type CastSwapRole = CastSwapPersonRole | CastSwapLocationRole | CastSwapPetRole | CastSwapProductRole\n\n/**\n * A fixed reference: 1–3 images of ONE thing that no role replaces, and the\n * line that says what it is (`\"the glass she drinks from\"`). Sent as given,\n * never prepared; its images count toward the 30.\n */\nexport interface CastSwapReference {\n /** 1–3 http(s) image URLs of one thing. */\n images: string[]\n /**\n * What it is, 1–500 characters. `{image}` in the line stands for this\n * reference's first image (`\"Use {image} for the sky\"`); a line without it\n * gets it appended. A `{role:N}` or a raw `{image:` / `{video:` / `{audio:`\n * token answers 400.\n */\n line: string\n}\n\n/**\n * @deprecated Nodaro sets this per engine; a run's `faceMasking` is ignored.\n */\nexport interface CastSwapFaceMaskingZone {\n leftPct?: number\n rightPct?: number\n topPct?: number\n bottomPct?: number\n}\n\n/**\n * @deprecated Nodaro sets how the clip is prepared for the video model, per\n * engine; a run cannot change it. A `faceMasking` sent is accepted and\n * ignored (no error), so older code keeps working unchanged.\n */\nexport interface CastSwapFaceMasking {\n mode: \"off\" | \"always\" | \"auto\"\n fill?: \"blur\" | \"depth\"\n minFaceHeightPct?: number\n maxFaceHeightPct?: number\n zone?: CastSwapFaceMaskingZone | null\n blurStrengthPct?: number\n threshold?: number\n}\n\n/** The body of `POST /v1/cast-swap` and `POST /v1/cast-swap/estimate`. */\nexport interface CastSwapParams {\n /** The source clip, 4–30 seconds. */\n videoUrl: string\n /**\n * Who and what to swap: at most 6 person roles, 1 location role, 3 pet roles\n * and 3 product roles, with at most 30 images in all. A role with no images\n * is skipped (that subject or place stays as in the video). At least one role\n * with images, or a `prePrompt` or `postPrompt`, is required.\n */\n roles: CastSwapRole[]\n /**\n * Fixed references (at most 5): things the video should show that no role\n * replaces, each with the line that names it. Their images count toward the\n * 30. A reference alone is enough for a run (no role needs images).\n */\n references?: CastSwapReference[]\n /**\n * Your own words placed at the start of the prompt, before the role\n * instructions; at most 4,000 characters. Mention a role as `{role:N}`, as in\n * `postPrompt`; the same 400 refusals apply (an N outside 1..`roles.length`,\n * a raw `{image:` / `{video:` / `{audio:` token).\n */\n prePrompt?: string\n /**\n * Extra instructions in your own words, at most 4,000 characters. Mention a\n * role as `{role:N}`, where N is its 1-based position in `roles`\n * (`{role:1}` is `roles[0]`; empty roles count).\n *\n * The route answers 400, before charging, for an N outside 1..`roles.length`,\n * for a raw `{image:` / `{video:` / `{audio:` token in the pre or post prompt\n * or a role's `name`, for a clip outside 4–30 s, and for a preview past the clip's\n * end (`previewStart + 4` > its length).\n */\n postPrompt?: string\n /** `true` runs on 4 seconds of the clip, starting at `previewStart`: a cheap check of the roles and choices. */\n preview?: boolean\n /** Where the preview starts, in seconds. Default 0. */\n previewStart?: number\n /**\n * The engine (see {@link CastSwapEngine}). Default `\"motion-prism\"`. The job\n * records it in `input_data.engine`, and a completed job's output in its\n * `engine`. The ids an older client sent ({@link CastSwapEngineLegacyId})\n * are still accepted.\n */\n engine?: CastSwapEngine | CastSwapEngineLegacyId\n /**\n * How the run follows the clip (see {@link CastSwapStyle}). Default\n * `\"precise\"`; the job records it in `input_data.style`.\n */\n style?: CastSwapStyle\n /**\n * Nodaro Motion Pulse only (Prism ignores it): which end of the clip is cut to\n * whole seconds (see {@link CastSwapMotionLength}). Default `\"cut-end\"`.\n */\n motionLength?: CastSwapMotionLength\n /** @deprecated use {@link motionLength} (still accepted). */\n klingLength?: CastSwapKlingLength\n /**\n * The output resolution. Nodaro Motion Prism: `\"480p\"` (default), `\"720p\"` or\n * `\"1080p\"`. Nodaro Motion Pulse: `\"720p\"` (default) or `\"1080p\"`; `\"480p\"`\n * answers 400.\n */\n resolution?: \"480p\" | \"720p\" | \"1080p\"\n /**\n * Render as a draft (Nodaro Motion Prism only). Defaults to `true` at 480p and\n * `false` above it; `true` with `\"720p\"` or `\"1080p\"` answers 400 (draft is\n * 480p only). Nodaro Motion Pulse has no draft: `true` answers 400\n * `draft_unsupported`.\n */\n draft?: boolean\n /**\n * Turn each person, pet and product role's photos into one clean reference\n * picture before the video (extra credits, shown in `breakdown.references`;\n * about a minute longer; falls back to your own photos if it fails).\n * Default `true`.\n */\n prepareReferences?: boolean\n /**\n * Ignored: Nodaro sets how the clip is prepared, per engine. Accepted (no\n * error) so older code keeps working.\n * @deprecated leave it out.\n */\n faceMasking?: CastSwapFaceMasking\n /**\n * `\"draft\"` means 480p draft.\n * @deprecated use `resolution` + `draft`.\n */\n quality?: \"draft\"\n /** A generation session to file the result in. */\n sessionId?: string\n /** The client app that sent the run (stored on the job as `input_data.origin`). */\n origin?: string\n}\n\n/** What a run would cost, in credits. */\nexport interface CastSwapEstimate {\n /**\n * The engine the run would use, by its public id (absent from an older\n * server = `\"motion-prism\"`). An id an older server answers is read as the\n * public id it names.\n */\n engine?: CastSwapEngine\n /**\n * What is held when the run starts. The run is charged what it actually\n * costs, which is expected to be `expectedCredits`.\n */\n totalCredits: number\n /**\n * The charge the run is expected to come to. Never above `totalCredits`\n * (on Nodaro Motion Pulse it equals it: Pulse renders exactly the length\n * asked for, so the hold is what it settles at). Absent from an older\n * server: read `totalCredits` then.\n */\n expectedCredits?: number\n /**\n * The parts of the quote, by name, for display only:\n * - `base`: the run itself (its base fee). A server before Cast Swap 0.396.0\n * names it `castSwap` instead: read `base`, else `castSwap`;\n * - `references`: preparing the reference pictures (0 when\n * `prepareReferences` is off or there is nothing to prepare);\n * - `motion`: what the video holds (on Nodaro Motion Pulse, what it costs);\n * - `motionExpected`: what the video is expected to be charged, never above\n * `motion` (Nodaro Motion Prism);\n * - `privacy`: preparing the clip, when the engine's setting does. In both\n * totals when it always runs; outside both when it is the retry\n * (`privacyCredits`).\n *\n * `motion` and `motionExpected` are alternatives, so the parts sum to more\n * than either total: read `totalCredits` and `expectedCredits`, never the\n * sum. Other parts may appear.\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n references: number\n motion?: number\n motionExpected?: number\n privacy?: number\n } & Record<string, number>\n /**\n * The extra credits charged only if the video model refuses the clip and\n * the run is retried (Nodaro's setting for the engine decides whether it\n * does). Not in `totalCredits` or `expectedCredits`; `run()` needs credits\n * for both the hold and this (else 402).\n */\n privacyCredits?: number\n /** @deprecated read {@link privacyCredits} (an older server answered this name). */\n maskingCredits?: number\n /**\n * `true` when the video is made at Auto length (every Nodaro Motion Prism\n * run): the final charge is expected to come out lower than `totalCredits`,\n * at about `expectedCredits`. `false` on Nodaro Motion Pulse.\n */\n settlesLower: boolean\n}\n\n/** Per-call options for {@link CastSwapResource.run}. */\nexport interface CastSwapRunOptions {\n /**\n * Sent as the `Idempotency-Key` header, unchanged (the SDK checks nothing;\n * an empty string sends no header, like no key).\n * The server takes 8–200 characters and answers 400 for any other length.\n * Reuse the same value when retrying the same run: within about 10 s the\n * repeat answers 200 `{ jobId, deduped: true }`, later 202 with the first\n * run's `jobId`. Nothing new is started or charged.\n */\n idempotencyKey?: string\n}\n\n/**\n * What a Full Quality version would be: `\"same-take\"` re-renders a Nodaro\n * Motion Prism draft's own take at 1080p; `\"new-take\"` makes a new Nodaro Motion Pulse take at\n * 1080p from a 720p run's inputs (it will not match the 720p run frame for\n * frame). The 720p run or draft stays either way.\n */\nexport type CastSwapFullQualityKind = \"same-take\" | \"new-take\"\n\n/**\n * What a Full Quality version of a run would cost\n * (`POST /v1/cast-swap/:jobId/full-quality/estimate`): a Nodaro Motion Prism\n * draft, or a completed Nodaro Motion Pulse run at 720p.\n */\nexport interface CastSwapFullQualityEstimate {\n /**\n * Which Full Quality this is ({@link CastSwapFullQualityKind}), so it can\n * be worded right. Absent from an older server: `\"same-take\"`.\n */\n kind?: CastSwapFullQualityKind\n /** The quote in credits: `breakdown.base` plus the 1080p render (same take) or the new take. */\n totalCredits: number\n /**\n * The parts of the quote, by name, for display only: `base` (the Full\n * Quality job's own steps; a server before Cast Swap 0.396.0 names it\n * `castSwap` instead: read `base`, else `castSwap`), and `motionHd` (a same\n * take: the 1080p render, 0 when an earlier try of this draft already\n * finished that render, which is then reused) or `motion` (a new take).\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n motionHd?: number\n motion?: number\n } & Record<string, number>\n /** ISO time until which the run can be finished at Full Quality (7 days after it completed). */\n availableUntil: string\n}\n\n/** Options for {@link CastSwapResource.fullQuality}. */\nexport interface CastSwapFullQualityParams {\n /** A generation session to file the Full Quality result in. */\n sessionId?: string\n}\n\n/** The Full Quality job (`POST /v1/cast-swap/:jobId/full-quality`). */\nexport interface CastSwapFullQualityResult {\n jobId: string\n /** `true` when this run's Full Quality was already running or done: that job is answered, nothing new is started or charged. */\n existing?: boolean\n}\n\n/**\n * The `code` of a Full Quality refusal (`NodaroError.code`), all before\n * anything is charged:\n * - `unauthorized` (401): no authenticated user;\n * - `not_found` (404): not your job, or not a Nodaro Motion run; also a\n * `sessionId` you may not use;\n * - `not_completed` (409): the run has not finished;\n * - `not_a_draft` (409): the run is neither a Nodaro Motion Prism draft nor a\n * Nodaro Motion Pulse run at 720p (a Pulse run at 1080p is already Full Quality);\n * - `draft_expired` (410): more than 7 days after the draft completed, or\n * the draft can no longer be finished at Full Quality;\n * - `full_quality_pending` (409, `details.retryable: true`): not final — an\n * earlier try's 1080p render of this draft is being reviewed, or has not\n * started yet; try again later (once the review ends). The only refusal\n * that ends on its own;\n * - `full_quality_unavailable` (409): final — nothing kept to re-render, no\n * readable completion time, or the 1080p finalize refuses this draft; on\n * the start only, also \"failed too many times\" (every try failed) or no\n * try can be started for this run;\n * - `insufficient_credits` (402), or in a workspace `budget_exceeded`,\n * `member_cap_exceeded` or `user_allowance_exceeded`;\n * - `job_blocked` (422): the request was blocked by the job policy;\n * - `job_read_failed` (503, retryable), `estimate_unavailable` (503, try\n * again shortly), `host_too_old` (503).\n *\n * Open-ended: a code not listed here may still arrive.\n */\nexport type CastSwapFullQualityRefusalCode =\n | \"unauthorized\"\n | \"not_found\"\n | \"not_completed\"\n | \"not_a_draft\"\n | \"draft_expired\"\n | \"full_quality_pending\"\n | \"full_quality_unavailable\"\n | \"insufficient_credits\"\n | \"budget_exceeded\"\n | \"member_cap_exceeded\"\n | \"user_allowance_exceeded\"\n | \"job_blocked\"\n | \"job_read_failed\"\n | \"estimate_unavailable\"\n | \"host_too_old\"\n | (string & {})\n\nexport class CastSwapResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Start a Nodaro Motion run (`POST /v1/cast-swap`, 202 `{ jobId }`). Returns the\n * job to follow. With `options.idempotencyKey` (sent as the\n * `Idempotency-Key` header; 8–200 characters, else 400) a repeat with the\n * same key within about 10 s answers 200 `{ jobId, deduped: true }`, a later\n * one 202 with the first run's `jobId`; nothing new starts.\n */\n run(params: CastSwapParams, options?: CastSwapRunOptions): Promise<{ jobId: string; deduped?: boolean }> {\n return this.client.request(\"POST\", \"/v1/cast-swap\", {\n body: params,\n ...(options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}),\n })\n }\n\n /** Quote a run before starting it (`POST /v1/cast-swap/estimate`); spends nothing. */\n async estimate(params: CastSwapParams): Promise<CastSwapEstimate> {\n const quote = await this.client.request<CastSwapEstimate>(\"POST\", \"/v1/cast-swap/estimate\", { body: params })\n // An older server names the engine by an earlier id: answered as the public id it names.\n const engine = nodaroMotionEngineFrom(quote?.engine)\n return engine && engine !== quote.engine ? { ...quote, engine } : quote\n }\n\n /**\n * Quote finishing a run at Full Quality (`POST\n * /v1/cast-swap/:jobId/full-quality/estimate`); spends nothing. `jobId` is a\n * finished Nodaro Motion Prism DRAFT run, or a finished Nodaro Motion Pulse\n * run at 720p (a Nodaro Motion or trend run); the quote's `kind` says whether it is the same take\n * re-rendered or a new take. The quote\n * does not look for a Full Quality already running: when one is,\n * {@link fullQuality} answers it (`existing: true`) and charges nothing.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQualityEstimate(jobId: string): Promise<CastSwapFullQualityEstimate> {\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality/estimate`, { body: {} })\n }\n\n /**\n * Finish a run at Full Quality (`POST /v1/cast-swap/:jobId/full-quality`):\n * at 1080p, with the clip's audio, as a new job linked to the run — a\n * Nodaro Motion Prism draft's own take re-rendered, or a new Nodaro Motion Pulse take from a\n * 720p run's inputs (the quote's `kind`). SPENDS CREDITS: quote it first with\n * {@link fullQualityEstimate}. Answers 202 `{ jobId }`, or 200\n * `{ jobId, existing: true }` when this run's Full Quality is already\n * running or done (one per run; a failed one may be asked again). Follow\n * the job with `client.jobs.get(jobId)`. No `Idempotency-Key` is taken: the\n * server keys the job by the draft. The new job keeps the draft's origin.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQuality(jobId: string, params: CastSwapFullQualityParams = {}): Promise<CastSwapFullQualityResult> {\n const body = params.sessionId !== undefined ? { sessionId: params.sessionId } : {}\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality`, { body })\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/resources/cast-swap.ts"],"names":["nodaroMotionEngineFrom"],"mappings":";;;;;AA8eO,IAAM,mBAAN,MAAuB;AAAA,EAC5B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASpB,GAAA,CAAI,QAAwB,OAAA,EAA6E;AACvG,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,eAAA,EAAiB;AAAA,MAClD,IAAA,EAAM,MAAA;AAAA,MACN,GAAI,OAAA,EAAS,cAAA,GAAiB,EAAE,OAAA,EAAS,EAAE,iBAAA,EAAmB,OAAA,CAAQ,cAAA,EAAe,EAAE,GAAI;AAAC,KAC7F,CAAA;AAAA,EACH;AAAA;AAAA,EAGA,MAAM,SAAS,MAAA,EAAmD;AAChE,IAAA,MAAM,KAAA,GAAQ,MAAM,IAAA,CAAK,MAAA,CAAO,OAAA,CAA0B,QAAQ,wBAAA,EAA0B,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAE5G,IAAA,MAAM,MAAA,GAASA,6BAAA,CAAuB,KAAA,EAAO,MAAM,CAAA;AACnD,IAAA,OAAO,MAAA,IAAU,WAAW,KAAA,CAAM,MAAA,GAAS,EAAE,GAAG,KAAA,EAAO,QAAO,GAAI,KAAA;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,oBAAoB,KAAA,EAAqD;AACvE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,sBAAA,CAAA,EAA0B,EAAE,IAAA,EAAM,IAAI,CAAA;AAAA,EACrH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,WAAA,CAAY,KAAA,EAAe,MAAA,GAAoC,EAAC,EAAuC;AACrG,IAAA,MAAM,IAAA,GAAO,OAAO,SAAA,KAAc,MAAA,GAAY,EAAE,SAAA,EAAW,MAAA,CAAO,SAAA,EAAU,GAAI,EAAC;AACjF,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,MAAA,EAAQ,CAAA,cAAA,EAAiB,kBAAA,CAAmB,KAAK,CAAC,CAAA,aAAA,CAAA,EAAiB,EAAE,IAAA,EAAM,CAAA;AAAA,EACxG;AACF","file":"chunk-GJH73EGF.cjs","sourcesContent":["import { nodaroMotionEngineFrom } from \"@nodaro/shared/models\"\nimport type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Nodaro Motion (the `castSwap` resource; routes `/v1/cast-swap`) — replace\n * the people, pets, products and/or the location in a short video with your\n * own references, keeping its motion, framing, timing and sound (the clip's\n * audio is kept, and the result is the clip's length).\n *\n * Before the video, each person, pet and product role's photos are turned\n * into one clean reference picture by an image model. This costs extra\n * credits (`breakdown.references` in the estimate), charged when it runs, even\n * if the video then fails; it adds about a minute, falls back to your own\n * photos if it fails, and is turned off with `prepareReferences: false`.\n * Locations are not prepared.\n *\n * Engines: a run is made on Nodaro Motion Prism (`engine` left out, or\n * `\"motion-prism\"`) or Nodaro Motion Pulse (`\"motion-pulse\"`). Pulse renders 720p\n * (its default) or 1080p and has no draft; it makes a new take guided by the\n * clip and pictures, so its Full Quality is a new take at 1080p rather than\n * the same take re-rendered (`CastSwapFullQualityEstimate.kind`).\n *\n * How the clip is prepared for the video model (for one, whether faces are\n * hidden first, and whether a refused clip is retried) is set by Nodaro for\n * each engine; a run cannot change it. `faceMasking` is no longer read\n * (deprecated: accepted and ignored).\n *\n * Cloud edition only: `/v1/cast-swap` is served by the cloud plugin and 404s\n * on self-hosted installs. `run()` answers 202 with a job id; follow it with\n * `client.jobs.get(jobId)` / `client.jobs.getStatus(jobId)` like any other job.\n *\n * Repeats: pass `{ idempotencyKey }` to `run()` and it is sent as the\n * `Idempotency-Key` header. A repeat with the same key within the credit\n * guard's dedup window (about 10 s) answers 200 `{ jobId, deduped: true }` with\n * an `X-Dedup-Hit` header; a later one answers 202 with the first run's\n * `jobId`. Nothing new is started or charged.\n *\n * Refusals (thrown as a `NodaroError` subclass; body `{ error: { code, message } }`), before\n * anything is charged: 400 `validation_error` (the body: no role with images,\n * no reference and no `prePrompt` or `postPrompt`, more roles of a kind\n * than allowed, more than 30 images in all, `draft: true` above 480p, a\n * `prePrompt` or `postPrompt` over 4,000 characters); on Nodaro Motion Pulse,\n * `draft_unsupported` (`draft: true`), `resolution_unsupported` (480p),\n * `output_format_unsupported` (a MOV edit output) and `too_many_images` (more\n * than 10 images in the run, across every role and fixed reference);\n * `raw_reference_token` (also in a reference's `line`),\n * `invalid_role_mention` (also any `{role:N}` in a reference's `line`),\n * `unsafe_url`, `video_unreadable`, `clip_out_of_range` (4–30 s),\n * `preview_out_of_range`, `no_roles_in_preview` (a preview with every role\n * `inPreview: false`, always refused even with a prompt, or with no role kept\n * in it that has images and no `prePrompt` or `postPrompt`), `prompt_too_long`\n * (the prompt would build too long: a `{role:N}` reads as the role's name when\n * it sends no images; Nodaro Motion Pulse's cap is 8,000 characters); 401; 402 `insufficient_credits` (`run()` only); 404\n * (a `sessionId` you may not use, `run()` only); 422 `job_blocked` (`run()`\n * only); 503 `host_too_old` (both); 503 `estimate_unavailable` (`estimate()`\n * only).\n */\n\n/**\n * The engine a Nodaro Motion run is made on, by its public id. Left out =\n * `\"motion-prism\"`.\n *\n * - `\"motion-prism\"` (Nodaro Motion Prism): 480p (the default, a draft unless\n * `draft: false`), 720p or 1080p; Full Quality re-renders a draft's own take\n * at 1080p.\n * - `\"motion-pulse\"` (Nodaro Motion Pulse): 720p (the default) or 1080p, never a\n * draft (`draft: true` answers 400 `draft_unsupported`); Full Quality makes a\n * new take at 1080p from a completed 720p run's inputs. A preview is still\n * 4 s from `previewStart`.\n */\nexport type CastSwapEngine = \"motion-prism\" | \"motion-pulse\"\n\n/**\n * The engine ids an older client sent: the earlier public ids (`\"motion-pro\"`\n * = `\"motion-prism\"`, `\"motion-lite\"` = `\"motion-pulse\"`) and the internal\n * ones (`\"seedance-2-5\"`, `\"kling-4\"`). Still accepted in a request; never\n * returned.\n * @deprecated use {@link CastSwapEngine}.\n */\nexport type CastSwapEngineLegacyId = \"motion-pro\" | \"motion-lite\" | \"seedance-2-5\" | \"kling-4\"\n\n/**\n * How a run follows its clip. Left out = `\"precise\"`.\n *\n * - `\"precise\"`: follows the clip exactly.\n * - `\"motion\"`: follows the clip's movement and takes the looks from your\n * photos, more freely than `\"precise\"`. Its price may differ from\n * `\"precise\"`'s: the estimate shows the exact price.\n */\nexport type CastSwapStyle = \"precise\" | \"motion\"\n\n/**\n * Where a Nodaro Motion Pulse run cuts the clip to whole seconds (Pulse renders\n * whole seconds; asked for more than the clip, it would stretch the motion):\n * - `\"cut-end\"` (the default): drop the fraction of a second at its end;\n * - `\"cut-start\"`: drop it at its start.\n */\nexport type CastSwapMotionLength = \"cut-end\" | \"cut-start\"\n\n/** @deprecated use {@link CastSwapMotionLength}. */\nexport type CastSwapKlingLength = CastSwapMotionLength\n\n/** Whether a swapped subject takes this trait from the references (`\"new\"`) or keeps the video's (`\"original\"`). */\nexport type CastSwapTraitSource = \"new\" | \"original\"\n\n/**\n * Preview-only settings, on every role kind; a full run (`preview` not `true`)\n * ignores both.\n */\nexport interface CastSwapRolePreviewSettings {\n /** The name used instead of `name` in a preview. Same rules as `name` (1–200 characters). */\n previewName?: string\n /**\n * `false` leaves this role out of the preview: its reference images are not\n * sent, not prepared and not charged, and a `{role:N}` naming it reads as its\n * `previewName`, else its `name`. Default `true`. A preview with every role\n * left out (always refused, even with a prompt), or with no role kept in it\n * that has images and no pre / post prompt, answers 400 `no_roles_in_preview`.\n */\n inPreview?: boolean\n}\n\n/** A person in the video to recast. */\nexport interface CastSwapPersonRole extends CastSwapRolePreviewSettings {\n kind: \"person\"\n /** How the person is told apart in the video, e.g. `\"the woman that attacks\"`. */\n name: string\n /** 0–3 images of ONE person. Empty or `null` keeps the original person. */\n images: string[] | null\n /** Body from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Outfit from the references or the video. Default `\"new\"`. */\n outfit?: CastSwapTraitSource\n /** Hairstyle and haircut from the references or the video. Default `\"new\"`. */\n hair?: CastSwapTraitSource\n}\n\n/** The place the video happens in. */\nexport interface CastSwapLocationRole extends CastSwapRolePreviewSettings {\n kind: \"location\"\n /** How the place is named. Default `\"the setting\"`. */\n name?: string\n /** 0–3 images of ONE place. Empty or `null` keeps the original place. */\n images: string[] | null\n}\n\n/** An animal in the video to recast. */\nexport interface CastSwapPetRole extends CastSwapRolePreviewSettings {\n kind: \"pet\"\n /** How the animal is told apart in the video, e.g. `\"the dog\"`. */\n name: string\n /** 0–3 images of ONE animal. Empty or `null` keeps the original animal. */\n images: string[] | null\n /** Body (shape, size and build) from the references or the video. Default `\"new\"`. */\n body?: CastSwapTraitSource\n /** Coat (fur, colors and markings) from the references or the video. Default `\"new\"`. */\n coat?: CastSwapTraitSource\n}\n\n/** An object in the video to recast. */\nexport interface CastSwapProductRole extends CastSwapRolePreviewSettings {\n kind: \"product\"\n /** How the object is told apart in the video, e.g. `\"the can\"`. */\n name: string\n /** 0–3 images of ONE product. Empty or `null` keeps the original object. */\n images: string[] | null\n /** Shape and proportions from the references or the video. Default `\"new\"`. */\n shape?: CastSwapTraitSource\n /** Finish (colors, materials, label and markings) from the references or the video. Default `\"new\"`. */\n finish?: CastSwapTraitSource\n}\n\nexport type CastSwapRole = CastSwapPersonRole | CastSwapLocationRole | CastSwapPetRole | CastSwapProductRole\n\n/**\n * A fixed reference: 1–3 images of ONE thing that no role replaces, and the\n * line that says what it is (`\"the glass she drinks from\"`). Sent as given,\n * never prepared; its images count toward the 30.\n */\nexport interface CastSwapReference {\n /** 1–3 http(s) image URLs of one thing. */\n images: string[]\n /**\n * What it is, 1–500 characters. `{image}` in the line stands for this\n * reference's first image (`\"Use {image} for the sky\"`); a line without it\n * gets it appended. A `{role:N}` or a raw `{image:` / `{video:` / `{audio:`\n * token answers 400.\n */\n line: string\n}\n\n/**\n * @deprecated Nodaro sets this per engine; a run's `faceMasking` is ignored.\n */\nexport interface CastSwapFaceMaskingZone {\n leftPct?: number\n rightPct?: number\n topPct?: number\n bottomPct?: number\n}\n\n/**\n * @deprecated Nodaro sets how the clip is prepared for the video model, per\n * engine; a run cannot change it. A `faceMasking` sent is accepted and\n * ignored (no error), so older code keeps working unchanged.\n */\nexport interface CastSwapFaceMasking {\n mode: \"off\" | \"always\" | \"auto\"\n fill?: \"blur\" | \"depth\"\n minFaceHeightPct?: number\n maxFaceHeightPct?: number\n zone?: CastSwapFaceMaskingZone | null\n blurStrengthPct?: number\n threshold?: number\n}\n\n/** The body of `POST /v1/cast-swap` and `POST /v1/cast-swap/estimate`. */\nexport interface CastSwapParams {\n /** The source clip, 4–30 seconds. */\n videoUrl: string\n /**\n * Who and what to swap: at most 6 person roles, 1 location role, 3 pet roles\n * and 3 product roles, with at most 30 images in all. A role with no images\n * is skipped (that subject or place stays as in the video). At least one role\n * with images, or a `prePrompt` or `postPrompt`, is required.\n */\n roles: CastSwapRole[]\n /**\n * Fixed references (at most 5): things the video should show that no role\n * replaces, each with the line that names it. Their images count toward the\n * 30. A reference alone is enough for a run (no role needs images).\n */\n references?: CastSwapReference[]\n /**\n * Your own words placed at the start of the prompt, before the role\n * instructions; at most 4,000 characters. Mention a role as `{role:N}`, as in\n * `postPrompt`; the same 400 refusals apply (an N outside 1..`roles.length`,\n * a raw `{image:` / `{video:` / `{audio:` token).\n */\n prePrompt?: string\n /**\n * Extra instructions in your own words, at most 4,000 characters. Mention a\n * role as `{role:N}`, where N is its 1-based position in `roles`\n * (`{role:1}` is `roles[0]`; empty roles count).\n *\n * The route answers 400, before charging, for an N outside 1..`roles.length`,\n * for a raw `{image:` / `{video:` / `{audio:` token in the pre or post prompt\n * or a role's `name`, for a clip outside 4–30 s, and for a preview past the clip's\n * end (`previewStart + 4` > its length).\n */\n postPrompt?: string\n /** `true` runs on 4 seconds of the clip, starting at `previewStart`: a cheap check of the roles and choices. */\n preview?: boolean\n /** Where the preview starts, in seconds. Default 0. */\n previewStart?: number\n /**\n * The engine (see {@link CastSwapEngine}). Default `\"motion-prism\"`. The job\n * records it in `input_data.engine`, and a completed job's output in its\n * `engine`. The ids an older client sent ({@link CastSwapEngineLegacyId})\n * are still accepted.\n */\n engine?: CastSwapEngine | CastSwapEngineLegacyId\n /**\n * How the run follows the clip (see {@link CastSwapStyle}). Default\n * `\"precise\"`; the job records it in `input_data.style`.\n */\n style?: CastSwapStyle\n /**\n * Flex only (`style: \"motion\"`, a direct run): an art style that restyles\n * the whole video, as a `direction.style` id of the platform's `style`\n * picker catalog (the same ids an image's `direction.style` takes); the\n * platform words it. Refused with 400 `unknown_art_style` (not in the\n * catalog), `art_style_not_supported` (a saved moodboard, `moodboard:…`)\n * or `art_style_needs_flex` (Precise, a trend run). It never changes the\n * price. The job records it in `input_data.direction`.\n */\n direction?: { style: string }\n /**\n * Nodaro Motion Pulse only (Prism ignores it): which end of the clip is cut to\n * whole seconds (see {@link CastSwapMotionLength}). Default `\"cut-end\"`.\n */\n motionLength?: CastSwapMotionLength\n /** @deprecated use {@link motionLength} (still accepted). */\n klingLength?: CastSwapKlingLength\n /**\n * The output resolution. Nodaro Motion Prism: `\"480p\"` (default), `\"720p\"` or\n * `\"1080p\"`. Nodaro Motion Pulse: `\"720p\"` (default) or `\"1080p\"`; `\"480p\"`\n * answers 400.\n */\n resolution?: \"480p\" | \"720p\" | \"1080p\"\n /**\n * Render as a draft (Nodaro Motion Prism only). Defaults to `true` at 480p and\n * `false` above it; `true` with `\"720p\"` or `\"1080p\"` answers 400 (draft is\n * 480p only). Nodaro Motion Pulse has no draft: `true` answers 400\n * `draft_unsupported`.\n */\n draft?: boolean\n /**\n * Turn each person, pet and product role's photos into one clean reference\n * picture before the video (extra credits, shown in `breakdown.references`;\n * about a minute longer; falls back to your own photos if it fails).\n * Default `true`.\n */\n prepareReferences?: boolean\n /**\n * Ignored: Nodaro sets how the clip is prepared, per engine. Accepted (no\n * error) so older code keeps working.\n * @deprecated leave it out.\n */\n faceMasking?: CastSwapFaceMasking\n /**\n * `\"draft\"` means 480p draft.\n * @deprecated use `resolution` + `draft`.\n */\n quality?: \"draft\"\n /** A generation session to file the result in. */\n sessionId?: string\n /** The client app that sent the run (stored on the job as `input_data.origin`). */\n origin?: string\n}\n\n/** What a run would cost, in credits. */\nexport interface CastSwapEstimate {\n /**\n * The engine the run would use, by its public id (absent from an older\n * server = `\"motion-prism\"`). An id an older server answers is read as the\n * public id it names.\n */\n engine?: CastSwapEngine\n /**\n * What is held when the run starts. The run is charged what it actually\n * costs, which is expected to be `expectedCredits`.\n */\n totalCredits: number\n /**\n * The charge the run is expected to come to. Never above `totalCredits`\n * (on Nodaro Motion Pulse it equals it: Pulse renders exactly the length\n * asked for, so the hold is what it settles at). Absent from an older\n * server: read `totalCredits` then.\n */\n expectedCredits?: number\n /**\n * The parts of the quote, by name, for display only:\n * - `base`: the run itself (its base fee). A server before Cast Swap 0.396.0\n * names it `castSwap` instead: read `base`, else `castSwap`;\n * - `references`: preparing the reference pictures (0 when\n * `prepareReferences` is off or there is nothing to prepare);\n * - `motion`: what the video holds (on Nodaro Motion Pulse, what it costs);\n * - `motionExpected`: what the video is expected to be charged, never above\n * `motion` (Nodaro Motion Prism);\n * - `privacy`: preparing the clip, when the engine's setting does. In both\n * totals when it always runs; outside both when it is the retry\n * (`privacyCredits`).\n *\n * `motion` and `motionExpected` are alternatives, so the parts sum to more\n * than either total: read `totalCredits` and `expectedCredits`, never the\n * sum. Other parts may appear.\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n references: number\n motion?: number\n motionExpected?: number\n privacy?: number\n } & Record<string, number>\n /**\n * The extra credits charged only if the video model refuses the clip and\n * the run is retried (Nodaro's setting for the engine decides whether it\n * does). Not in `totalCredits` or `expectedCredits`; `run()` needs credits\n * for both the hold and this (else 402).\n */\n privacyCredits?: number\n /** @deprecated read {@link privacyCredits} (an older server answered this name). */\n maskingCredits?: number\n /**\n * `true` when the video is made at Auto length (every Nodaro Motion Prism\n * run): the final charge is expected to come out lower than `totalCredits`,\n * at about `expectedCredits`. `false` on Nodaro Motion Pulse.\n */\n settlesLower: boolean\n}\n\n/** Per-call options for {@link CastSwapResource.run}. */\nexport interface CastSwapRunOptions {\n /**\n * Sent as the `Idempotency-Key` header, unchanged (the SDK checks nothing;\n * an empty string sends no header, like no key).\n * The server takes 8–200 characters and answers 400 for any other length.\n * Reuse the same value when retrying the same run: within about 10 s the\n * repeat answers 200 `{ jobId, deduped: true }`, later 202 with the first\n * run's `jobId`. Nothing new is started or charged.\n */\n idempotencyKey?: string\n}\n\n/**\n * What a Full Quality version would be: `\"same-take\"` re-renders a Nodaro\n * Motion Prism draft's own take at 1080p; `\"new-take\"` makes a new Nodaro Motion Pulse take at\n * 1080p from a 720p run's inputs (it will not match the 720p run frame for\n * frame). The 720p run or draft stays either way.\n */\nexport type CastSwapFullQualityKind = \"same-take\" | \"new-take\"\n\n/**\n * What a Full Quality version of a run would cost\n * (`POST /v1/cast-swap/:jobId/full-quality/estimate`): a Nodaro Motion Prism\n * draft, or a completed Nodaro Motion Pulse run at 720p.\n */\nexport interface CastSwapFullQualityEstimate {\n /**\n * Which Full Quality this is ({@link CastSwapFullQualityKind}), so it can\n * be worded right. Absent from an older server: `\"same-take\"`.\n */\n kind?: CastSwapFullQualityKind\n /** The quote in credits: `breakdown.base` plus the 1080p render (same take) or the new take. */\n totalCredits: number\n /**\n * The parts of the quote, by name, for display only: `base` (the Full\n * Quality job's own steps; a server before Cast Swap 0.396.0 names it\n * `castSwap` instead: read `base`, else `castSwap`), and `motionHd` (a same\n * take: the 1080p render, 0 when an earlier try of this draft already\n * finished that render, which is then reused) or `motion` (a new take).\n */\n breakdown: {\n base?: number\n /** @deprecated read {@link base} (an older server answered this name for the same part). */\n castSwap?: number\n motionHd?: number\n motion?: number\n } & Record<string, number>\n /** ISO time until which the run can be finished at Full Quality (7 days after it completed). */\n availableUntil: string\n}\n\n/** Options for {@link CastSwapResource.fullQuality}. */\nexport interface CastSwapFullQualityParams {\n /** A generation session to file the Full Quality result in. */\n sessionId?: string\n}\n\n/** The Full Quality job (`POST /v1/cast-swap/:jobId/full-quality`). */\nexport interface CastSwapFullQualityResult {\n jobId: string\n /** `true` when this run's Full Quality was already running or done: that job is answered, nothing new is started or charged. */\n existing?: boolean\n}\n\n/**\n * The `code` of a Full Quality refusal (`NodaroError.code`), all before\n * anything is charged:\n * - `unauthorized` (401): no authenticated user;\n * - `not_found` (404): not your job, or not a Nodaro Motion run; also a\n * `sessionId` you may not use;\n * - `not_completed` (409): the run has not finished;\n * - `not_a_draft` (409): the run is neither a Nodaro Motion Prism draft nor a\n * Nodaro Motion Pulse run at 720p (a Pulse run at 1080p is already Full Quality);\n * - `draft_expired` (410): more than 7 days after the draft completed, or\n * the draft can no longer be finished at Full Quality;\n * - `full_quality_pending` (409, `details.retryable: true`): not final — an\n * earlier try's 1080p render of this draft is being reviewed, or has not\n * started yet; try again later (once the review ends). The only refusal\n * that ends on its own;\n * - `full_quality_unavailable` (409): final — nothing kept to re-render, no\n * readable completion time, or the 1080p finalize refuses this draft; on\n * the start only, also \"failed too many times\" (every try failed) or no\n * try can be started for this run;\n * - `insufficient_credits` (402), or in a workspace `budget_exceeded`,\n * `member_cap_exceeded` or `user_allowance_exceeded`;\n * - `job_blocked` (422): the request was blocked by the job policy;\n * - `job_read_failed` (503, retryable), `estimate_unavailable` (503, try\n * again shortly), `host_too_old` (503).\n *\n * Open-ended: a code not listed here may still arrive.\n */\nexport type CastSwapFullQualityRefusalCode =\n | \"unauthorized\"\n | \"not_found\"\n | \"not_completed\"\n | \"not_a_draft\"\n | \"draft_expired\"\n | \"full_quality_pending\"\n | \"full_quality_unavailable\"\n | \"insufficient_credits\"\n | \"budget_exceeded\"\n | \"member_cap_exceeded\"\n | \"user_allowance_exceeded\"\n | \"job_blocked\"\n | \"job_read_failed\"\n | \"estimate_unavailable\"\n | \"host_too_old\"\n | (string & {})\n\nexport class CastSwapResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Start a Nodaro Motion run (`POST /v1/cast-swap`, 202 `{ jobId }`). Returns the\n * job to follow. With `options.idempotencyKey` (sent as the\n * `Idempotency-Key` header; 8–200 characters, else 400) a repeat with the\n * same key within about 10 s answers 200 `{ jobId, deduped: true }`, a later\n * one 202 with the first run's `jobId`; nothing new starts.\n */\n run(params: CastSwapParams, options?: CastSwapRunOptions): Promise<{ jobId: string; deduped?: boolean }> {\n return this.client.request(\"POST\", \"/v1/cast-swap\", {\n body: params,\n ...(options?.idempotencyKey ? { headers: { \"Idempotency-Key\": options.idempotencyKey } } : {}),\n })\n }\n\n /** Quote a run before starting it (`POST /v1/cast-swap/estimate`); spends nothing. */\n async estimate(params: CastSwapParams): Promise<CastSwapEstimate> {\n const quote = await this.client.request<CastSwapEstimate>(\"POST\", \"/v1/cast-swap/estimate\", { body: params })\n // An older server names the engine by an earlier id: answered as the public id it names.\n const engine = nodaroMotionEngineFrom(quote?.engine)\n return engine && engine !== quote.engine ? { ...quote, engine } : quote\n }\n\n /**\n * Quote finishing a run at Full Quality (`POST\n * /v1/cast-swap/:jobId/full-quality/estimate`); spends nothing. `jobId` is a\n * finished Nodaro Motion Prism DRAFT run, or a finished Nodaro Motion Pulse\n * run at 720p (a Nodaro Motion or trend run); the quote's `kind` says whether it is the same take\n * re-rendered or a new take. The quote\n * does not look for a Full Quality already running: when one is,\n * {@link fullQuality} answers it (`existing: true`) and charges nothing.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQualityEstimate(jobId: string): Promise<CastSwapFullQualityEstimate> {\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality/estimate`, { body: {} })\n }\n\n /**\n * Finish a run at Full Quality (`POST /v1/cast-swap/:jobId/full-quality`):\n * at 1080p, with the clip's audio, as a new job linked to the run — a\n * Nodaro Motion Prism draft's own take re-rendered, or a new Nodaro Motion Pulse take from a\n * 720p run's inputs (the quote's `kind`). SPENDS CREDITS: quote it first with\n * {@link fullQualityEstimate}. Answers 202 `{ jobId }`, or 200\n * `{ jobId, existing: true }` when this run's Full Quality is already\n * running or done (one per run; a failed one may be asked again). Follow\n * the job with `client.jobs.get(jobId)`. No `Idempotency-Key` is taken: the\n * server keys the job by the draft. The new job keeps the draft's origin.\n * Refusals: {@link CastSwapFullQualityRefusalCode}.\n */\n fullQuality(jobId: string, params: CastSwapFullQualityParams = {}): Promise<CastSwapFullQualityResult> {\n const body = params.sessionId !== undefined ? { sessionId: params.sessionId } : {}\n return this.client.request(\"POST\", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality`, { body })\n }\n}\n"]}
@@ -27,13 +27,24 @@ var UnauthorizedError = class extends NodaroError {
27
27
  }
28
28
  };
29
29
  var ForbiddenError = class extends NodaroError {
30
- constructor(message = "Forbidden", missingScope) {
31
- super(message, "forbidden", 403);
30
+ /** `code` defaults to `"forbidden"`; {@link ModelUnavailableError} passes its own. */
31
+ constructor(message = "Forbidden", missingScope, code = "forbidden") {
32
+ super(message, code, 403);
32
33
  this.missingScope = missingScope;
33
34
  this.name = "ForbiddenError";
34
35
  }
35
36
  missingScope;
36
37
  };
38
+ var MODEL_UNAVAILABLE_CODES = /* @__PURE__ */ new Set([
39
+ "model_not_available",
40
+ "model_disabled"
41
+ ]);
42
+ var ModelUnavailableError = class extends ForbiddenError {
43
+ constructor(code, message = "This model is not available") {
44
+ super(message, void 0, code);
45
+ this.name = "ModelUnavailableError";
46
+ }
47
+ };
37
48
  var NotFoundError = class extends NodaroError {
38
49
  constructor(message = "Not found") {
39
50
  super(message, "not_found", 404);
@@ -68,12 +79,14 @@ var CreditCapExceededError = class extends InsufficientCreditsError {
68
79
  }
69
80
  };
70
81
  var StorageExceededError = class extends NodaroError {
71
- constructor(message = "Storage exceeded", limitBytes) {
82
+ constructor(message = "Storage exceeded", limitBytes, reason) {
72
83
  super(message, "storage_exceeded", 413);
73
84
  this.limitBytes = limitBytes;
85
+ this.reason = reason;
74
86
  this.name = "StorageExceededError";
75
87
  }
76
88
  limitBytes;
89
+ reason;
77
90
  };
78
91
  var WorkflowConflictError = class extends NodaroError {
79
92
  constructor(message = "Workflow was updated by another writer", currentUpdatedAt, currentVersion, currentRecord, code = "workflow_conflict") {
@@ -278,6 +291,10 @@ function selectError(status, body) {
278
291
  throw new AppRunVersionChangedError(message, finite(parsed.runVersion), finite(parsed.appVersion));
279
292
  }
280
293
  if (status === 422 && code === "job_blocked") throw new JobBlockedError(read.message);
294
+ const modelCode = read.code;
295
+ if (status === 403 && modelCode !== void 0 && MODEL_UNAVAILABLE_CODES.has(modelCode)) {
296
+ throw new ModelUnavailableError(modelCode, read.message);
297
+ }
281
298
  if (status === 403 && code === "insufficient_scope") {
282
299
  throw new ForbiddenError(read.message, envelope.missingScope);
283
300
  }
@@ -293,7 +310,7 @@ function selectError(status, body) {
293
310
  }
294
311
  throw new InsufficientCreditsError(read.message, required, available, read.code ?? "insufficient_credits");
295
312
  }
296
- if (status === 413) throw new StorageExceededError(read.message, envelope.limitBytes);
313
+ if (status === 413) throw new StorageExceededError(read.message, envelope.limitBytes, read.code);
297
314
  throw new NodaroError(message, code, status);
298
315
  }
299
316
 
@@ -310,6 +327,8 @@ exports.JobBlockedError = JobBlockedError;
310
327
  exports.JobFailedError = JobFailedError;
311
328
  exports.JobHeldError = JobHeldError;
312
329
  exports.JobTimeoutError = JobTimeoutError;
330
+ exports.MODEL_UNAVAILABLE_CODES = MODEL_UNAVAILABLE_CODES;
331
+ exports.ModelUnavailableError = ModelUnavailableError;
313
332
  exports.NodaroError = NodaroError;
314
333
  exports.NotFoundError = NotFoundError;
315
334
  exports.RateLimitedError = RateLimitedError;
@@ -320,5 +339,5 @@ exports.StudioPreviewUnavailable = StudioPreviewUnavailable;
320
339
  exports.UnauthorizedError = UnauthorizedError;
321
340
  exports.WorkflowConflictError = WorkflowConflictError;
322
341
  exports.throwFromResponse = throwFromResponse;
323
- //# sourceMappingURL=chunk-FM2KM5TY.cjs.map
324
- //# sourceMappingURL=chunk-FM2KM5TY.cjs.map
342
+ //# sourceMappingURL=chunk-GSE7SB3I.cjs.map
343
+ //# sourceMappingURL=chunk-GSE7SB3I.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/errors.ts"],"names":[],"mappings":"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","file":"chunk-GSE7SB3I.cjs","sourcesContent":["import type { StudioOpsResponse } from \"./resources/studio-productions.js\"\n\nexport class NodaroError extends Error {\n /**\n * Every other field of the server's error envelope (`{ error: { code,\n * message, … } }`), as it was sent: for example a trend refusal's `slot`, a\n * publish refusal's `reasons`, a validation error's `issues`. Empty when the\n * envelope had nothing else, or for an error the SDK made itself. A copy —\n * changing it changes nothing else.\n */\n public readonly details: Readonly<Record<string, unknown>> = {}\n\n constructor(\n message: string,\n public readonly code: string,\n public readonly status: number,\n details?: Readonly<Record<string, unknown>>,\n ) {\n super(message)\n this.name = \"NodaroError\"\n if (details) this.details = { ...details }\n }\n}\n\nexport class UnauthorizedError extends NodaroError {\n constructor(message = \"Authentication required\") {\n super(message, \"unauthorized\", 401)\n this.name = \"UnauthorizedError\"\n }\n}\n\nexport class ForbiddenError extends NodaroError {\n /** `code` defaults to `\"forbidden\"`; {@link ModelUnavailableError} passes its own. */\n constructor(message = \"Forbidden\", public readonly missingScope?: string, code = \"forbidden\") {\n super(message, code, 403)\n this.name = \"ForbiddenError\"\n }\n}\n\nexport type ModelUnavailableCode = \"model_not_available\" | \"model_disabled\"\n\n/**\n * The 403 codes {@link ModelUnavailableError} carries: a model this\n * deployment does not offer (`model_not_available` — outside its edition or\n * surface, or hidden by its operator) and a model an admin switched off on\n * the models page (`model_disabled`).\n */\nexport const MODEL_UNAVAILABLE_CODES: ReadonlySet<ModelUnavailableCode> = new Set<ModelUnavailableCode>([\n \"model_not_available\",\n \"model_disabled\",\n])\n\n/**\n * HTTP 403 refusing the MODEL, not the caller: this deployment does not offer\n * it, or an admin switched it off. Answered by the credit guard before any\n * credits are held (the LLM and pipeline lanes still answer a switched-off\n * model with a 402 for now).\n * Choosing another model is the remedy — retrying, topping up or a wider\n * scope changes nothing. A {@link ForbiddenError}, so existing catches keep\n * working; `code` is the server's own code and says which. The envelope\n * names no model: what was refused is the request's own `provider` (or, for\n * a fan-out, one of its `models`).\n */\nexport class ModelUnavailableError extends ForbiddenError {\n declare readonly code: ModelUnavailableCode\n\n constructor(code: ModelUnavailableCode, message = \"This model is not available\") {\n super(message, undefined, code)\n this.name = \"ModelUnavailableError\"\n }\n}\n\nexport class NotFoundError extends NodaroError {\n constructor(message = \"Not found\") {\n super(message, \"not_found\", 404)\n this.name = \"NotFoundError\"\n }\n}\n\nexport class RateLimitedError extends NodaroError {\n constructor(message = \"Rate limited\") {\n super(message, \"rate_limited\", 429)\n this.name = \"RateLimitedError\"\n }\n}\n\n/**\n * HTTP 402: the run costs more than the caller may spend. `code` is the\n * refusal's own code — `insufficient_credits` for the caller's own balance, or\n * another 402 code such as `free_video_limit`. A spending cap someone else set\n * (a workspace budget, a member cap, a per-user allowance) is the subclass\n * {@link CreditCapExceededError}, so `instanceof InsufficientCreditsError`\n * still catches every 402.\n */\nexport class InsufficientCreditsError extends NodaroError {\n constructor(\n message = \"Insufficient credits\",\n public readonly required?: number,\n public readonly available?: number,\n code = \"insufficient_credits\",\n ) {\n super(message, code, 402)\n this.name = \"InsufficientCreditsError\"\n }\n}\n\n/** The 402 codes of a spending cap set by someone other than the caller. */\nexport type CreditCapCode = \"budget_exceeded\" | \"member_cap_exceeded\" | \"user_allowance_exceeded\"\n\n/**\n * The 402 codes {@link CreditCapExceededError} carries: the workspace's budget\n * (`budget_exceeded`), the caller's cap in that workspace\n * (`member_cap_exceeded`), the deployment's per-user allowance\n * (`user_allowance_exceeded`).\n */\nexport const CREDIT_CAP_CODES: ReadonlySet<CreditCapCode> = new Set<CreditCapCode>([\n \"budget_exceeded\",\n \"member_cap_exceeded\",\n \"user_allowance_exceeded\",\n])\n\n/**\n * HTTP 402 from a spending cap, not from the caller's own balance: topping up\n * does not help — whoever set the cap (the workspace's owner, the deployment's\n * operator) has to raise it. An {@link InsufficientCreditsError}, so existing\n * catches keep working; `code` says which cap. `available`, when sent, is what\n * the cap has left.\n */\nexport class CreditCapExceededError extends InsufficientCreditsError {\n declare readonly code: CreditCapCode\n\n constructor(code: CreditCapCode, message = \"A credit cap cannot cover this run\", required?: number, available?: number) {\n super(message, required, available, code)\n this.name = \"CreditCapExceededError\"\n }\n}\n\n/**\n * HTTP 413: what was sent does not fit. `code` is always `storage_exceeded`;\n * `reason` is the platform's own code, when the answer carried one:\n * `storage_limit_exceeded` is a full storage, while `file_too_large` is a\n * single file over the limit, not a full storage (likewise\n * `payload_too_large`, `post_too_large`, `duration_exceeded`).\n */\nexport class StorageExceededError extends NodaroError {\n constructor(\n message = \"Storage exceeded\",\n public readonly limitBytes?: number,\n /** The platform's own code for this 413, e.g. `storage_limit_exceeded` or `file_too_large`. */\n public readonly reason?: string,\n ) {\n super(message, \"storage_exceeded\", 413)\n this.name = \"StorageExceededError\"\n }\n}\n\n/**\n * Optimistic-concurrency rejection (HTTP 409 `workflow_conflict`): the workflow\n * was written by another tab/device after the state carried in\n * `expectedUpdatedAt`/`expectedVersion` was read. `currentRecord` — when the\n * server includes it — is the full current workflow: merge your changes onto it\n * and retry with its fresh `updatedAt`, no follow-up GET needed.\n */\nexport class WorkflowConflictError extends NodaroError {\n constructor(\n message = \"Workflow was updated by another writer\",\n public readonly currentUpdatedAt?: string,\n public readonly currentVersion?: number,\n public readonly currentRecord?: Record<string, unknown>,\n /**\n * The wire code this conflict actually arrived with.\n *\n * `production_busy` is the studio production routes' own 409: the row\n * changed under a read-modify-write and the server exhausted its retries.\n * It is the same situation and the same remedy — re-read and apply again —\n * so it is the same ERROR, and a caller catching `WorkflowConflictError`\n * handles both. The code stays truthful because a caller that logs or\n * branches on it should see what the server said, not what the class is\n * usually called.\n */\n code: WorkflowConflictCode = \"workflow_conflict\",\n ) {\n super(message, code, 409)\n this.name = \"WorkflowConflictError\"\n }\n}\n\n/** The 409 codes that mean \"somebody else wrote first; re-read and retry\". */\nexport type WorkflowConflictCode = \"workflow_conflict\" | \"production_busy\"\n\n/**\n * A studio operation batch was refused, and the error names WHICH operation\n * (`opIndex`, zero-based) was wrong. Nothing in the batch was written: a batch\n * applies atomically or not at all, so fix that one operation and send the\n * whole batch again.\n *\n * Selected by SHAPE — any 4xx carrying a numeric `opIndex` — not by a list of\n * codes, so a new refusal reason (`op_invalid`, `op_target_missing`, whatever\n * the server adds next) reaches the caller as this error without an SDK\n * release. `code` is whatever the server sent.\n */\nexport class StudioOpError extends NodaroError {\n constructor(\n message: string,\n code: string,\n status: number,\n /** Zero-based index into the `ops` array that was sent. */\n public readonly opIndex: number,\n ) {\n super(message, code, status)\n this.name = \"StudioOpError\"\n }\n}\n\n/** The 409 codes whose answer names the job to turn to instead (a top-level `jobId`). */\nconst CONTINUATION_REFUSAL_CODES: ReadonlySet<string> = new Set([\n \"already_running\",\n \"continuation_superseded\",\n \"render_final_already_rendered\",\n])\n\n/**\n * A 409 that names the job to turn to instead: continuing a use-case run\n * (`client.edit.continueUseCase`) answers `already_running` (a continuation is\n * under way, or one that already completed — follow `jobId`),\n * `continuation_superseded` (a later continuation failed too — continue\n * `jobId` instead) or `render_final_already_rendered` (a Render final with this\n * very edit already completed — `jobId` holds the result). `code` and `status`\n * are what the server sent. Selected for exactly those three codes when the\n * answer carries a top-level `jobId`; every other 409 stays a plain\n * `NodaroError`.\n */\nexport class ContinuationRefusedError extends NodaroError {\n constructor(\n message: string,\n code: string,\n /** The job the refusal names. */\n public readonly jobId: string,\n ) {\n super(message, code, 409)\n this.name = \"ContinuationRefusedError\"\n }\n}\n\n/**\n * The one run that finishes a continuation held at a Preview review (the\n * `next` of {@link ContinuationPreviewPendingError}): pass these three fields\n * to `client.workflows.run`. It continues that execution, runs each held render\n * at Final and each held Tighten Episode continuing the run that made its\n * Preview, then every node after them.\n */\nexport interface HeldFinalRun {\n continueFromExecutionId: string\n /** The nodes it runs, in canvas order. */\n nodeIds: string[]\n /** For this run only: each held render at Final, each held use-case node's `useCaseContinue`. */\n inputOverrides: Record<string, Record<string, unknown>>\n}\n\n/**\n * HTTP 409 `continuation_preview_pending`: a continue-from-failed\n * (`client.workflows.run` with `continueMode: \"from-failed\"`) whose run's\n * newest later continuation completed by stopping at a Preview review, so\n * continuing again would stop there too. `executionId` is that continuation;\n * `renderNodeIds` the Apply EDL renders and `reviewNodeIds` the Tighten Episode\n * nodes holding it; `next` the run that finishes them — send it first\n * (`client.workflows.run(workflowId, error.next)`), then continue. Absent only\n * when the server could not name it. For a single held render, `next` is that\n * render's `client.workflows.renderFinal`.\n */\nexport class ContinuationPreviewPendingError extends NodaroError {\n constructor(\n message: string,\n public readonly executionId: string,\n public readonly renderNodeIds: readonly string[],\n public readonly reviewNodeIds: readonly string[],\n public readonly next?: HeldFinalRun,\n ) {\n super(message, \"continuation_preview_pending\", 409)\n this.name = \"ContinuationPreviewPendingError\"\n }\n}\n\nconst stringList = (v: unknown): string[] => (Array.isArray(v) ? v.filter((id): id is string => typeof id === \"string\") : [])\n\n/** A `next` as the server sends it, or undefined for anything else. */\nfunction heldFinalRunOf(v: unknown): HeldFinalRun | undefined {\n if (!v || typeof v !== \"object\") return undefined\n const r = v as Record<string, unknown>\n if (typeof r.continueFromExecutionId !== \"string\" || !Array.isArray(r.nodeIds)) return undefined\n if (!r.inputOverrides || typeof r.inputOverrides !== \"object\" || Array.isArray(r.inputOverrides)) return undefined\n return {\n continueFromExecutionId: r.continueFromExecutionId,\n nodeIds: stringList(r.nodeIds),\n inputOverrides: r.inputOverrides as Record<string, Record<string, unknown>>,\n }\n}\n\n/**\n * HTTP 409 `already_running` that names the execution under way (a top-level\n * `executionId`): the run you asked to start or continue is still running —\n * follow `executionId` (`client.executions.get`) instead of starting it again.\n * Sent by the workflow run route and by an app run's Retry\n * (`client.apps.resume`). An `already_running` that names a job instead stays\n * {@link ContinuationRefusedError}; one that names nothing, a plain\n * `NodaroError`.\n */\nexport class AlreadyRunningError extends NodaroError {\n constructor(\n message: string,\n /** The execution under way. */\n public readonly executionId: string,\n ) {\n super(message, \"already_running\", 409)\n this.name = \"AlreadyRunningError\"\n }\n}\n\n/**\n * HTTP 409 `app_run_version_changed`: a Retry of a failed app run\n * (`client.apps.resume`) refused because the app is on another version than\n * the one the run ran — continuing would mix them. `runVersion` is the run's\n * version, `appVersion` the one you are on (the `version` you sent, else the\n * app's latest). Start the run over (`client.apps.run`) to run `appVersion`,\n * or send `{ version: runVersion }` to continue on the run's own version.\n * Nothing was written or billed. Selected by code; the two numbers are\n * `undefined` when the answer does not carry them.\n */\nexport class AppRunVersionChangedError extends NodaroError {\n constructor(\n message: string,\n public readonly runVersion?: number,\n public readonly appVersion?: number,\n ) {\n super(message, \"app_run_version_changed\", 409)\n this.name = \"AppRunVersionChangedError\"\n }\n}\n\n/**\n * HTTP 422 `job_blocked`. A job policy registered by this deployment refused\n * the generation **before it ran** — no job was created, nothing was reserved\n * and nothing was charged. `message` is the policy's user-safe text: show it\n * as-is. Do not retry the identical request; whether the same input would be\n * judged differently is the deployment's policy's business.\n *\n * Only occurs on deployments that register a job policy. Selected by `code`,\n * not by status, the same way `workflow_conflict` narrows a 409 above — any\n * other 422 stays a plain `NodaroError`.\n */\nexport class JobBlockedError extends NodaroError {\n constructor(message = \"Blocked by this deployment's content policy\") {\n super(message, \"job_blocked\", 422)\n this.name = \"JobBlockedError\"\n }\n}\n\n/**\n * A job reached a terminal `failed`/`cancelled` status while being awaited by\n * `nodes.runAndWait` / `nodes.runMany`. Not an HTTP-level error (the polls\n * themselves succeeded), so `status` is 0 — distinguish it by type/`code`.\n * Carries the job's own `error_message` (as the message) and `jobId`.\n */\nexport class JobFailedError extends NodaroError {\n constructor(\n message: string,\n public readonly jobId: string,\n /** The terminal status that triggered the failure (`failed` | `cancelled`). */\n public readonly jobStatus: \"failed\" | \"cancelled\" = \"failed\",\n ) {\n super(message, \"job_failed\", 0)\n this.name = \"JobFailedError\"\n }\n}\n\n/**\n * `nodes.runAndWait` polled past its `maxMs` deadline without the job reaching\n * a terminal status. Not an HTTP error — `status` is 0; catch by type/`code`.\n */\nexport class JobTimeoutError extends NodaroError {\n constructor(\n message: string,\n public readonly jobId: string,\n /** The wall-clock deadline (ms) that was exceeded. */\n public readonly timeoutMs: number,\n ) {\n super(message, \"job_timeout\", 0)\n this.name = \"JobTimeoutError\"\n }\n}\n\n/**\n * The caller's `AbortSignal` fired while `nodes.runAndWait` was polling (or it\n * was already aborted on entry). Polling stops and this rejects. Not an HTTP\n * error — `status` is 0; catch by type/`code`.\n */\nexport class JobAbortedError extends NodaroError {\n constructor(message = \"Aborted\", public readonly jobId?: string) {\n super(message, \"job_aborted\", 0)\n this.name = \"JobAbortedError\"\n }\n}\n\n/**\n * A batch preview was asked for and this deployment cannot give one, so\n * NOTHING was sent: the batch is still unapplied and the production untouched.\n *\n * A preview is two requests because the route's body is parsed in strip mode —\n * a deployment that predates the preview silently DROPS the flag and APPLIES\n * the batch. So the SDK asks with an EMPTY batch first and sends the real one\n * only when that answer carries the `dryRun` marker. This is what it throws\n * when the answer does not: whatever the older deployment made of an empty\n * batch, the caller's batch never left.\n *\n * The remedy is a deployment that serves the preview — there is nothing to\n * retry here. To apply the batch instead, send it without the flag.\n *\n * A deployment that REFUSES the empty batch outright throws its own error\n * instead of this one, which is the right way round: the route's message says\n * more than \"unavailable\" does.\n *\n * Not an HTTP error: the request itself succeeded and answered the older shape.\n * `status` is 0; catch by type/`code`.\n */\nexport class StudioPreviewUnavailable extends NodaroError {\n constructor(\n message = \"This deployment does not preview operation batches; nothing was sent\",\n ) {\n super(message, \"studio_preview_unavailable\", 0)\n this.name = \"StudioPreviewUnavailable\"\n }\n}\n\n/**\n * A batch preview was asked for and the batch was APPLIED instead. The\n * production is written; this is the opposite of {@link\n * StudioPreviewUnavailable}, where nothing was sent.\n *\n * How it happens: the preview's proving ping and the batch are two requests,\n * and a fleet mid-rollout can serve them from different deployments. The ping\n * answers the marker, the batch reaches a deployment that predates the preview,\n * parses in strip mode, drops the flag and writes. The SDK cannot recall that\n * request — by the time the answer comes back the change has landed — so it\n * refuses to call the result a preview, which is the only thing still in its\n * gift. `receipts` and `warnings` are on both shapes, so an unchecked reply\n * would have shown a person what ALREADY happened under the heading of what\n * would.\n *\n * `applied` is what the route answered: the ordinary apply reply, whose\n * `production` and `version` are now the truth. Adopt them the way a plain\n * apply's caller does — do NOT re-send the batch, and do not present it for\n * approval.\n *\n * Not an HTTP error: the request succeeded, at the wrong thing. `status` is 0.\n */\nexport class StudioPreviewAppliedError extends NodaroError {\n constructor(\n /**\n * The apply reply the route sent back, as it sent it. An answer this\n * package does not recognise arrives here unchanged rather than being\n * dressed up: it is what the deployment said about a batch it took.\n *\n * `undefined` when the answer carried no body at all — a 204, an empty\n * envelope. The refusal still fires, because a non-preview answer is never\n * handed back as a preview, but there is nothing to report and the SDK will\n * not invent it: whether the batch was applied is unknown from here, and\n * the caller settles it by re-reading the production.\n */\n public readonly applied: StudioOpsResponse | undefined,\n message = applied\n ? \"Asked for a preview and this deployment APPLIED the batch; the change is written — see `applied`\"\n : \"Asked for a preview and this deployment answered with neither one nor a body to read; the batch may have been applied — re-read the production before deciding anything\",\n ) {\n super(message, \"studio_preview_applied\", 0)\n this.name = \"StudioPreviewAppliedError\"\n }\n}\n\n/**\n * The awaited job entered `pending_review`: a job policy registered by this\n * deployment held its output for a human reviewer. `pending_review` is\n * IN-FLIGHT, not terminal, so `nodes.runAndWait` / `nodes.runMany` end the\n * poll on the first tick they observe it rather than burning `maxMs` on a\n * status that no longer moves on its own.\n *\n * This does NOT cancel the job — the output exists, a human is reviewing it,\n * and the credit reservation stays `reserved` for the whole hold. Do not\n * re-run the request (a duplicate would be held too): re-fetch with\n * `jobs.get(jobId)` later, or surface \"awaiting review\" to your user and poll\n * `jobs.getStatus()` yourself. It resolves to `completed` (approved), `failed`\n * (rejected, with `error_hint.kind === \"policy-block\"`) or `cancelled`.\n *\n * Not an HTTP error — `status` is 0; catch by type/`code`.\n */\nexport class JobHeldError extends NodaroError {\n constructor(\n message: string,\n public readonly jobId: string,\n ) {\n super(message, \"job_held\", 0)\n this.name = \"JobHeldError\"\n }\n}\n\n/** The `{ error: { code, message, … } }` envelope every current route sends. */\ninterface ApiErrorEnvelope {\n code?: string\n message?: string\n missingScope?: string\n required?: number\n available?: number\n limitBytes?: number\n opIndex?: number\n [key: string]: unknown\n}\n\ninterface ApiErrorBody {\n /** The envelope — or, on an older route, a bare string (see {@link readErrorBody}). */\n error?: ApiErrorEnvelope | string\n /** A top-level message: an older route's, a bare validation answer's, or the server framework's own. */\n message?: unknown\n /** OAuth's human text (RFC 6749 §5.2), beside a bare-string `error`. */\n error_description?: unknown\n /** A bare validation answer's per-field issues (`{ message, issues }`). */\n issues?: unknown\n /** A refusal that names another job (see {@link ContinuationRefusedError}). */\n jobId?: unknown\n /** `continuation_preview_pending`: the held continuation, what holds it, and the run that finishes it. */\n executionId?: unknown\n renderNodeIds?: unknown\n reviewNodeIds?: unknown\n next?: unknown\n /** The credit guard's 402 sends its figures beside the envelope: what the run needs… */\n required?: unknown\n /** …and what the caller has (withheld on a deployment-paid instance). */\n balance?: unknown\n /** A per-user allowance's 402: what the allowance has left. */\n remaining?: unknown\n /** `app_run_version_changed`: the version the run ran, and the one the caller is on. */\n runVersion?: unknown\n appVersion?: unknown\n}\n\nconst finite = (v: unknown): number | undefined => (typeof v === \"number\" && Number.isFinite(v) ? v : undefined)\n\n/** A machine code as an older route writes it: lower snake_case, never a sentence or a reason phrase. */\nconst BARE_CODE = /^[a-z][a-z0-9_]*$/\n\nconst nonEmpty = (v: unknown): string | undefined => (typeof v === \"string\" && v.length > 0 ? v : undefined)\n\n/**\n * Where a body keeps its code and its human message. Most routes send the\n * envelope `{ error: { code, message } }`; three other shapes reach the SDK\n * too, and each is read for what it says rather than collapsed into\n * `internal_error` / \"Request failed\":\n *\n * - an older route's bare string, `{ error: \"<code>\", message?, … }` (character\n * training, a few profile and billing routes), and OAuth's\n * `{ error: \"<code>\", error_description }`. A snake_case string is the code;\n * a sentence (`\"Profile not found\"`) is the message.\n * - a bare validation answer, `{ message, issues: [...] }`: `validation_error`.\n * - the server framework's own answer, `{ statusCode, error: \"<reason phrase>\",\n * message }` (a route it does not have): the reason phrase is neither, the\n * message is kept — so \"no such route\" stays distinguishable from \"no such\n * resource\".\n *\n * At HTTP 500 and above only the CODE is read from outside the envelope. Text\n * there can be whatever the server failed with: the framework's own answer to\n * an uncaught throw is `{ statusCode: 500, error: \"Internal Server Error\",\n * message: <the raw error> }`, and the server's sanitizer rewrites only the\n * `internal_error` envelope. The envelope's own message is a route's chosen\n * sentence and is read at every status, as before.\n *\n * `message` is undefined when the body carries no human text it may show, so a\n * typed class keeps its own default (\"Not found\").\n */\nfunction readErrorBody(status: number, body: ApiErrorBody): { code: string | undefined; message: string | undefined; envelope: ApiErrorEnvelope } {\n const raw = body.error\n const envelope: ApiErrorEnvelope = raw && typeof raw === \"object\" ? raw : {}\n const bare = typeof raw === \"string\" ? raw : undefined\n const bareCode = bare !== undefined && BARE_CODE.test(bare) ? bare : undefined\n // Words with a space between them are human text: an older route's sentence,\n // or the framework's reason phrase — which always arrives with a real\n // `message`, read first. A single capitalised word (\"Unauthorized\") is a\n // reason phrase alone and says nothing the status does not.\n const bareSentence = bare !== undefined && bareCode === undefined && /\\s/.test(bare.trim()) ? bare : undefined\n const code =\n nonEmpty(envelope.code) ??\n bareCode ??\n (status === 400 && raw === undefined && Array.isArray(body.issues) ? \"validation_error\" : undefined)\n const outside = status >= 500 ? undefined : (nonEmpty(body.message) ?? nonEmpty(body.error_description) ?? bareSentence)\n const message = nonEmpty(envelope.message) ?? outside\n return { code, message, envelope }\n}\n\n/** The envelope's fields other than `code` and `message` (see {@link NodaroError.details}). */\nfunction envelopeDetails(envelope: ApiErrorEnvelope): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(envelope)) {\n if (key !== \"code\" && key !== \"message\") out[key] = value\n }\n return out\n}\n\nexport function throwFromResponse(status: number, body: ApiErrorBody): never {\n try {\n selectError(status, body)\n } catch (err) {\n // Every class carries the envelope's other fields, whichever was chosen.\n if (err instanceof NodaroError) {\n const raw = body && typeof body === \"object\" ? body.error : undefined\n if (raw && typeof raw === \"object\") Object.defineProperty(err, \"details\", { value: envelopeDetails(raw), enumerable: true })\n }\n throw err\n }\n}\n\nfunction selectError(status: number, body: ApiErrorBody): never {\n // A body that is not an object (an empty answer, `null`, a bare string) still\n // throws by its status.\n const parsed: ApiErrorBody = body && typeof body === \"object\" ? body : {}\n const read = readErrorBody(status, parsed)\n const envelope = read.envelope\n const code = read.code ?? \"internal_error\"\n // A typed class falls back to its own default; a generic error to the code\n // it carries, which says more than \"Request failed\" does.\n const message = read.message ?? (read.code ? read.code : \"Request failed\")\n if (status === 401) throw new UnauthorizedError(read.message)\n if (status === 409 && (code === \"workflow_conflict\" || code === \"production_busy\")) {\n throw new WorkflowConflictError(\n read.message,\n envelope.currentUpdatedAt as string | undefined,\n envelope.currentVersion as number | undefined,\n envelope.currentRecord as Record<string, unknown> | undefined,\n code,\n )\n }\n // By shape, not by code — see StudioOpError. Only the studio operations route\n // sends an op index, so this cannot capture anyone else's 400.\n if (status >= 400 && status < 500 && typeof envelope.opIndex === \"number\") {\n throw new StudioOpError(message, code, status, envelope.opIndex)\n }\n if (status === 409 && CONTINUATION_REFUSAL_CODES.has(code) && typeof parsed.jobId === \"string\") {\n throw new ContinuationRefusedError(message, code, parsed.jobId)\n }\n if (status === 409 && code === \"continuation_preview_pending\" && typeof parsed.executionId === \"string\") {\n throw new ContinuationPreviewPendingError(\n message,\n parsed.executionId,\n stringList(parsed.renderNodeIds),\n stringList(parsed.reviewNodeIds),\n heldFinalRunOf(parsed.next),\n )\n }\n if (status === 409 && code === \"already_running\" && typeof parsed.executionId === \"string\") {\n throw new AlreadyRunningError(message, parsed.executionId)\n }\n if (status === 409 && code === \"app_run_version_changed\") {\n throw new AppRunVersionChangedError(message, finite(parsed.runVersion), finite(parsed.appVersion))\n }\n if (status === 422 && code === \"job_blocked\") throw new JobBlockedError(read.message)\n // The model, not the caller — before the scope line, so its own code is\n // kept (a plain ForbiddenError says \"forbidden\" whatever the server sent).\n const modelCode = read.code as ModelUnavailableCode | undefined\n if (status === 403 && modelCode !== undefined && MODEL_UNAVAILABLE_CODES.has(modelCode)) {\n throw new ModelUnavailableError(modelCode, read.message)\n }\n if (status === 403 && code === \"insufficient_scope\") {\n throw new ForbiddenError(read.message, envelope.missingScope)\n }\n if (status === 403) throw new ForbiddenError(read.message)\n // A 404 the framework answered itself (no route at that path) carries its\n // message at the top level, not under `error`; `readErrorBody` keeps it so\n // callers can tell \"no such route\" from \"no such resource\".\n if (status === 404) throw new NotFoundError(read.message)\n if (status === 429) throw new RateLimitedError(read.message)\n if (status === 402) {\n // The credit guard puts `required` / `balance` (an allowance: `remaining`)\n // beside the envelope; an envelope that carries them (`required` /\n // `available`) is read first.\n const required = finite(envelope.required) ?? finite(parsed.required)\n const available = finite(envelope.available) ?? finite(parsed.balance) ?? finite(parsed.remaining)\n const capCode = read.code as CreditCapCode | undefined\n if (capCode !== undefined && CREDIT_CAP_CODES.has(capCode)) {\n throw new CreditCapExceededError(capCode, read.message, required, available)\n }\n throw new InsufficientCreditsError(read.message, required, available, read.code ?? \"insufficient_credits\")\n }\n if (status === 413) throw new StorageExceededError(read.message, envelope.limitBytes, read.code)\n throw new NodaroError(message, code, status)\n}\n"]}