@nodaro/sdk 2.33.0 → 2.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GKQSA24K.cjs → chunk-3WNEIBTH.cjs} +43 -35
- package/dist/chunk-3WNEIBTH.cjs.map +1 -0
- package/dist/{chunk-JMOKD6ZP.js → chunk-7CUWAVWB.js} +3 -3
- package/dist/{chunk-JMOKD6ZP.js.map → chunk-7CUWAVWB.js.map} +1 -1
- package/dist/{chunk-E5BM4BLO.js → chunk-7IWVDWSP.js} +20 -3
- package/dist/chunk-7IWVDWSP.js.map +1 -0
- package/dist/{chunk-RHJRLXKY.cjs → chunk-7XOK277W.cjs} +9 -9
- package/dist/{chunk-RHJRLXKY.cjs.map → chunk-7XOK277W.cjs.map} +1 -1
- package/dist/{chunk-3QBH2VE2.cjs → chunk-A7QSOD2S.cjs} +20 -3
- package/dist/chunk-A7QSOD2S.cjs.map +1 -0
- package/dist/{chunk-VV4TZG5S.js → chunk-AUKHMT53.js} +3 -3
- package/dist/chunk-AUKHMT53.js.map +1 -0
- package/dist/{chunk-JSCC2N7N.js → chunk-AVOQ5DG4.js} +29 -21
- package/dist/chunk-AVOQ5DG4.js.map +1 -0
- package/dist/{chunk-I6CXC345.js → chunk-D2ILCSOQ.js} +3 -3
- package/dist/{chunk-I6CXC345.js.map → chunk-D2ILCSOQ.js.map} +1 -1
- package/dist/{chunk-4NLVBYMW.js → chunk-DQAYIVVS.js} +42 -8
- package/dist/chunk-DQAYIVVS.js.map +1 -0
- package/dist/chunk-ED3ZOX3M.js +54 -0
- package/dist/chunk-ED3ZOX3M.js.map +1 -0
- package/dist/{chunk-5ALNFATQ.cjs → chunk-EK672FFM.cjs} +2 -2
- package/dist/chunk-EK672FFM.cjs.map +1 -0
- package/dist/{chunk-OXQKE5EG.cjs → chunk-ETX3TLNB.cjs} +43 -9
- package/dist/{chunk-4NLVBYMW.js.map → chunk-ETX3TLNB.cjs.map} +1 -1
- package/dist/{chunk-BRV7Z4GD.cjs → chunk-FHVNTS4E.cjs} +2 -2
- package/dist/{chunk-BRV7Z4GD.cjs.map → chunk-FHVNTS4E.cjs.map} +1 -1
- package/dist/{chunk-N6GLZOE4.cjs → chunk-FM2KM5TY.cjs} +52 -10
- package/dist/chunk-FM2KM5TY.cjs.map +1 -0
- package/dist/{chunk-53SXNN3A.js → chunk-FQNCIP6K.js} +2 -2
- package/dist/chunk-FQNCIP6K.js.map +1 -0
- package/dist/{chunk-KNMW722T.cjs → chunk-FRQJNGJS.cjs} +5 -5
- package/dist/{chunk-KNMW722T.cjs.map → chunk-FRQJNGJS.cjs.map} +1 -1
- package/dist/{chunk-4CXB7RA6.js → chunk-IGMWFEFB.js} +6 -4
- package/dist/chunk-IGMWFEFB.js.map +1 -0
- package/dist/{chunk-56NJIP7P.cjs → chunk-IISVYX5J.cjs} +5 -5
- package/dist/{chunk-56NJIP7P.cjs.map → chunk-IISVYX5J.cjs.map} +1 -1
- package/dist/{chunk-6OGGJQVA.js → chunk-ILG5DHQQ.js} +2 -2
- package/dist/chunk-ILG5DHQQ.js.map +1 -0
- package/dist/{chunk-ZQQABQMH.cjs → chunk-JTOEHQQJ.cjs} +12 -2
- package/dist/chunk-JTOEHQQJ.cjs.map +1 -0
- package/dist/{chunk-ZXJQSFIA.js → chunk-JUON5NXA.js} +2 -2
- package/dist/{chunk-ZXJQSFIA.js.map → chunk-JUON5NXA.js.map} +1 -1
- package/dist/chunk-KARJ7P7Y.js +3 -0
- package/dist/chunk-KARJ7P7Y.js.map +1 -0
- package/dist/{chunk-JGS6YBDW.js → chunk-L6T44A3G.js} +51 -11
- package/dist/chunk-L6T44A3G.js.map +1 -0
- package/dist/{chunk-U4T3Z3K7.cjs → chunk-NKH2UFSD.cjs} +5 -5
- package/dist/chunk-NKH2UFSD.cjs.map +1 -0
- package/dist/{chunk-E2ZXHS6E.js → chunk-OIPPTBW4.js} +2 -2
- package/dist/chunk-OIPPTBW4.js.map +1 -0
- package/dist/{chunk-DKEYSJCE.cjs → chunk-OIYMTGYN.cjs} +2 -2
- package/dist/chunk-OIYMTGYN.cjs.map +1 -0
- package/dist/{chunk-NLQQHJ25.cjs → chunk-OSMKIRKI.cjs} +4 -4
- package/dist/{chunk-NLQQHJ25.cjs.map → chunk-OSMKIRKI.cjs.map} +1 -1
- package/dist/chunk-PG2GBS3K.cjs +4 -0
- package/dist/chunk-PG2GBS3K.cjs.map +1 -0
- package/dist/{chunk-GB724HW2.cjs → chunk-PQ7OKM3E.cjs} +6 -4
- package/dist/chunk-PQ7OKM3E.cjs.map +1 -0
- package/dist/{chunk-Y5CYFNNW.js → chunk-Q6HY2Q5V.js} +4 -4
- package/dist/{chunk-Y5CYFNNW.js.map → chunk-Q6HY2Q5V.js.map} +1 -1
- package/dist/chunk-QGOEQGAE.js +102 -0
- package/dist/chunk-QGOEQGAE.js.map +1 -0
- package/dist/{chunk-B7RG6AUQ.cjs → chunk-QZHRXPN5.cjs} +22 -22
- package/dist/chunk-QZHRXPN5.cjs.map +1 -0
- package/dist/chunk-RQSGS7ZK.cjs +4 -0
- package/dist/chunk-RQSGS7ZK.cjs.map +1 -0
- package/dist/{chunk-KGKCAGRD.cjs → chunk-TCLNSVYA.cjs} +2 -2
- package/dist/chunk-TCLNSVYA.cjs.map +1 -0
- package/dist/chunk-U2B7YQ2N.cjs +56 -0
- package/dist/chunk-U2B7YQ2N.cjs.map +1 -0
- package/dist/chunk-VCEYLJ2Q.cjs +104 -0
- package/dist/chunk-VCEYLJ2Q.cjs.map +1 -0
- package/dist/{chunk-VGWOIWRQ.cjs → chunk-VHSMOBU7.cjs} +2 -2
- package/dist/{chunk-VGWOIWRQ.cjs.map → chunk-VHSMOBU7.cjs.map} +1 -1
- package/dist/{chunk-T3SYREY4.js → chunk-WY4QRJZW.js} +12 -2
- package/dist/chunk-WY4QRJZW.js.map +1 -0
- package/dist/chunk-YCVRQZT3.js +3 -0
- package/dist/chunk-YCVRQZT3.js.map +1 -0
- package/dist/{chunk-DPSMVOM3.js → chunk-YSZM3N7Q.js} +2 -2
- package/dist/chunk-YSZM3N7Q.js.map +1 -0
- package/dist/{chunk-5A7J24LN.js → chunk-Z7UZ3FD3.js} +3 -3
- package/dist/{chunk-5A7J24LN.js.map → chunk-Z7UZ3FD3.js.map} +1 -1
- package/dist/{chunk-6ECW23GA.js → chunk-ZDSC6KBT.js} +3 -3
- package/dist/chunk-ZDSC6KBT.js.map +1 -0
- package/dist/entries/apps.cjs +2 -2
- package/dist/entries/apps.d.cts +4 -0
- package/dist/entries/apps.d.ts +4 -0
- package/dist/entries/apps.js +1 -1
- package/dist/entries/cast-swap.cjs +13 -0
- package/dist/entries/cast-swap.cjs.map +1 -0
- package/dist/entries/cast-swap.d.cts +380 -0
- package/dist/entries/cast-swap.d.ts +380 -0
- package/dist/entries/cast-swap.js +4 -0
- package/dist/entries/cast-swap.js.map +1 -0
- package/dist/entries/characters.d.cts +2 -2
- package/dist/entries/characters.d.ts +2 -2
- package/dist/entries/client.cjs +29 -27
- package/dist/entries/client.d.cts +8 -2
- package/dist/entries/client.d.ts +8 -2
- package/dist/entries/client.js +24 -22
- package/dist/entries/copilot.cjs +4 -4
- package/dist/entries/copilot.js +3 -3
- package/dist/entries/core.cjs +6 -6
- package/dist/entries/core.js +2 -2
- package/dist/entries/creatures.d.cts +2 -2
- package/dist/entries/creatures.d.ts +2 -2
- package/dist/entries/credits.cjs +2 -2
- package/dist/entries/credits.d.cts +37 -2
- package/dist/entries/credits.d.ts +37 -2
- package/dist/entries/credits.js +1 -1
- package/dist/entries/edit.cjs +7 -7
- package/dist/entries/edit.d.cts +3 -0
- package/dist/entries/edit.d.ts +3 -0
- package/dist/entries/edit.js +2 -2
- package/dist/entries/errors.cjs +30 -22
- package/dist/entries/errors.d.cts +42 -4
- package/dist/entries/errors.d.ts +42 -4
- package/dist/entries/errors.js +1 -1
- package/dist/entries/jobs.cjs +2 -2
- package/dist/entries/jobs.d.cts +76 -4
- package/dist/entries/jobs.d.ts +76 -4
- package/dist/entries/jobs.js +1 -1
- package/dist/entries/locations.d.cts +2 -2
- package/dist/entries/locations.d.ts +2 -2
- package/dist/entries/media.cjs +4 -4
- package/dist/entries/media.d.cts +39 -5
- package/dist/entries/media.d.ts +39 -5
- package/dist/entries/media.js +3 -3
- package/dist/entries/nodes.cjs +3 -3
- package/dist/entries/nodes.d.cts +2 -2
- package/dist/entries/nodes.d.ts +2 -2
- package/dist/entries/nodes.js +2 -2
- package/dist/entries/objects.d.cts +2 -2
- package/dist/entries/objects.d.ts +2 -2
- package/dist/entries/prompt-helper.cjs +2 -2
- package/dist/entries/prompt-helper.d.cts +3 -1
- package/dist/entries/prompt-helper.d.ts +3 -1
- package/dist/entries/prompt-helper.js +1 -1
- package/dist/entries/scene3d.d.cts +3 -3
- package/dist/entries/scene3d.d.ts +3 -3
- package/dist/entries/studio.cjs +5 -5
- package/dist/entries/studio.d.cts +2 -2
- package/dist/entries/studio.d.ts +2 -2
- package/dist/entries/studio.js +2 -2
- package/dist/entries/templates.cjs +2 -2
- package/dist/entries/templates.d.cts +4 -0
- package/dist/entries/templates.d.ts +4 -0
- package/dist/entries/templates.js +1 -1
- package/dist/entries/trends.cjs +13 -0
- package/dist/entries/trends.cjs.map +1 -0
- package/dist/entries/trends.d.cts +295 -0
- package/dist/entries/trends.d.ts +295 -0
- package/dist/entries/trends.js +4 -0
- package/dist/entries/trends.js.map +1 -0
- package/dist/entries/tutorials.cjs +2 -2
- package/dist/entries/tutorials.d.cts +4 -0
- package/dist/entries/tutorials.d.ts +4 -0
- package/dist/entries/tutorials.js +1 -1
- package/dist/entries/uploads.cjs +2 -2
- package/dist/entries/uploads.d.cts +14 -1
- package/dist/entries/uploads.d.ts +14 -1
- package/dist/entries/uploads.js +1 -1
- package/dist/entries/workflows.cjs +2 -2
- package/dist/entries/workflows.d.cts +6 -0
- package/dist/entries/workflows.d.ts +6 -0
- package/dist/entries/workflows.js +1 -1
- package/dist/index.cjs +158 -138
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +33 -29
- package/dist/{nodes-C-wrO6Sg.d.ts → nodes-9WpYNWtS.d.ts} +35 -1
- package/dist/{nodes-J8ByUN8z.d.cts → nodes-BDUk5Aej.d.cts} +35 -1
- package/dist/{studio-productions-vbCNSbtf.d.ts → studio-productions-DtTE8mdl.d.ts} +35 -1
- package/dist/{studio-productions-DUHvdSvk.d.cts → studio-productions-r2-VZsKj.d.cts} +35 -1
- package/package.json +12 -2
- package/dist/chunk-3QBH2VE2.cjs.map +0 -1
- package/dist/chunk-4CXB7RA6.js.map +0 -1
- package/dist/chunk-53SXNN3A.js.map +0 -1
- package/dist/chunk-5ALNFATQ.cjs.map +0 -1
- package/dist/chunk-6ECW23GA.js.map +0 -1
- package/dist/chunk-6OGGJQVA.js.map +0 -1
- package/dist/chunk-B7RG6AUQ.cjs.map +0 -1
- package/dist/chunk-DKEYSJCE.cjs.map +0 -1
- package/dist/chunk-DPSMVOM3.js.map +0 -1
- package/dist/chunk-E2ZXHS6E.js.map +0 -1
- package/dist/chunk-E5BM4BLO.js.map +0 -1
- package/dist/chunk-GB724HW2.cjs.map +0 -1
- package/dist/chunk-GKQSA24K.cjs.map +0 -1
- package/dist/chunk-JGS6YBDW.js.map +0 -1
- package/dist/chunk-JSCC2N7N.js.map +0 -1
- package/dist/chunk-KGKCAGRD.cjs.map +0 -1
- package/dist/chunk-N6GLZOE4.cjs.map +0 -1
- package/dist/chunk-OXQKE5EG.cjs.map +0 -1
- package/dist/chunk-T3SYREY4.js.map +0 -1
- package/dist/chunk-U4T3Z3K7.cjs.map +0 -1
- package/dist/chunk-VV4TZG5S.js.map +0 -1
- package/dist/chunk-ZQQABQMH.cjs.map +0 -1
|
@@ -1,51 +1,53 @@
|
|
|
1
|
+
import { VideoProResource } from './chunk-ERLXU47J.js';
|
|
2
|
+
import { VoicesResource } from './chunk-T7N7DFQJ.js';
|
|
1
3
|
import { WebhooksResource } from './chunk-YN6CBIIB.js';
|
|
2
|
-
import { WorkflowsResource } from './chunk-
|
|
4
|
+
import { WorkflowsResource } from './chunk-JUON5NXA.js';
|
|
3
5
|
import { WorkspacesResource } from './chunk-Z5GLY4R3.js';
|
|
6
|
+
import { Scene3DResource } from './chunk-NNHWH7ER.js';
|
|
4
7
|
import { SessionsResource } from './chunk-Y6VDCZPB.js';
|
|
5
8
|
import { ShotsResource } from './chunk-WVFAQBS7.js';
|
|
6
|
-
import { StudioResource } from './chunk-
|
|
7
|
-
import { TemplatesResource } from './chunk-
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { StudioResource } from './chunk-AUKHMT53.js';
|
|
10
|
+
import { TemplatesResource } from './chunk-ILG5DHQQ.js';
|
|
11
|
+
import { TrendsResource } from './chunk-QGOEQGAE.js';
|
|
12
|
+
import { TutorialsResource } from './chunk-YSZM3N7Q.js';
|
|
13
|
+
import { UploadsResource } from './chunk-WY4QRJZW.js';
|
|
14
|
+
import { PalettesResource } from './chunk-WEQWU2IC.js';
|
|
12
15
|
import { PickerCatalogsResource } from './chunk-BLA44UCM.js';
|
|
13
16
|
import { PipelinesResource } from './chunk-K4RQOSJH.js';
|
|
14
17
|
import { ProjectsResource } from './chunk-H7VQTG4M.js';
|
|
15
|
-
import { PromptHelperResource } from './chunk-
|
|
18
|
+
import { PromptHelperResource } from './chunk-OIPPTBW4.js';
|
|
16
19
|
import { RecastResource } from './chunk-AJVSMNPZ.js';
|
|
17
20
|
import { ReduceResource } from './chunk-IHKIYVZQ.js';
|
|
18
21
|
import { SavedPostsResource } from './chunk-NCCBS6GU.js';
|
|
19
|
-
import {
|
|
22
|
+
import { MediaResource } from './chunk-DQAYIVVS.js';
|
|
20
23
|
import { ModelsResource } from './chunk-Y6V6CBY5.js';
|
|
21
24
|
import { MoodboardsResource } from './chunk-YVU2M7MI.js';
|
|
22
25
|
import { PresetsResource } from './chunk-JTAW54UM.js';
|
|
23
|
-
import { NodesResource } from './chunk-
|
|
26
|
+
import { NodesResource } from './chunk-ZDSC6KBT.js';
|
|
24
27
|
import { OAuthResource } from './chunk-Z7LGWNI7.js';
|
|
25
28
|
import { ObjectsResource } from './chunk-7LSFG2AF.js';
|
|
26
29
|
import { OrganizationsResource } from './chunk-ALSLZG3U.js';
|
|
27
|
-
import {
|
|
30
|
+
import { EditResource } from './chunk-Z7UZ3FD3.js';
|
|
28
31
|
import { ExecutionsResource } from './chunk-Z3ZKFI2M.js';
|
|
29
32
|
import { GalleryResource } from './chunk-JDEZHITT.js';
|
|
30
|
-
import { JobsResource } from './chunk-
|
|
33
|
+
import { JobsResource } from './chunk-7IWVDWSP.js';
|
|
31
34
|
import { LibraryResource } from './chunk-P6E4QDJN.js';
|
|
32
35
|
import { LlmResource } from './chunk-E37CVHWW.js';
|
|
33
36
|
import { LocationsResource } from './chunk-TVENC6PH.js';
|
|
34
|
-
import {
|
|
37
|
+
import { CollectionsResource } from './chunk-4WRDR4GN.js';
|
|
35
38
|
import { CommunityResource } from './chunk-SFB4YLCS.js';
|
|
36
39
|
import { CompetitorsResource } from './chunk-BU5A6K4C.js';
|
|
37
|
-
import { CopilotResource } from './chunk-
|
|
38
|
-
import { NodaroClientCore } from './chunk-
|
|
40
|
+
import { CopilotResource } from './chunk-D2ILCSOQ.js';
|
|
41
|
+
import { NodaroClientCore } from './chunk-Q6HY2Q5V.js';
|
|
39
42
|
import { CreaturesResource } from './chunk-CK3AMMSC.js';
|
|
40
|
-
import { CreditsResource } from './chunk-
|
|
43
|
+
import { CreditsResource } from './chunk-IGMWFEFB.js';
|
|
41
44
|
import { DeveloperAppsResource } from './chunk-65E3JBFZ.js';
|
|
42
|
-
import {
|
|
43
|
-
import { AppsResource } from './chunk-53SXNN3A.js';
|
|
45
|
+
import { AppsResource } from './chunk-FQNCIP6K.js';
|
|
44
46
|
import { AudioResource } from './chunk-3QFTP5P5.js';
|
|
45
47
|
import { BillingResource } from './chunk-J4WFSKY6.js';
|
|
48
|
+
import { CastSwapResource } from './chunk-ED3ZOX3M.js';
|
|
46
49
|
import { CatalogsResource } from './chunk-KG4R454Z.js';
|
|
47
50
|
import { CharactersResource } from './chunk-EJSGJDZY.js';
|
|
48
|
-
import { CollectionsResource } from './chunk-4WRDR4GN.js';
|
|
49
51
|
|
|
50
52
|
// src/client.ts
|
|
51
53
|
var NodaroClient = class _NodaroClient extends NodaroClientCore {
|
|
@@ -94,6 +96,10 @@ var NodaroClient = class _NodaroClient extends NodaroClientCore {
|
|
|
94
96
|
models;
|
|
95
97
|
shots;
|
|
96
98
|
recast;
|
|
99
|
+
/** Cast Swap: replace the people and/or location in a short video (Cloud). */
|
|
100
|
+
castSwap;
|
|
101
|
+
/** Trends: ready-made Cast Swap recipes you fill with your own pictures (Cloud). */
|
|
102
|
+
trends;
|
|
97
103
|
studio;
|
|
98
104
|
copilot;
|
|
99
105
|
community;
|
|
@@ -143,6 +149,8 @@ var NodaroClient = class _NodaroClient extends NodaroClientCore {
|
|
|
143
149
|
this.models = new ModelsResource(this);
|
|
144
150
|
this.shots = new ShotsResource(this);
|
|
145
151
|
this.recast = new RecastResource(this);
|
|
152
|
+
this.castSwap = new CastSwapResource(this);
|
|
153
|
+
this.trends = new TrendsResource(this);
|
|
146
154
|
this.studio = new StudioResource(this);
|
|
147
155
|
this.copilot = new CopilotResource(this);
|
|
148
156
|
this.community = new CommunityResource(this);
|
|
@@ -180,5 +188,5 @@ function createClient(opts) {
|
|
|
180
188
|
}
|
|
181
189
|
|
|
182
190
|
export { NodaroClient, createClient };
|
|
183
|
-
//# sourceMappingURL=chunk-
|
|
184
|
-
//# sourceMappingURL=chunk-
|
|
191
|
+
//# sourceMappingURL=chunk-AVOQ5DG4.js.map
|
|
192
|
+
//# sourceMappingURL=chunk-AVOQ5DG4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0DO,IAAM,YAAA,GAAN,MAAM,aAAA,SAAqB,gBAAA,CAAiB;AAAA,EACxC,SAAA;AAAA,EACA,QAAA;AAAA;AAAA,EAEA,QAAA;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,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,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,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,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,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-AVOQ5DG4.js","sourcesContent":["import { WorkflowsResource } from \"./resources/workflows.js\"\nimport { ProjectsResource } from \"./resources/projects.js\"\nimport { SessionsResource } from \"./resources/sessions.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 { 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 { 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 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 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 /** 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.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.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.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,4 +1,4 @@
|
|
|
1
|
-
import { readSseStream } from './chunk-
|
|
1
|
+
import { readSseStream } from './chunk-7CUWAVWB.js';
|
|
2
2
|
|
|
3
3
|
// src/resources/copilot.ts
|
|
4
4
|
var COPILOT_FRAME_TYPES = /* @__PURE__ */ new Set([
|
|
@@ -98,5 +98,5 @@ var CopilotResource = class {
|
|
|
98
98
|
};
|
|
99
99
|
|
|
100
100
|
export { CopilotResource };
|
|
101
|
-
//# sourceMappingURL=chunk-
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
101
|
+
//# sourceMappingURL=chunk-D2ILCSOQ.js.map
|
|
102
|
+
//# sourceMappingURL=chunk-D2ILCSOQ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/resources/copilot.ts"],"names":[],"mappings":"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","file":"chunk-I6CXC345.js","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":[],"mappings":"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","file":"chunk-D2ILCSOQ.js","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,4 +1,4 @@
|
|
|
1
|
-
import { readSseStream } from './chunk-
|
|
1
|
+
import { readSseStream } from './chunk-7CUWAVWB.js';
|
|
2
2
|
|
|
3
3
|
// src/resources/media.ts
|
|
4
4
|
var MediaResource = class {
|
|
@@ -236,8 +236,32 @@ var MediaResource = class {
|
|
|
236
236
|
* to 5 minutes at 30 fps (a faster clip counts
|
|
237
237
|
* proportionally longer), priced by the clip's length. Poll
|
|
238
238
|
* `jobs.get(jobId)`: the output carries `videoUrl` (the mask), `width`,
|
|
239
|
-
* `height`, `frames
|
|
240
|
-
*
|
|
239
|
+
* `height`, `frames`, `coverage` (the fraction of pixels selected, rounded
|
|
240
|
+
* to 4 decimals) and `kept` (any region left on any frame: false only when
|
|
241
|
+
* the size / zone filters left an empty mask — read it rather than
|
|
242
|
+
* `coverage`, which a few pixels round to 0). Feed the mask to
|
|
243
|
+
* {@link MediaResource.maskComposite}.
|
|
244
|
+
*
|
|
245
|
+
* `holdLastMask: true` keeps the last mask on frames where the subject is
|
|
246
|
+
* lost (a mask covering under 0.002 % of the frame, e.g. a face behind a
|
|
247
|
+
* hand): each such frame after the first detection repeats the most recent
|
|
248
|
+
* non-empty one; the output then also carries `heldFrames`.
|
|
249
|
+
* `minSubjectHeightPct` (0–100, default 0 = off) drops every connected
|
|
250
|
+
* region whose bounding box is shorter than that % of the frame height
|
|
251
|
+
* (extras' small faces behind the main subject); it runs before
|
|
252
|
+
* `holdLastMask`, and the output then carries `droppedRegions`.
|
|
253
|
+
* `maxSubjectHeightPct` (0–100, default 0 = off) is its mirror: it drops
|
|
254
|
+
* regions TALLER than that % (keep only the small background faces). With
|
|
255
|
+
* both set a region is kept when min ≤ height ≤ max; min > max is a 400.
|
|
256
|
+
* `zone` (`{ leftPct, rightPct, topPct, bottomPct }`, each 0–49 % of the
|
|
257
|
+
* frame, a margin left out = 0; default null = off) keeps only the regions
|
|
258
|
+
* whose bounding-box centre lies inside the frame minus those margins (after
|
|
259
|
+
* the size cuts, before `holdLastMask`). `perShot: true` finds the clip's
|
|
260
|
+
* scene cuts first and segments each shot on its own: the subject is
|
|
261
|
+
* detected again after every cut, `holdLastMask` never crosses a cut, and
|
|
262
|
+
* each shot's mask is fitted to that shot's exact frame count; on a clip
|
|
263
|
+
* with no cut it gives the same mask, fitted to the clip's exact frame
|
|
264
|
+
* count. The output carries `shots` (1 when off).
|
|
241
265
|
*/
|
|
242
266
|
videoMask(input) {
|
|
243
267
|
return this.client.request("POST", "/v1/video-mask", { body: input });
|
|
@@ -248,9 +272,19 @@ var MediaResource = class {
|
|
|
248
272
|
* The result follows the foreground's size, frame rate and length; the
|
|
249
273
|
* background is fitted (`backgroundFit`, default cover) and loops when
|
|
250
274
|
* shorter; the mask holds its last frame when shorter. Optional
|
|
251
|
-
* `invertMask`, `feather` (0–20 px), `grow` (−10–10 px)
|
|
252
|
-
*
|
|
253
|
-
*
|
|
275
|
+
* `invertMask`, `feather` (0–20 px), `grow` (−10–10 px), `opacity` (0–1,
|
|
276
|
+
* default 1: how strongly the foreground covers the background inside the
|
|
277
|
+
* mask) and `audioSource` (foreground / background / mix / none). Priced per started 5 seconds of
|
|
278
|
+
* the result (the video it follows up to 300 s). Poll `jobs.get(jobId)` for `videoUrl`.
|
|
279
|
+
*
|
|
280
|
+
* `fill` picks what fills the masked area: `video` (default — the
|
|
281
|
+
* foreground, required then), `pixelate` (the background itself in
|
|
282
|
+
* blocks of `pixelSizePct` % of the frame width, 0.2–10, default 1.25) or
|
|
283
|
+
* `blur` (the background blurred, sigma `blurStrengthPct` % of the frame
|
|
284
|
+
* width, 0.1–5, default 2). Pixelate and blur take no
|
|
285
|
+
* `foregroundUrl` (one sent is ignored): the result follows the background
|
|
286
|
+
* and is priced on its length, and it always carries the background's sound
|
|
287
|
+
* (`audioSource` is ignored).
|
|
254
288
|
*/
|
|
255
289
|
maskComposite(input) {
|
|
256
290
|
return this.client.request("POST", "/v1/mask-composite", { body: input });
|
|
@@ -276,5 +310,5 @@ var MediaResource = class {
|
|
|
276
310
|
};
|
|
277
311
|
|
|
278
312
|
export { MediaResource };
|
|
279
|
-
//# sourceMappingURL=chunk-
|
|
280
|
-
//# sourceMappingURL=chunk-
|
|
313
|
+
//# sourceMappingURL=chunk-DQAYIVVS.js.map
|
|
314
|
+
//# sourceMappingURL=chunk-DQAYIVVS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/media.ts"],"names":[],"mappings":";;;AAsGO,IAAM,gBAAN,MAAoB;AAAA,EACzB,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcpB,cAAc,KAAA,EAMsB;AAClC,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAgC,MAAA,EAAQ,sBAAsB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAClG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,OAAO,qBAAA,CACL,UAAA,EACA,IAAA,GAAiC,EAAC,EACsB;AACxD,IAAA,MAAM,GAAA,GAAM,GAAG,IAAA,CAAK,MAAA,CAAO,OAAO,CAAA,4BAAA,EAA+B,kBAAA,CAAmB,UAAU,CAAC,CAAA,CAAA;AAC/F,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,OAAA,EAAS,QAAQ,EAAE,aAAA,EAAe,UAAU,KAAK,CAAA,CAAA,KAAO,EAAC;AAAA,MACzD,QAAQ,IAAA,CAAK;AAAA,KACd,CAAA;AAID,IAAA,OAAO,aAAA,CAAqC,GAAA,EAAK,EAAE,KAAA,EAAO,mBAAmB,CAAA;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,KAAA,EAAqH;AACjI,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,uBAAuB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC9F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,aAAa,KAAA,EAYkB;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,qBAAqB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,aAAa,KAAA,EAiCkB;AAE7B,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,qBAAqB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBA,wBAAwB,KAAA,EAMoC;AAC1D,IAAA,OAAO,KAAK,MAAA,CAAO,OAAA;AAAA,MACjB,MAAA;AAAA,MACA,qCAAA;AAAA,MACA,EAAE,MAAM,KAAA;AAAM,KAChB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,KAAA,EAUqB;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,kBAAkB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuCA,YAAY,KAAA,EAAqD;AAC/D,IAAA,MAAM,EAAE,cAAA,EAAgB,kBAAA,EAAoB,GAAG,MAAK,GAAI,KAAA;AAGxD,IAAA,MAAM,IAAA,GAAgC;AAAA,MACpC,GAAG,IAAA;AAAA,MACH,GAAI,cAAA,KAAmB,MAAA,GAAY,EAAE,eAAA,EAAiB,cAAA,KAAmB,EAAC;AAAA,MAC1E,GAAI,kBAAA,KAAuB,MAAA,GAAY,EAAE,mBAAA,EAAqB,kBAAA,KAAuB;AAAC,KACxF;AACA,IAAA,OAAO,KAAK,MAAA,CAAO,OAAA,CAA2B,QAAQ,kBAAA,EAAoB,EAAE,MAAM,CAAA;AAAA,EACpF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,KAAA,EAMqB;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,kBAAkB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAW,KAAA,EAAoD;AAC7D,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,mBAAmB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC1F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,KAAA,EAUkB;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,sBAAsB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,UAAU,KAAA,EAcqB;AAC7B,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,iBAAiB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EACxF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,aAAa,KAAA,EAAwD;AACnE,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,qBAAqB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC5F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoCA,UAAU,KAAA,EAAqD;AAC7D,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,kBAAkB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,cAAc,KAAA,EAAyD;AACrE,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAA2B,MAAA,EAAQ,sBAAsB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EAC7F;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,cAAc,KAAA,EAAgD;AAC5D,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAuB,MAAA,EAAQ,sBAAsB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAAQ,KAAA,EAAiE;AACvE,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAsC,MAAA,EAAQ,qBAAqB,EAAE,IAAA,EAAM,OAAO,CAAA;AAAA,EACvG;AACF","file":"chunk-DQAYIVVS.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\nimport { readSseStream } from \"../sse.js\"\nimport type { OverlayAnchor, VideoMaskRequest, MaskCompositeRequest } from \"@nodaro/shared/media\"\nimport type { CaptionStyle, CaptionLookId, SupportedFontName } from \"@nodaro/shared/captions\"\nimport type { TranscribeLane } from \"@nodaro/shared/models\"\nimport type { VideoOverlayRequest } from \"@nodaro/shared/video\"\n\n/** One word-timed caption entry (one per WORD for the kinetic styles). */\nexport interface CaptionEntry {\n text: string\n startMs: number\n endMs: number\n timestampMs?: number | null\n confidence?: number | null\n}\n\n/** Look + motion levers — see {@link MediaResource.addCaptions}. `look` is a\n * named preset the explicit levers override; an unset look renders as `outline`\n * (the default). The STYLING levers (`look`, `fontFamily`, `fontWeight`,\n * `strokeColor`/`strokeWidth`, `uppercase`, `positionY`, `maxWordsPerLine`) now\n * apply to the static `subtitle` style too — a subtitle carrying any of them\n * renders via Remotion. Only `highlightColor` (no spoken-word cursor to colour)\n * and `animate` (no motion to freeze) stay kinetic-only and are rejected (400)\n * on `subtitle`. */\nexport interface CaptionLookInput {\n look?: CaptionLookId\n fontFamily?: SupportedFontName\n fontWeight?: number\n strokeColor?: string\n strokeWidth?: number\n highlightColor?: string\n uppercase?: boolean\n positionY?: number\n /** Cap on how many words one caption LINE (or `tiktok-words` page) may hold,\n * 1-20, on TOP of the frame-width budget, sentence ends and pauses that\n * already close a line — 1-2 gives the punchy CapCut read, unset fits the\n * width. Applies to `word-highlight` / `karaoke` / `bouncy` / `tiktok-words`\n * and to a Remotion-rendered `subtitle`; inert on `word-pop` (always one\n * word). */\n maxWordsPerLine?: number\n /** Kinetic styles only. `false` freezes the per-word MOTION — the grouping,\n * line-holding and spoken-word highlight stay, only the movement stops;\n * default `true`. Rejected (400) on the static `subtitle` style. */\n animate?: boolean\n}\n\n/** One caption SEGMENT: a time range with optional style/look overrides and its\n * own words (`text`/`captions`, else the shared transcript filtered to range).\n * A segmented render is entirely Remotion, so any `style` is valid here. */\nexport interface CaptionSegmentInput extends CaptionLookInput {\n startMs: number\n endMs: number\n style?: CaptionStyle\n position?: \"bottom\" | \"top\" | \"center\"\n fontSize?: number\n color?: string\n backgroundColor?: string\n text?: string\n captions?: CaptionEntry[]\n}\n\n/** {@link MediaResource.addCaptions} input. */\nexport interface AddCaptionsInput extends CaptionLookInput {\n videoUrl: string\n text?: string\n captions?: CaptionEntry[]\n /** Transcribe the video's audio when no text/captions are given (default true). */\n autoTranscribe?: boolean\n transcribeProvider?: TranscribeLane\n style?: CaptionStyle\n position?: \"bottom\" | \"top\" | \"center\"\n fontSize?: number\n color?: string\n backgroundColor?: string\n /** Apply different treatments to time ranges in one call (non-overlapping). */\n segments?: CaptionSegmentInput[]\n}\n\n/**\n * Media ingestion + trimming — the source-preparation steps a Voice Changer Pro\n * flow (or any pipeline) needs before it has a clip to work on: pull a social\n * video into storage, copy a remote URL into storage, trim a video/audio to a\n * range, and probe a video's metadata. Each generation-style op returns a job id\n * to poll (`jobs.get(jobId)`); `videoMetadata` is a direct read.\n */\n/**\n * Where one overlay layer should go, in {@link MediaResource.imageOverlay}'s\n * percent units — the answer from {@link MediaResource.suggestOverlayPlacement}.\n */\nexport interface OverlayPlacement {\n /** The point on the base image the layer attaches to. */\n anchor: OverlayAnchor\n /** Offset from the anchor in % of the base width (negative on a right anchor = inward). */\n x: number\n /** Offset from the anchor in % of the base height (negative on a bottom anchor = inward). */\n y: number\n /** The layer's width in % of the base width. */\n width: number\n /** One sentence, plain language, on why this spot. */\n reason: string\n}\n\nexport class MediaResource {\n constructor(private client: NodaroClientCore) {}\n\n /**\n * Download a social video (YouTube / TikTok / Instagram / X / Facebook) into\n * your storage (`POST /v1/download-video`). `maxHeight` caps the resolution\n * (default \"best\"); `sectionStartSec` + `sectionEndSec` (both-or-neither) fetch\n * ONLY that time range instead of the whole video. A download that arrives\n * with no audio stream FAILS by default (it is usually a degraded source\n * response, and is retried through other routes first); pass\n * `requireAudio: false` to accept a clip that really has no sound. Returns a\n * `downloadId`; progress streams from\n * `GET /v1/download-video/progress/:downloadId` (server-sent events) and the\n * finished file lands in your library.\n */\n downloadVideo(input: {\n url: string\n maxHeight?: number\n sectionStartSec?: number\n sectionEndSec?: number\n requireAudio?: boolean\n }): Promise<{ downloadId: string }> {\n return this.client.request<{ downloadId: string }>(\"POST\", \"/v1/download-video\", { body: input })\n }\n\n /**\n * Stream the live progress of a {@link MediaResource.downloadVideo} import\n * (`GET /v1/download-video/progress/:downloadId`, server-sent events) as an\n * async iterable. Yields a {@link DownloadVideoProgress} roughly every 500ms\n * until the download reaches `completed` (its event carries the stored\n * `videoUrl`) or `failed` (its event carries `error`), then ends. The progress\n * state expires server-side shortly after the download starts existing, so\n * start iterating promptly after `downloadVideo` returns.\n *\n * No request timeout is applied (a large import legitimately takes minutes) —\n * pass an `AbortSignal` to cancel from the caller.\n */\n async *downloadVideoProgress(\n downloadId: string,\n opts: { signal?: AbortSignal } = {},\n ): AsyncGenerator<DownloadVideoProgress, void, undefined> {\n const url = `${this.client.baseUrl}/v1/download-video/progress/${encodeURIComponent(downloadId)}`\n const token = await this.client.auth.getToken()\n const res = await this.client.fetch(url, {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n signal: opts.signal,\n })\n // The shared reader owns the non-OK throw, the empty-body guard, the frame\n // parse and the cancel-on-early-exit — this route emits the same\n // `data: <json>` frames every other stream here does.\n yield* readSseStream<DownloadVideoProgress>(res, { label: \"progress stream\" })\n }\n\n /**\n * Copy an external media URL into your Nodaro storage (`POST /v1/save-to-storage`)\n * — a server-side fetch, so nothing round-trips through the client. Poll\n * `jobs.get(jobId)`.\n */\n saveToStorage(input: { mediaUrl: string; filename?: string; mediaType?: \"image\" | \"video\" | \"audio\" }): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/save-to-storage\", { body: input })\n }\n\n /**\n * Composite 2–30 images into ONE large 2K/4K collage (`POST /v1/image-collage`).\n * `layout` `\"smart\"` (default — justified rows at each image's exact aspect\n * ratio, no cropping; the output height floats) or `\"grid\"` (uniform,\n * letterboxed cells). `imageSizes` is index-aligned with `imageUrls` and\n * gives per-image RELATIVE size hints for the smart layout: `0` auto\n * (\"don't care\", default), `1` big (~2× linear vs medium), `2` medium,\n * `3` small (~½ linear). All-equal hints change nothing; grid ignores them.\n * For storyboards, set `numbered` to stamp a 1-based sequence badge at each\n * image's corner (top-left by default; `badgePosition: \"top-right\"` moves it;\n * in `imageUrls` order) and pass `imageLabels`\n * (index-aligned with `imageUrls`; `null`/`\"\"`/omitted = no caption for that\n * image) to caption images after the number, e.g. `3 · Close-up`. Badges are\n * an overlay only — they never change the layout, the output size or the\n * credit cost. Poll `jobs.get(jobId)` for the finished image.\n */\n imageCollage(input: {\n imageUrls: string[]\n imageSizes?: Array<0 | 1 | 2 | 3>\n numbered?: boolean\n imageLabels?: Array<string | null>\n /** Corner the badges sit in — `\"top-left\"` (default, storyboard convention) or `\"top-right\"`. */\n badgePosition?: \"top-left\" | \"top-right\"\n layout?: \"smart\" | \"grid\"\n resolution?: \"2K\" | \"4K\"\n aspectRatio?: string\n gap?: number\n backgroundColor?: string\n }): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/image-collage\", { body: input })\n }\n\n /**\n * Place 1–12 layers — pictures, real text, QR codes, shapes — on a base image,\n * pixel-exactly (`POST /v1/image-overlay`) — local, deterministic, no AI.\n * Every layer position/size is a PERCENT of the base image: `anchor` (nine\n * positions, default `\"center\"`), `x`/`y` (offset from the anchor in % of\n * the base width/height; negative on a right/bottom anchor moves inward),\n * `width` (% of the base width, default 25 — height follows the layer's\n * aspect unless `height` is set). Plus `opacity` (0..1), `rotation`\n * (degrees), `blend` (`\"over\"` | `\"multiply\"` | `\"screen\"`), `fit`,\n * `shadow` and `roundedCorners`. The output keeps the base's pixel size\n * unless `canvas` is set. Flat credit cost. Poll `jobs.get(jobId)` for the\n * finished image.\n */\n imageOverlay(input: {\n imageUrl: string\n layers: Array<{\n imageUrl: string\n anchor?: OverlayAnchor\n x?: number\n y?: number\n width?: number\n height?: number\n opacity?: number\n rotation?: number\n blend?: \"over\" | \"multiply\" | \"screen\"\n fit?: \"contain\" | \"cover\" | \"stretch\"\n shadow?: { blur: number; offsetX: number; offsetY: number; color: string; opacity: number }\n roundedCorners?: number\n zIndex?: number\n /** \"image\" (default, needs imageUrl) | \"text\" | \"qr\" | \"shape\" — see @nodaro/shared image-overlay-layers. */\n kind?: \"image\" | \"text\" | \"qr\" | \"shape\"\n text?: Record<string, unknown>\n qr?: Record<string, unknown>\n shape?: Record<string, unknown>\n effects?: Record<string, unknown>\n }>\n canvas?: { width: number; height: number; backgroundColor?: string }\n baseFit?: \"contain\" | \"cover\"\n outputFormat?: \"png\" | \"jpg\" | \"webp\"\n /** Extra platform renders (see OVERLAY_PLATFORMS in @nodaro/shared); returned as output `variants[]`. */\n variants?: string[]\n /** The mask the job also emits as output `maskUrl` (white = may change). Default \"around\". */\n maskMode?: \"none\" | \"layers\" | \"around\" | \"outside\"\n maskSpread?: number\n /** Fills every QR layer whose `qr.fromInput` is true — the node's QR link handle. */\n qrText?: string\n }): Promise<{ jobId: string }> {\n // The finished job's output: { imageUrl, width, height, maskUrl?, variants?: [{ id, label, width, height, url }] }.\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/image-overlay\", { body: input })\n }\n\n /**\n * Ask a vision model WHERE one overlay layer should sit on a base image\n * (`POST /v1/image-overlay/suggest-placement`) — it reads the picture and\n * keeps the element off the faces, the subject and the busiest texture.\n * The answer comes back in {@link MediaResource.imageOverlay}'s own percent\n * units — `anchor`, `x`/`y` offsets, `width` — so it drops straight onto a\n * layer (`const { reason, ...box } = placement`), plus a one-sentence\n * `reason` you can show a user. Nothing is composited here: apply the\n * placement yourself.\n *\n * `layerAspect` is the element's width / height (1 = square, the default) so\n * the proposed box stays in proportion; `intent` says what the element is\n * (\"a logo\", \"a price badge\"); `safeArea` is the always-visible region as\n * fractions of the canvas (a platform preset's safe area), which the\n * placement is kept inside. Unlike the other media calls this one answers\n * synchronously — there is nothing to poll; `jobId` is the billing record\n * (one image-to-text call).\n */\n suggestOverlayPlacement(input: {\n imageUrl: string\n layerAspect?: number\n intent?: string\n safeArea?: { x: number; y: number; w: number; h: number }\n llmModel?: string\n }): Promise<{ jobId: string; placement: OverlayPlacement }> {\n return this.client.request<{ jobId: string; placement: OverlayPlacement }>(\n \"POST\",\n \"/v1/image-overlay/suggest-placement\",\n { body: input },\n )\n }\n\n /**\n * Trim a video to a range (`POST /v1/trim-video`). Give the range in whichever\n * unit fits: `startTime`/`endTime` seconds, `trim*Frames`, `trim*Seconds`, or\n * `keepFirst`/`keepLastSeconds`. Poll `jobs.get(jobId)`.\n */\n trimVideo(input: {\n videoUrl: string\n startTime?: number\n endTime?: number\n trimStartFrames?: number\n trimEndFrames?: number\n trimStartSeconds?: number\n trimEndSeconds?: number\n keepFirstSeconds?: number\n keepLastSeconds?: number\n }): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/trim-video\", { body: input })\n }\n\n /**\n * Burn captions into a video (`POST /v1/add-captions`). Give the words as\n * `text`, word-timed `captions[]`, or let it transcribe (`autoTranscribe`,\n * the default when neither is set).\n *\n * `style: \"subtitle\"` renders statically (FFmpeg) UNLESS it carries a styling\n * lever, in which case it — like the KINETIC styles (`word-highlight` /\n * `karaoke` / `tiktok-words` / `word-pop` / `bouncy`) — renders via Remotion.\n * `look` picks a preset — `outline` (Montserrat 900, UPPERCASE, black outline,\n * yellow spoken word — the TikTok/Reels read) or `clean`; an UNSET look renders\n * as `outline`. The explicit STYLING levers (`fontFamily`, `fontWeight`,\n * `strokeColor`/`strokeWidth`, `uppercase`, `positionY`, `maxWordsPerLine`)\n * override individual fields of it and now apply to `subtitle` too. Only\n * `highlightColor` (the spoken-word cursor) and `animate` stay kinetic-only\n * and are REJECTED on `subtitle`.\n *\n * `animate` (default true) freezes the per-word MOTION on the kinetic styles\n * when set to false — the grouping, line-holding and spoken-word highlight\n * stay; only the movement stops.\n *\n * `maxWordsPerLine` (1-20) caps how many words a line — or a `tiktok-words`\n * page — may hold, on top of the width budget / sentence ends / pauses that\n * already close one; it is inert on `word-pop`, which is always one word.\n * Like every lever here it exists top-level AND per segment, and a segment\n * that does not name its own inherits the top-level value.\n *\n * `segments[]` applies DIFFERENT treatments to non-overlapping time ranges in\n * one call (e.g. a large top intro, then a small bottom body); a segment that\n * names its own `look` starts fresh from that preset and does not inherit the\n * top-level explicit levers. Poll `jobs.get(jobId)`.\n *\n * `word-highlight` shows ONE held line at a time and a word's\n * `startMs`/`endMs` is its SPOKEN window (what times the highlight, not how\n * long the text is on screen) — so `captions[]` can be handed over verbatim\n * from an `audio.transcribe()` job's `output_data.words`, with\n * `autoTranscribe: false`.\n */\n addCaptions(input: AddCaptionsInput): Promise<{ jobId: string }> {\n const { autoTranscribe, transcribeProvider, ...rest } = input\n // The route body is camelCase except these two flags (worker snake_case);\n // omit each when unset so an absent flag stays absent on the wire.\n const body: Record<string, unknown> = {\n ...rest,\n ...(autoTranscribe !== undefined ? { auto_transcribe: autoTranscribe } : {}),\n ...(transcribeProvider !== undefined ? { transcribe_provider: transcribeProvider } : {}),\n }\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/add-captions\", { body })\n }\n\n /**\n * Trim (and extract) audio from a video or audio source\n * (`POST /v1/trim-audio`) to `[startTime, endTime]` seconds, in `audioFormat`\n * (`mp3` default / `wav` / `aac`). Poll `jobs.get(jobId)`.\n */\n trimAudio(input: {\n videoUrl?: string\n audioUrl?: string\n audioFormat?: \"mp3\" | \"wav\" | \"aac\"\n startTime?: number\n endTime?: number\n }): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/trim-audio\", { body: input })\n }\n\n /**\n * Cut a video and/or an audio file into consecutive parts\n * (`POST /v1/split-media`). Every part is at most `chunkDuration` seconds and\n * at least `minPartDuration` (default 4, never above `chunkDuration`) — a\n * short leftover is evened out with the parts before it. Video is cut on\n * whole frames with each part's sound matching its picture; audio parts are\n * sample-exact, in `audioFormat` (`mp3` default / `wav` / `aac`). With both\n * sources each is split on its own. At most 200 parts per input. Poll\n * `jobs.get(jobId)`; the parts are on the completed job's `output_data` —\n * see {@link SplitMediaOutput}.\n */\n splitMedia(input: SplitMediaInput): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/split-media\", { body: input })\n }\n\n /**\n * Turn one still image + one audio track into an MP4\n * (`POST /v1/still-to-video`) — locally rendered (FFmpeg), no AI model,\n * zero credits. The output duration IS the audio's duration; there is no\n * duration field. Optional `motion` animates the still (zoom / pan /\n * ken-burns) at `intensity` 1–10. `fit: \"contain\"` letterboxes with\n * `padColor` instead of cropping. Poll `jobs.get(jobId)`.\n */\n stillToVideo(input: {\n imageUrl: string\n audioUrl: string\n motion?: \"none\" | \"zoom-in\" | \"zoom-out\" | \"pan-left\" | \"pan-right\" | \"ken-burns\"\n intensity?: number\n resolution?: \"720p\" | \"1080p\" | \"4K\"\n aspectRatio?: \"16:9\" | \"9:16\" | \"1:1\" | \"4:3\"\n fps?: 24 | 30\n fit?: \"cover\" | \"contain\"\n padColor?: string\n }): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/still-to-video\", { body: input })\n }\n\n /**\n * Turn 2–100 images + one optional audio track into an MP4 slideshow\n * (`POST /v1/slideshow`) — locally rendered (FFmpeg), zero credits. With\n * audio, the output duration IS the audio's duration (equal split unless\n * `imageDurations` pins rows — null entries = auto; mismatched pinned sums\n * scale proportionally and the factor is disclosed in the job output).\n * Without audio: N × `perImageDuration`, silent output. Transitions\n * consume the outgoing slide, so totals stay exact. For a single image use\n * `stillToVideo`. Poll `jobs.get(jobId)`.\n */\n slideshow(input: {\n imageUrls: string[]\n audioUrl?: string\n imageDurations?: Array<number | null>\n perImageDuration?: number\n transition?: string\n transitionDuration?: number\n motion?: \"none\" | \"zoom-in\" | \"zoom-out\" | \"ken-burns\" | \"alternate\"\n intensity?: number\n resolution?: \"720p\" | \"1080p\" | \"4K\"\n aspectRatio?: \"16:9\" | \"9:16\" | \"1:1\" | \"4:3\"\n fps?: 24 | 30\n fit?: \"cover\" | \"contain\"\n padColor?: string\n }): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/slideshow\", { body: input })\n }\n\n /**\n * Place 1–20 timed image layers over a video (`POST /v1/video-overlay`) —\n * rendered locally (FFmpeg) in one pass, no AI; the base audio is kept\n * untouched. Each layer has an `imageUrl`, a `start` and an optional `end`\n * in seconds (no `end` = to the end of the video) and a placement: a\n * `preset` (`\"card\"`, `\"corner-badge\"` with a `corner`, `\"full-frame\"`) or\n * an explicit box in {@link MediaResource.imageOverlay}'s percent vocabulary\n * (`anchor`, `x`, `y`, `width`, `height`, `fit`) — an explicit box field\n * overrides the preset, and a layer with neither is a corner badge\n * (bottom-right, or the `corner` it names). `outputAspect` renders onto a\n * 16:9 / 9:16 / 1:1 / 4:5 canvas\n * (`baseFit` cover by default; `backgroundColor` pads `contain`). Poll\n * `jobs.get(jobId)`: the output carries `videoUrl`, `thumbnailUrl`, `width`,\n * `height`, `durationSec` and `warnings[]` (a layer clipped or skipped at the\n * video's end, an animated image's first frame, re-encoded audio).\n */\n videoOverlay(input: VideoOverlayRequest): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/video-overlay\", { body: input })\n }\n\n /**\n * Track a subject described in plain text through a video and get a\n * black-and-white MASK VIDEO back (`POST /v1/video-mask`, SAM 3.1 by default,\n * or `provider: \"sam-3\"` at half the price) — white = the subject. Clips up\n * to 5 minutes at 30 fps (a faster clip counts\n * proportionally longer), priced by the clip's length. Poll\n * `jobs.get(jobId)`: the output carries `videoUrl` (the mask), `width`,\n * `height`, `frames`, `coverage` (the fraction of pixels selected, rounded\n * to 4 decimals) and `kept` (any region left on any frame: false only when\n * the size / zone filters left an empty mask — read it rather than\n * `coverage`, which a few pixels round to 0). Feed the mask to\n * {@link MediaResource.maskComposite}.\n *\n * `holdLastMask: true` keeps the last mask on frames where the subject is\n * lost (a mask covering under 0.002 % of the frame, e.g. a face behind a\n * hand): each such frame after the first detection repeats the most recent\n * non-empty one; the output then also carries `heldFrames`.\n * `minSubjectHeightPct` (0–100, default 0 = off) drops every connected\n * region whose bounding box is shorter than that % of the frame height\n * (extras' small faces behind the main subject); it runs before\n * `holdLastMask`, and the output then carries `droppedRegions`.\n * `maxSubjectHeightPct` (0–100, default 0 = off) is its mirror: it drops\n * regions TALLER than that % (keep only the small background faces). With\n * both set a region is kept when min ≤ height ≤ max; min > max is a 400.\n * `zone` (`{ leftPct, rightPct, topPct, bottomPct }`, each 0–49 % of the\n * frame, a margin left out = 0; default null = off) keeps only the regions\n * whose bounding-box centre lies inside the frame minus those margins (after\n * the size cuts, before `holdLastMask`). `perShot: true` finds the clip's\n * scene cuts first and segments each shot on its own: the subject is\n * detected again after every cut, `holdLastMask` never crosses a cut, and\n * each shot's mask is fitted to that shot's exact frame count; on a clip\n * with no cut it gives the same mask, fitted to the clip's exact frame\n * count. The output carries `shots` (1 when off).\n */\n videoMask(input: VideoMaskRequest): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/video-mask\", { body: input })\n }\n\n /**\n * Place a foreground video over a background video through a mask video\n * (`POST /v1/mask-composite`; white = foreground) — local FFmpeg, no AI.\n * The result follows the foreground's size, frame rate and length; the\n * background is fitted (`backgroundFit`, default cover) and loops when\n * shorter; the mask holds its last frame when shorter. Optional\n * `invertMask`, `feather` (0–20 px), `grow` (−10–10 px), `opacity` (0–1,\n * default 1: how strongly the foreground covers the background inside the\n * mask) and `audioSource` (foreground / background / mix / none). Priced per started 5 seconds of\n * the result (the video it follows up to 300 s). Poll `jobs.get(jobId)` for `videoUrl`.\n *\n * `fill` picks what fills the masked area: `video` (default — the\n * foreground, required then), `pixelate` (the background itself in\n * blocks of `pixelSizePct` % of the frame width, 0.2–10, default 1.25) or\n * `blur` (the background blurred, sigma `blurStrengthPct` % of the frame\n * width, 0.1–5, default 2). Pixelate and blur take no\n * `foregroundUrl` (one sent is ignored): the result follows the background\n * and is priced on its length, and it always carries the background's sound\n * (`audioSource` is ignored).\n */\n maskComposite(input: MaskCompositeRequest): Promise<{ jobId: string }> {\n return this.client.request<{ jobId: string }>(\"POST\", \"/v1/mask-composite\", { body: input })\n }\n\n /**\n * Probe a social video's metadata (`POST /v1/video-metadata`) — duration,\n * dimensions, title, live status — WITHOUT downloading it. A direct read, not a\n * job. Use it to decide whether to trim before importing.\n */\n videoMetadata(input: { url: string }): Promise<VideoMetadata> {\n return this.client.request<VideoMetadata>(\"POST\", \"/v1/video-metadata\", { body: input })\n }\n\n /**\n * Cut or crop a stored file (`POST /v1/media/process`) — synchronous and\n * free, the source-preparation sibling of the priced `trimVideo` node.\n * `trim` is `[startTime, endTime]` in seconds; `deleteSource: true` removes\n * the source object afterwards when it is yours and nothing else references\n * it (\"the cut replaces the original\"). Answers the stored file.\n */\n process(input: MediaProcessInput): Promise<{ data: MediaProcessResult }> {\n return this.client.request<{ data: MediaProcessResult }>(\"POST\", \"/v1/media/process\", { body: input })\n }\n}\n\n/**\n * One event from {@link MediaResource.downloadVideoProgress}. The stream ends\n * after a `completed` event (which carries the stored `videoUrl` + an optional\n * `thumbnailUrl`) or a `failed` event (which carries `error`).\n */\nexport interface DownloadVideoProgress {\n phase: \"downloading\" | \"processing\" | \"uploading\" | \"completed\" | \"failed\"\n /** Download percent (0–100). Section fetches report jumpy percents — display, don't sum. */\n percent: number\n /** The imported video's storage URL — set on the `completed` event. */\n videoUrl?: string\n /** Thumbnail storage URL — set on the `completed` event when one was captured. */\n thumbnailUrl?: string\n /** What went wrong — set on the `failed` event. */\n error?: string\n}\n\n/** Result of {@link MediaResource.videoMetadata}. Fields are best-effort — a probe may omit some. */\nexport interface VideoMetadata {\n durationSec?: number | null\n width?: number | null\n height?: number | null\n title?: string | null\n isLive?: boolean\n [key: string]: unknown\n}\n\n/** Body of {@link MediaResource.splitMedia} (`POST /v1/split-media`). At least one of `videoUrl` / `audioUrl`. */\nexport interface SplitMediaInput {\n /** Video to split. */\n videoUrl?: string\n /** Audio file to split (split on its own when a video is given too). */\n audioUrl?: string\n /** The longest a part may be, in seconds (at least 1). Every part is at most this long. */\n chunkDuration: number\n /** The shortest a part may be, in seconds (0 or more, default 4). Must not exceed `chunkDuration` (400 otherwise). */\n minPartDuration?: number\n /** Format of the audio parts. Default `mp3`. */\n audioFormat?: \"mp3\" | \"wav\" | \"aac\"\n}\n\n/** A completed split-media job's `output_data`. */\nexport interface SplitMediaOutput {\n /** The video parts, in order (when a video was split). */\n videoUrls?: string[]\n /** The audio parts, in order (when an audio file was split). */\n audioUrls?: string[]\n /** The number of parts — the larger of the two lists. */\n chunkCount: number\n /** Each part's exact length in seconds: the video parts' when a video was split, else the audio parts'. */\n partDurationsSec?: number[]\n /** The audio parts' lengths, only when BOTH a video and an audio file were split. */\n audioPartDurationsSec?: number[]\n}\n\nexport interface MediaProcessInput {\n sourceUrl: string\n type: \"video\" | \"audio\"\n trim?: { startTime: number; endTime: number }\n crop?: { x: number; y: number; width: number; height: number }\n format?: \"mp4\" | \"webm\" | \"mp3\" | \"wav\" | \"m4a\" | \"aac\"\n deleteSource?: boolean\n}\n\nexport interface MediaProcessResult {\n url: string\n thumbnailUrl: string | null\n assetId: string | null\n sizeBytes: number\n mimeType: string\n metadata: Record<string, unknown>\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/resources/cast-swap.ts
|
|
2
|
+
var CastSwapResource = class {
|
|
3
|
+
constructor(client) {
|
|
4
|
+
this.client = client;
|
|
5
|
+
}
|
|
6
|
+
client;
|
|
7
|
+
/**
|
|
8
|
+
* Start a Cast Swap run (`POST /v1/cast-swap`, 202 `{ jobId }`). Returns the
|
|
9
|
+
* job to follow. With `options.idempotencyKey` (sent as the
|
|
10
|
+
* `Idempotency-Key` header; 8–200 characters, else 400) a repeat with the
|
|
11
|
+
* same key within about 10 s answers 200 `{ jobId, deduped: true }`, a later
|
|
12
|
+
* one 202 with the first run's `jobId`; nothing new starts.
|
|
13
|
+
*/
|
|
14
|
+
run(params, options) {
|
|
15
|
+
return this.client.request("POST", "/v1/cast-swap", {
|
|
16
|
+
body: params,
|
|
17
|
+
...options?.idempotencyKey ? { headers: { "Idempotency-Key": options.idempotencyKey } } : {}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** Quote a run before starting it (`POST /v1/cast-swap/estimate`); spends nothing. */
|
|
21
|
+
estimate(params) {
|
|
22
|
+
return this.client.request("POST", "/v1/cast-swap/estimate", { body: params });
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Quote finishing a draft at Full Quality (`POST
|
|
26
|
+
* /v1/cast-swap/:jobId/full-quality/estimate`); spends nothing. `jobId` is a
|
|
27
|
+
* finished DRAFT run (a Cast Swap or trend run made as a draft). The quote
|
|
28
|
+
* does not look for a Full Quality already running: when one is,
|
|
29
|
+
* {@link fullQuality} answers it (`existing: true`) and charges nothing.
|
|
30
|
+
* Refusals: {@link CastSwapFullQualityRefusalCode}.
|
|
31
|
+
*/
|
|
32
|
+
fullQualityEstimate(jobId) {
|
|
33
|
+
return this.client.request("POST", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality/estimate`, { body: {} });
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Finish a draft at Full Quality (`POST /v1/cast-swap/:jobId/full-quality`):
|
|
37
|
+
* the same take re-rendered at 1080p, with the clip's audio, as a new job
|
|
38
|
+
* linked to the draft. SPENDS CREDITS: quote it first with
|
|
39
|
+
* {@link fullQualityEstimate}. Answers 202 `{ jobId }`, or 200
|
|
40
|
+
* `{ jobId, existing: true }` when this draft's Full Quality is already
|
|
41
|
+
* running or done (one per draft; a failed one may be asked again). Follow
|
|
42
|
+
* the job with `client.jobs.get(jobId)`. No `Idempotency-Key` is taken: the
|
|
43
|
+
* server keys the job by the draft. The new job keeps the draft's origin.
|
|
44
|
+
* Refusals: {@link CastSwapFullQualityRefusalCode}.
|
|
45
|
+
*/
|
|
46
|
+
fullQuality(jobId, params = {}) {
|
|
47
|
+
const body = params.sessionId !== void 0 ? { sessionId: params.sessionId } : {};
|
|
48
|
+
return this.client.request("POST", `/v1/cast-swap/${encodeURIComponent(jobId)}/full-quality`, { body });
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { CastSwapResource };
|
|
53
|
+
//# sourceMappingURL=chunk-ED3ZOX3M.js.map
|
|
54
|
+
//# sourceMappingURL=chunk-ED3ZOX3M.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/cast-swap.ts"],"names":[],"mappings":";AA4WO,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,SAAS,MAAA,EAAmD;AAC1D,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,MAAA,EAAQ,0BAA0B,EAAE,IAAA,EAAM,QAAQ,CAAA;AAAA,EAC/E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,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,EAaA,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-ED3ZOX3M.js","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Cast Swap — replace the people, pets, products and/or the location in a\n * short video with your own references, keeping its motion, framing, timing\n * and sound (the clip's 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 * 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, a `faceMasking` setting\n * out of range), `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); 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/** 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 * Margins of the frame, each 0–49 % (default 0): a face whose centre lies in a\n * margin is not masked, so only faces inside the inner rectangle are.\n */\nexport interface CastSwapFaceMaskingZone {\n /** % of the frame's width from the left edge. Default 0. */\n leftPct?: number\n /** % of the frame's width from the right edge. Default 0. */\n rightPct?: number\n /** % of the frame's height from the top edge. Default 0. */\n topPct?: number\n /** % of the frame's height from the bottom edge. Default 0. */\n bottomPct?: number\n}\n\n/**\n * Face masking: the faces in the source clip are covered before the video\n * model sees it, keeping their movement and lip timing while the rest of the\n * clip is sent as it is.\n *\n * - `\"off\"` (the same as leaving `faceMasking` out): the clip is sent as it is.\n * - `\"always\"`: the faces are masked before the first attempt. Its credits are\n * in the quote (`breakdown.masking`, counted in `totalCredits`).\n * - `\"auto\"`: the run starts unmasked; only if the video model refuses the\n * source clip is it retried once with the faces masked. Any other failure is\n * not retried. The extra credits, charged only when that retry runs, are the\n * estimate's `maskingCredits` (not in `totalCredits`).\n *\n * A completed job's output carries `faceMasking: { applied, reason }`:\n * `applied` is whether the video was made from the masked clip, and `reason`\n * is `\"always\"` (masked before the first attempt), `\"input_refused\"` (`auto`\n * retried after the source clip was refused), `\"no_faces\"` (no face was left\n * to mask after the filters: an `always` run continues unmasked; an `auto`\n * run fails with the original refusal instead) or `\"off\"`.\n */\nexport interface CastSwapFaceMasking {\n mode: \"off\" | \"always\" | \"auto\"\n /** What covers a masked face: `\"blur\"` (default) or `\"depth\"` (a depth-color view of it). */\n fill?: \"blur\" | \"depth\"\n /** Mask only faces at least this % of the frame's height, 0–100. Default 15. */\n minFaceHeightPct?: number\n /**\n * Mask only faces at most this % of the frame's height, 0–100. Default 0 (no\n * limit). When above 0 it must be at least `minFaceHeightPct` (else 400).\n */\n maxFaceHeightPct?: number\n /** Leave out faces near the edges of the frame. Default: no margins. */\n zone?: CastSwapFaceMaskingZone\n /** The blur's strength, 0.1–5 % of the frame's width (`fill: \"blur\"`). Default 2. */\n blurStrengthPct?: number\n /** How sure the face finder must be, 0.05–0.95: lower finds more faces. Default 0.5. */\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 /** The output resolution. Default `\"480p\"`. */\n resolution?: \"480p\" | \"720p\" | \"1080p\"\n /**\n * Render as a draft. Defaults to `true` at 480p and `false` above it; `true`\n * with `\"720p\"` or `\"1080p\"` answers 400 (draft is 480p only).\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 /** Mask the faces in the source clip (see {@link CastSwapFaceMasking}). Default: off. */\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 quote in credits: `breakdown.castSwap + breakdown.seedance +\n * breakdown.references`, plus `breakdown.masking` with face masking\n * `\"always\"`.\n */\n totalCredits: number\n /**\n * `castSwap`: the run itself; `seedance`: the video model it calls;\n * `references`: preparing the reference pictures (0 when `prepareReferences`\n * is off or there is nothing to prepare); `masking`: masking the faces,\n * present only when `faceMasking` is on. With `\"auto\"` it equals\n * `maskingCredits` and is not added to `totalCredits`.\n */\n breakdown: { castSwap: number; seedance: number; references: number; masking?: number }\n /**\n * Face masking `\"auto\"` only: the extra credits charged if the source clip\n * is refused and the run is retried with the faces masked. Not in\n * `totalCredits`; `run()` needs credits for both (else 402).\n */\n maskingCredits?: number\n /** `true` when the video is made at Auto length: the final charge is expected to come out lower than this quote. */\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 finishing a draft at Full Quality would cost\n * (`POST /v1/cast-swap/:jobId/full-quality/estimate`).\n */\nexport interface CastSwapFullQualityEstimate {\n /** The quote in credits: `breakdown.castSwap + breakdown.seedanceHd`. */\n totalCredits: number\n /**\n * `castSwap`: the Full Quality job's own steps; `seedanceHd`: the 1080p\n * render of the draft's take (0 when an earlier try of this draft already\n * finished that render, which is then reused).\n */\n breakdown: { castSwap: number; seedanceHd: number }\n /** ISO time until which the draft 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 draft'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 Cast Swap 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 was not made as a draft;\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 Cast Swap 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 estimate(params: CastSwapParams): Promise<CastSwapEstimate> {\n return this.client.request(\"POST\", \"/v1/cast-swap/estimate\", { body: params })\n }\n\n /**\n * Quote finishing a draft at Full Quality (`POST\n * /v1/cast-swap/:jobId/full-quality/estimate`); spends nothing. `jobId` is a\n * finished DRAFT run (a Cast Swap or trend run made as a draft). 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 draft at Full Quality (`POST /v1/cast-swap/:jobId/full-quality`):\n * the same take re-rendered at 1080p, with the clip's audio, as a new job\n * linked to the draft. SPENDS CREDITS: quote it first with\n * {@link fullQualityEstimate}. Answers 202 `{ jobId }`, or 200\n * `{ jobId, existing: true }` when this draft's Full Quality is already\n * running or done (one per draft; 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"]}
|
|
@@ -23,5 +23,5 @@ var TemplatesResource = class {
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
exports.TemplatesResource = TemplatesResource;
|
|
26
|
-
//# sourceMappingURL=chunk-
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
26
|
+
//# sourceMappingURL=chunk-EK672FFM.cjs.map
|
|
27
|
+
//# sourceMappingURL=chunk-EK672FFM.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/resources/templates.ts"],"names":[],"mappings":";;;AA4GO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YAAoB,MAAA,EAA0B;AAA1B,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EAA2B;AAAA,EAA3B,MAAA;AAAA;AAAA,EAGpB,MAAA,CAAO,MAAA,GAAgC,EAAC,EAAmC;AACzE,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,OAAA,CAAQ,KAAA,EAAO,sBAAA,EAAwB,EAAE,KAAA,EAAO,EAAE,GAAG,MAAA,EAAO,EAAG,CAAA;AAAA,EACpF;AAAA;AAAA,EAGA,IAAI,IAAA,EAAiC;AACnC,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,KAAA,EAAO,iBAAiB,kBAAA,CAAmB,IAAI,CAAC,CAAA,CAAE,CAAA;AAAA,EAC/E;AAAA;AAAA,EAGA,KAAA,CAAM,MAAc,MAAA,EAA2D;AAC7E,IAAA,OAAO,IAAA,CAAK,OAAO,OAAA,CAAQ,MAAA,EAAQ,iBAAiB,kBAAA,CAAmB,IAAI,CAAC,CAAA,MAAA,CAAA,EAAU;AAAA,MACpF,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF","file":"chunk-EK672FFM.cjs","sourcesContent":["import type { NodaroClientCore } from \"../core.js\"\n\n/**\n * Workflow-template marketplace — the PUBLIC-BY-DESIGN surfaces only:\n * browse cards, a single template with its full snapshot, and the free\n * clone-into-my-project action. Creator/admin surfaces (publish, mine,\n * favorites, metadata patch, tutorial flags) are deliberately NOT part of\n * the public SDK contract; first-party apps reach them via\n * `client.request()`.\n */\n\n/** Card returned by the marketplace browse (no snapshot payload). */\nexport interface TemplateBrowseCard {\n id: string\n slug: string\n name: string\n description: string | null\n /** The listed price; when `estimatedPerMinuteCredits` is above 0, its fixed part. */\n estimatedCredits: number\n /** The listed price holds a metered LLM call's ESTIMATE (its model's typical\n * call, charged its actual usage per token): show it `~N`. Absent for a\n * fixed price, and on a deployment running the tier-pricing rollback. */\n estimatedCreditsIsEstimate?: true\n /**\n * Credits per minute of the recording the template is given, when its price\n * follows that recording's length (an Apply EDL render of a whole episode,\n * an Edit Plan pass): the price is `estimatedCredits` plus this per minute.\n * 0 or absent when the price does not depend on a recording's length.\n */\n estimatedPerMinuteCredits?: number\n /**\n * The listed price is a range: `estimatedCredits` / `estimatedPerMinuteCredits`\n * are \"from\" (the saved settings), these \"up to\" — the most a run can cost over\n * the template's exposed fields. Present only when they differ from \"from\".\n */\n maxEstimatedCredits?: number\n maxEstimatedPerMinuteCredits?: number\n category: string\n outputTypes: string[]\n tags: string[]\n nodeTypesUsed: string[]\n providersUsed: string[]\n nodeCount: number\n complexity: string\n previewMediaUrl: string | null\n previewMediaType: \"image\" | \"video\" | null\n creatorId: string\n creatorDisplayName: string | null\n cloneCount: number\n favoriteCount: number\n createdAt: string\n}\n\nexport type TemplateSort = \"newest\" | \"popular\" | \"most-favorited\"\n\nexport interface BrowseTemplatesParams {\n /** Opaque cursor from the previous page's `nextCursor`. */\n cursor?: string\n limit?: number\n category?: string\n outputType?: string\n tag?: string\n /** Full-text search over name/description/tags. */\n search?: string\n sort?: TemplateSort\n /** Only templates using this node type. */\n nodeType?: string\n /** Only templates using this provider/model id. */\n provider?: string\n complexity?: string\n}\n\nexport interface BrowseTemplatesResult {\n data: TemplateBrowseCard[]\n /** Pass back as `cursor` to fetch the next page; `null` on the last page. */\n nextCursor: string | null\n}\n\n/**\n * A single public template (`GET /v1/templates/:slug`) — the browse-card\n * fields plus the full workflow snapshot the viewer/clone consume. The route\n * returns the whole camelCased row, so additional columns may appear beyond\n * the ones typed here; the index signature keeps them reachable without\n * casting.\n */\nexport interface Template extends TemplateBrowseCard {\n markdownDescription: string | null\n /** React Flow node snapshots (generic node JSON, execution data stripped on clone). */\n snapshotNodes: unknown[]\n snapshotEdges: unknown[]\n snapshotSettings: Record<string, unknown>\n /** Channels the template is listed in (e.g. \"marketplace\", \"tutorial\"). */\n listedIn: string[]\n readonly [key: string]: unknown\n}\n\nexport interface CloneTemplateParams {\n /** Target project (must belong to the caller). */\n projectId: string\n /** Optional name for the cloned workflow; defaults to the template's name. */\n name?: string\n}\n\nexport interface CloneTemplateResult {\n workflowId: string\n projectId: string\n}\n\nexport class TemplatesResource {\n constructor(private client: NodaroClientCore) {}\n\n /** Browse the public template marketplace (cursor-paginated, no auth required). */\n browse(params: BrowseTemplatesParams = {}): Promise<BrowseTemplatesResult> {\n return this.client.request(\"GET\", \"/v1/templates/browse\", { query: { ...params } })\n }\n\n /** Fetch one public template by slug, including its full workflow snapshot. */\n get(slug: string): Promise<Template> {\n return this.client.request(\"GET\", `/v1/templates/${encodeURIComponent(slug)}`)\n }\n\n /** Clone a template into one of the caller's projects. Free — no credits charged. */\n clone(slug: string, params: CloneTemplateParams): Promise<CloneTemplateResult> {\n return this.client.request(\"POST\", `/v1/templates/${encodeURIComponent(slug)}/clone`, {\n body: params,\n })\n }\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkFRQJNGJS_cjs = require('./chunk-FRQJNGJS.cjs');
|
|
4
4
|
|
|
5
5
|
// src/resources/media.ts
|
|
6
6
|
var MediaResource = class {
|
|
@@ -42,7 +42,7 @@ var MediaResource = class {
|
|
|
42
42
|
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
43
43
|
signal: opts.signal
|
|
44
44
|
});
|
|
45
|
-
yield*
|
|
45
|
+
yield* chunkFRQJNGJS_cjs.readSseStream(res, { label: "progress stream" });
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
48
|
* Copy an external media URL into your Nodaro storage (`POST /v1/save-to-storage`)
|
|
@@ -238,8 +238,32 @@ var MediaResource = class {
|
|
|
238
238
|
* to 5 minutes at 30 fps (a faster clip counts
|
|
239
239
|
* proportionally longer), priced by the clip's length. Poll
|
|
240
240
|
* `jobs.get(jobId)`: the output carries `videoUrl` (the mask), `width`,
|
|
241
|
-
* `height`, `frames
|
|
242
|
-
*
|
|
241
|
+
* `height`, `frames`, `coverage` (the fraction of pixels selected, rounded
|
|
242
|
+
* to 4 decimals) and `kept` (any region left on any frame: false only when
|
|
243
|
+
* the size / zone filters left an empty mask — read it rather than
|
|
244
|
+
* `coverage`, which a few pixels round to 0). Feed the mask to
|
|
245
|
+
* {@link MediaResource.maskComposite}.
|
|
246
|
+
*
|
|
247
|
+
* `holdLastMask: true` keeps the last mask on frames where the subject is
|
|
248
|
+
* lost (a mask covering under 0.002 % of the frame, e.g. a face behind a
|
|
249
|
+
* hand): each such frame after the first detection repeats the most recent
|
|
250
|
+
* non-empty one; the output then also carries `heldFrames`.
|
|
251
|
+
* `minSubjectHeightPct` (0–100, default 0 = off) drops every connected
|
|
252
|
+
* region whose bounding box is shorter than that % of the frame height
|
|
253
|
+
* (extras' small faces behind the main subject); it runs before
|
|
254
|
+
* `holdLastMask`, and the output then carries `droppedRegions`.
|
|
255
|
+
* `maxSubjectHeightPct` (0–100, default 0 = off) is its mirror: it drops
|
|
256
|
+
* regions TALLER than that % (keep only the small background faces). With
|
|
257
|
+
* both set a region is kept when min ≤ height ≤ max; min > max is a 400.
|
|
258
|
+
* `zone` (`{ leftPct, rightPct, topPct, bottomPct }`, each 0–49 % of the
|
|
259
|
+
* frame, a margin left out = 0; default null = off) keeps only the regions
|
|
260
|
+
* whose bounding-box centre lies inside the frame minus those margins (after
|
|
261
|
+
* the size cuts, before `holdLastMask`). `perShot: true` finds the clip's
|
|
262
|
+
* scene cuts first and segments each shot on its own: the subject is
|
|
263
|
+
* detected again after every cut, `holdLastMask` never crosses a cut, and
|
|
264
|
+
* each shot's mask is fitted to that shot's exact frame count; on a clip
|
|
265
|
+
* with no cut it gives the same mask, fitted to the clip's exact frame
|
|
266
|
+
* count. The output carries `shots` (1 when off).
|
|
243
267
|
*/
|
|
244
268
|
videoMask(input) {
|
|
245
269
|
return this.client.request("POST", "/v1/video-mask", { body: input });
|
|
@@ -250,9 +274,19 @@ var MediaResource = class {
|
|
|
250
274
|
* The result follows the foreground's size, frame rate and length; the
|
|
251
275
|
* background is fitted (`backgroundFit`, default cover) and loops when
|
|
252
276
|
* shorter; the mask holds its last frame when shorter. Optional
|
|
253
|
-
* `invertMask`, `feather` (0–20 px), `grow` (−10–10 px)
|
|
254
|
-
*
|
|
255
|
-
*
|
|
277
|
+
* `invertMask`, `feather` (0–20 px), `grow` (−10–10 px), `opacity` (0–1,
|
|
278
|
+
* default 1: how strongly the foreground covers the background inside the
|
|
279
|
+
* mask) and `audioSource` (foreground / background / mix / none). Priced per started 5 seconds of
|
|
280
|
+
* the result (the video it follows up to 300 s). Poll `jobs.get(jobId)` for `videoUrl`.
|
|
281
|
+
*
|
|
282
|
+
* `fill` picks what fills the masked area: `video` (default — the
|
|
283
|
+
* foreground, required then), `pixelate` (the background itself in
|
|
284
|
+
* blocks of `pixelSizePct` % of the frame width, 0.2–10, default 1.25) or
|
|
285
|
+
* `blur` (the background blurred, sigma `blurStrengthPct` % of the frame
|
|
286
|
+
* width, 0.1–5, default 2). Pixelate and blur take no
|
|
287
|
+
* `foregroundUrl` (one sent is ignored): the result follows the background
|
|
288
|
+
* and is priced on its length, and it always carries the background's sound
|
|
289
|
+
* (`audioSource` is ignored).
|
|
256
290
|
*/
|
|
257
291
|
maskComposite(input) {
|
|
258
292
|
return this.client.request("POST", "/v1/mask-composite", { body: input });
|
|
@@ -278,5 +312,5 @@ var MediaResource = class {
|
|
|
278
312
|
};
|
|
279
313
|
|
|
280
314
|
exports.MediaResource = MediaResource;
|
|
281
|
-
//# sourceMappingURL=chunk-
|
|
282
|
-
//# sourceMappingURL=chunk-
|
|
315
|
+
//# sourceMappingURL=chunk-ETX3TLNB.cjs.map
|
|
316
|
+
//# sourceMappingURL=chunk-ETX3TLNB.cjs.map
|