@fuserstudio/sdk 0.0.0-stage → 0.0.1

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/index.d.ts ADDED
@@ -0,0 +1,2607 @@
1
+ //#region src/generated/types.gen.d.ts
2
+ type ApiError = {
3
+ /**
4
+ * The HTTP error kind, e.g. NOT_FOUND or CONFLICT.
5
+ */
6
+ code: string;
7
+ message: string;
8
+ /**
9
+ * Which conflict a 409 is: stale_revision, idempotency_key_reused or canvas_not_editable.
10
+ */
11
+ reason?: string;
12
+ issues?: Array<{
13
+ message: string;
14
+ path: string;
15
+ }>;
16
+ };
17
+ type CanvasListData = {
18
+ body?: never;
19
+ path?: never;
20
+ query?: {
21
+ query?: string;
22
+ workspaceId?: string | 'personal';
23
+ limit?: number;
24
+ cursor?: string;
25
+ };
26
+ url: '/v1/canvas_list';
27
+ };
28
+ type CanvasListErrors = {
29
+ /**
30
+ * The input is invalid.
31
+ */
32
+ 400: ApiError;
33
+ /**
34
+ * No valid API key.
35
+ */
36
+ 401: ApiError;
37
+ /**
38
+ * The key or user can't do this.
39
+ */
40
+ 403: ApiError;
41
+ /**
42
+ * The canvas, run, node or upload was not found.
43
+ */
44
+ 404: ApiError;
45
+ /**
46
+ * Too many requests; wait Retry-After seconds.
47
+ */
48
+ 429: ApiError;
49
+ /**
50
+ * Something went wrong on our side.
51
+ */
52
+ 500: ApiError;
53
+ };
54
+ type CanvasListResponses = {
55
+ /**
56
+ * Successful response
57
+ */
58
+ 200: {
59
+ canvases: Array<{
60
+ canvasId: string;
61
+ title: string;
62
+ /**
63
+ * The workspace it is in; null for your personal space.
64
+ */
65
+ workspaceId: string | null;
66
+ updatedAt: string | null;
67
+ url: string;
68
+ }>;
69
+ nextCursor: string | null;
70
+ };
71
+ };
72
+ type CanvasGetData = {
73
+ body?: never;
74
+ path?: never;
75
+ query: {
76
+ canvasId: string;
77
+ cursor?: string;
78
+ nodeIds?: Array<string>;
79
+ search?: string;
80
+ };
81
+ url: '/v1/canvas_get';
82
+ };
83
+ type CanvasGetErrors = {
84
+ /**
85
+ * The input is invalid.
86
+ */
87
+ 400: ApiError;
88
+ /**
89
+ * No valid API key.
90
+ */
91
+ 401: ApiError;
92
+ /**
93
+ * The key or user can't do this.
94
+ */
95
+ 403: ApiError;
96
+ /**
97
+ * The canvas, run, node or upload was not found.
98
+ */
99
+ 404: ApiError;
100
+ /**
101
+ * Too many requests; wait Retry-After seconds.
102
+ */
103
+ 429: ApiError;
104
+ /**
105
+ * Something went wrong on our side.
106
+ */
107
+ 500: ApiError;
108
+ };
109
+ type CanvasGetResponses = {
110
+ /**
111
+ * Successful response
112
+ */
113
+ 200: {
114
+ canvasId: string;
115
+ title: string;
116
+ url: string;
117
+ revision: number;
118
+ summary: {
119
+ nodeCount: number;
120
+ edgeCount: number;
121
+ nodesByType: {
122
+ [key: string]: number;
123
+ };
124
+ /**
125
+ * The box around every node.
126
+ */
127
+ bounds: {
128
+ x: number;
129
+ y: number;
130
+ width: number;
131
+ height: number;
132
+ } | null;
133
+ };
134
+ nodes: Array<{
135
+ id: string;
136
+ type?: string;
137
+ label?: string;
138
+ /**
139
+ * Left edge on the canvas (larger is further right), the same coordinates canvas_edit moveNodes and canvas_arrange take.
140
+ */
141
+ x?: number;
142
+ /**
143
+ * Top edge; larger is further down.
144
+ */
145
+ y?: number;
146
+ /**
147
+ * Drawn width.
148
+ */
149
+ width?: number;
150
+ /**
151
+ * Drawn height.
152
+ */
153
+ height?: number;
154
+ /**
155
+ * The group node it sits in.
156
+ */
157
+ group?: string;
158
+ in: Array<string>;
159
+ out: Array<string>;
160
+ values?: {
161
+ [key: string]: string;
162
+ };
163
+ results?: Array<string>;
164
+ }>;
165
+ edges: Array<{
166
+ from: string;
167
+ to: string;
168
+ }>;
169
+ nextCursor: string | null;
170
+ };
171
+ };
172
+ type CanvasEditData = {
173
+ body: {
174
+ /**
175
+ * Canvas to edit. Omit it and pass newCanvas to create one.
176
+ */
177
+ canvasId?: string;
178
+ /**
179
+ * Rename the canvas. With canvasId only; a new canvas takes newCanvas.name. The diff may be empty when this is all you're changing.
180
+ */
181
+ title?: string;
182
+ /**
183
+ * Create a new canvas with this name and apply the diff to it.
184
+ */
185
+ newCanvas?: {
186
+ name: string;
187
+ /**
188
+ * Workspace to create it in, from account_get. Omit for your personal space.
189
+ */
190
+ workspaceId?: string;
191
+ };
192
+ /**
193
+ * A fresh random value, such as a UUID, for each new edit; never reuse one from an earlier edit. Resend the same key only when retrying this same edit.
194
+ */
195
+ idempotencyKey: string;
196
+ /**
197
+ * The revision from your latest canvas_get or canvas_edit. If someone has edited the canvas since, the edit still applies unless it touches nodes they changed; then it is refused, naming them. Results arriving from runs never count.
198
+ */
199
+ expectedRevision?: number;
200
+ diff: {
201
+ nodes?: Array<{
202
+ /**
203
+ * Local id, unique in this diff, referenced by edges.
204
+ */
205
+ ref: string;
206
+ /**
207
+ * Node type key from the vocabulary.
208
+ */
209
+ type: string;
210
+ /**
211
+ * Short role-specific display name for this node.
212
+ */
213
+ label: string;
214
+ /**
215
+ * Literal input values as {id, value} pairs, using allowed input ids. Use an empty array when every input comes from edges.
216
+ */
217
+ inputs: Array<{
218
+ id: string;
219
+ /**
220
+ * Literal input value.
221
+ */
222
+ value: string | number | boolean | Array<string>;
223
+ }>;
224
+ }>;
225
+ edges?: Array<{
226
+ /**
227
+ * Source socket: "ref.outputId" for a new node, or "#nodeId.outputId" for an existing canvas node.
228
+ */
229
+ from: string;
230
+ /**
231
+ * Target socket: "ref.inputId" for a new node, or "#nodeId.inputId" for an existing canvas node.
232
+ */
233
+ to: string;
234
+ }>;
235
+ /**
236
+ * Existing edges to remove before applying the rest of this edit. Both ends must use "#nodeId.socket" refs. Empty array when no standalone disconnection is needed.
237
+ */
238
+ disconnectEdges?: Array<{
239
+ /**
240
+ * Source socket: "ref.outputId" for a new node, or "#nodeId.outputId" for an existing canvas node.
241
+ */
242
+ from: string;
243
+ /**
244
+ * Target socket: "ref.inputId" for a new node, or "#nodeId.inputId" for an existing canvas node.
245
+ */
246
+ to: string;
247
+ }>;
248
+ /**
249
+ * Input changes on existing canvas nodes (edit mode only). Empty array otherwise.
250
+ */
251
+ setInputs?: Array<{
252
+ /**
253
+ * Existing canvas node id.
254
+ */
255
+ nodeId: string;
256
+ inputId: string;
257
+ /**
258
+ * Literal input value.
259
+ */
260
+ value: string | number | boolean | Array<string>;
261
+ }>;
262
+ /**
263
+ * Existing canvas node ids to DELETE (edit mode only — e.g. when replacing a node with a different type). Deleting a node also removes its edges. Empty array otherwise.
264
+ */
265
+ deleteNodeIds?: Array<string>;
266
+ /**
267
+ * Change how large existing nodes are drawn on the canvas. This is not the output's resolution or aspect ratio, which are node inputs. A media node's height follows its media's shape. Nothing else moves: nodes a bigger node now covers come back in overlaps, and canvas_arrange lays them out again.
268
+ */
269
+ resizeNodes?: Array<{
270
+ /**
271
+ * An existing node id.
272
+ */
273
+ nodeId: string;
274
+ /**
275
+ * New width in canvas pixels. Outputs are drawn 320 wide by default.
276
+ */
277
+ width: number;
278
+ }>;
279
+ /**
280
+ * Move existing nodes to exact spots. To lay several out in a row, column, grid or along their wiring, use canvas_arrange instead of working out positions.
281
+ */
282
+ moveNodes?: Array<{
283
+ /**
284
+ * An existing node id.
285
+ */
286
+ nodeId: string;
287
+ /**
288
+ * New left edge, in canvas_get's coordinates.
289
+ */
290
+ x: number;
291
+ /**
292
+ * New top edge, in canvas_get's coordinates.
293
+ */
294
+ y: number;
295
+ }>;
296
+ /**
297
+ * Rename existing nodes (the name shown on the node). Nothing moves. New nodes take their name from label.
298
+ */
299
+ renameNodes?: Array<{
300
+ /**
301
+ * An existing node id.
302
+ */
303
+ nodeId: string;
304
+ /**
305
+ * Its new name.
306
+ */
307
+ label: string;
308
+ }>;
309
+ /**
310
+ * Make a labelled group (a frame on the canvas) around nodes, add nodes to an existing group, or recolor one. The frame grows to fit. Lay nodes out first with canvas_arrange if they are spread out. Deleting a group node keeps its members.
311
+ */
312
+ groups?: Array<{
313
+ /**
314
+ * Name for a new group. Pass this or groupId.
315
+ */
316
+ label?: string;
317
+ /**
318
+ * An existing group to add the nodes to or recolor.
319
+ */
320
+ groupId?: string;
321
+ /**
322
+ * Nodes to put in the group where they sit now: existing ids (moved out of any other group) or refs of nodes this edit adds.
323
+ */
324
+ nodeIds?: Array<string>;
325
+ /**
326
+ * Frame color. gray is the default.
327
+ */
328
+ color?: 'gray' | 'purple' | 'mint' | 'sky' | 'tangerine' | 'rose';
329
+ }>;
330
+ /**
331
+ * Take these nodes out of their group, leaving them where they are.
332
+ */
333
+ ungroupNodeIds?: Array<string>;
334
+ };
335
+ };
336
+ path?: never;
337
+ query?: never;
338
+ url: '/v1/canvas_edit';
339
+ };
340
+ type CanvasEditErrors = {
341
+ /**
342
+ * The input is invalid.
343
+ */
344
+ 400: ApiError;
345
+ /**
346
+ * No valid API key.
347
+ */
348
+ 401: ApiError;
349
+ /**
350
+ * The key or user can't do this.
351
+ */
352
+ 403: ApiError;
353
+ /**
354
+ * The canvas, run, node or upload was not found.
355
+ */
356
+ 404: ApiError;
357
+ /**
358
+ * Conflicts with an earlier request; see reason.
359
+ */
360
+ 409: ApiError;
361
+ /**
362
+ * Too many requests; wait Retry-After seconds.
363
+ */
364
+ 429: ApiError;
365
+ /**
366
+ * Something went wrong on our side.
367
+ */
368
+ 500: ApiError;
369
+ };
370
+ type CanvasEditResponses = {
371
+ /**
372
+ * Successful response
373
+ */
374
+ 200: {
375
+ canvasId: string;
376
+ url: string;
377
+ revision: number;
378
+ createdNodeIds: {
379
+ [key: string]: string;
380
+ };
381
+ warnings: Array<string>;
382
+ /**
383
+ * Moved or resized nodes that now overlap another node. Lay them out with canvas_arrange, or move them.
384
+ */
385
+ overlaps: Array<{
386
+ nodeId: string;
387
+ overlapsWith: string;
388
+ }>;
389
+ replayed: boolean;
390
+ };
391
+ };
392
+ type CanvasArrangeData = {
393
+ body: {
394
+ canvasId: string;
395
+ /**
396
+ * Nodes to arrange, all at the top level or all in the same group. With layout, this order is the placement order.
397
+ */
398
+ nodeIds?: Array<string>;
399
+ /**
400
+ * Tidy every top-level node on the canvas. Only when the user asked to reorganize the whole canvas: it moves work they placed by hand.
401
+ */
402
+ all?: boolean;
403
+ layout?: {
404
+ /**
405
+ * row: left to right. column: top to bottom. grid: rows of `columns`.
406
+ */
407
+ mode: 'row' | 'column' | 'grid';
408
+ /**
409
+ * Nodes per row for grid; defaults to about the square root of the count.
410
+ */
411
+ columns?: number;
412
+ /**
413
+ * Space between nodes, in canvas pixels. Default 64.
414
+ */
415
+ gap?: number;
416
+ /**
417
+ * Top-left corner of the block, in canvas_get's coordinates. It is used as given, even over other nodes.
418
+ */
419
+ origin?: {
420
+ x: number;
421
+ y: number;
422
+ };
423
+ };
424
+ /**
425
+ * The revision from your latest canvas_get or canvas_edit; the call is refused only if someone changed these nodes since.
426
+ */
427
+ expectedRevision?: number;
428
+ };
429
+ path?: never;
430
+ query?: never;
431
+ url: '/v1/canvas_arrange';
432
+ };
433
+ type CanvasArrangeErrors = {
434
+ /**
435
+ * The input is invalid.
436
+ */
437
+ 400: ApiError;
438
+ /**
439
+ * No valid API key.
440
+ */
441
+ 401: ApiError;
442
+ /**
443
+ * The key or user can't do this.
444
+ */
445
+ 403: ApiError;
446
+ /**
447
+ * The canvas, run, node or upload was not found.
448
+ */
449
+ 404: ApiError;
450
+ /**
451
+ * Too many requests; wait Retry-After seconds.
452
+ */
453
+ 429: ApiError;
454
+ /**
455
+ * Something went wrong on our side.
456
+ */
457
+ 500: ApiError;
458
+ };
459
+ type CanvasArrangeResponses = {
460
+ /**
461
+ * Successful response
462
+ */
463
+ 200: {
464
+ canvasId: string;
465
+ url: string;
466
+ revision: number;
467
+ arranged: number;
468
+ moved: number;
469
+ /**
470
+ * The arranged block's box; place more work below or beside it.
471
+ */
472
+ bounds: {
473
+ x: number;
474
+ y: number;
475
+ width: number;
476
+ height: number;
477
+ };
478
+ /**
479
+ * Arranged nodes that overlap other nodes, possible with an explicit origin. Arrange again without an origin to clear them.
480
+ */
481
+ overlaps: Array<{
482
+ nodeId: string;
483
+ overlapsWith: string;
484
+ }>;
485
+ };
486
+ };
487
+ type CatalogSearchData = {
488
+ body?: never;
489
+ path?: never;
490
+ query?: {
491
+ query?: string;
492
+ category?: 'image' | 'video' | 'text' | 'mesh' | 'primitive';
493
+ };
494
+ url: '/v1/catalog_search';
495
+ };
496
+ type CatalogSearchErrors = {
497
+ /**
498
+ * The input is invalid.
499
+ */
500
+ 400: ApiError;
501
+ /**
502
+ * No valid API key.
503
+ */
504
+ 401: ApiError;
505
+ /**
506
+ * The key or user can't do this.
507
+ */
508
+ 403: ApiError;
509
+ /**
510
+ * The canvas, run, node or upload was not found.
511
+ */
512
+ 404: ApiError;
513
+ /**
514
+ * Too many requests; wait Retry-After seconds.
515
+ */
516
+ 429: ApiError;
517
+ /**
518
+ * Something went wrong on our side.
519
+ */
520
+ 500: ApiError;
521
+ };
522
+ type CatalogSearchResponses = {
523
+ /**
524
+ * Successful response
525
+ */
526
+ 200: {
527
+ /**
528
+ * False when nothing matched the query; nodeTypes then lists everything available.
529
+ */
530
+ matched: boolean;
531
+ note?: string;
532
+ /**
533
+ * The node to use for each common job, with the input values to set.
534
+ */
535
+ recommended: Array<{
536
+ job: string;
537
+ type: string;
538
+ inputs?: {
539
+ [key: string]: string;
540
+ };
541
+ /**
542
+ * About what one run costs at its cheapest settings.
543
+ */
544
+ credits?: number;
545
+ }>;
546
+ nodeTypes: Array<{
547
+ type: string;
548
+ category: 'image' | 'video' | 'text' | 'mesh' | 'primitive';
549
+ purpose: string;
550
+ inputs: Array<{
551
+ id: string;
552
+ kind: 'text' | 'number' | 'boolean' | 'enum' | 'image' | 'video' | 'media';
553
+ description: string;
554
+ required?: boolean;
555
+ multiple?: boolean;
556
+ values?: Array<string>;
557
+ min?: number;
558
+ max?: number;
559
+ defaultValue?: string | number | boolean;
560
+ }>;
561
+ output: string;
562
+ notes?: Array<string>;
563
+ /**
564
+ * About what one run costs at its cheapest settings, per model or variant, cheapest first. Compare these to pick a cheaper model; run_start dryRun gives the exact price on a canvas.
565
+ */
566
+ prices?: Array<{
567
+ variant: string;
568
+ credits: number;
569
+ settings: string;
570
+ }>;
571
+ }>;
572
+ };
573
+ };
574
+ type RunStartData = {
575
+ body: {
576
+ canvasId: string;
577
+ /**
578
+ * Nodes to run, plus whatever they need upstream. Omit to run the whole canvas.
579
+ */
580
+ nodeIds?: Array<string>;
581
+ /**
582
+ * The most this run may cost; it is refused above it. Required unless dryRun.
583
+ */
584
+ maxCredits?: number;
585
+ /**
586
+ * A fresh random value, such as a UUID, for each new run; required unless dryRun. Resend the same key only when retrying this same run; the first run is returned instead of starting another.
587
+ */
588
+ idempotencyKey?: string;
589
+ /**
590
+ * Only price the run and list anything blocking it; nothing starts and nothing is spent.
591
+ */
592
+ dryRun?: boolean;
593
+ };
594
+ path?: never;
595
+ query?: never;
596
+ url: '/v1/run_start';
597
+ };
598
+ type RunStartErrors = {
599
+ /**
600
+ * The input is invalid.
601
+ */
602
+ 400: ApiError;
603
+ /**
604
+ * No valid API key.
605
+ */
606
+ 401: ApiError;
607
+ /**
608
+ * The key or user can't do this.
609
+ */
610
+ 403: ApiError;
611
+ /**
612
+ * The canvas, run, node or upload was not found.
613
+ */
614
+ 404: ApiError;
615
+ /**
616
+ * Conflicts with an earlier request; see reason.
617
+ */
618
+ 409: ApiError;
619
+ /**
620
+ * Too many requests; wait Retry-After seconds.
621
+ */
622
+ 429: ApiError;
623
+ /**
624
+ * Something went wrong on our side.
625
+ */
626
+ 500: ApiError;
627
+ };
628
+ type RunStartResponses = {
629
+ /**
630
+ * Successful response
631
+ */
632
+ 200: {
633
+ status: 'quoted';
634
+ quote: {
635
+ nodeIds: Array<string>;
636
+ credits: number;
637
+ /**
638
+ * Chat nodes and paid tools, included in credits at a rough guess. The run is charged what they actually cost.
639
+ */
640
+ guessedNodeIds: Array<string>;
641
+ unpricedNodeIds: Array<string>;
642
+ blockers: Array<{
643
+ code: 'active_run_exists' | 'compositor_participates' | 'unsupported_node' | 'missing_required_input' | 'dependency_cycle' | 'no_executable_nodes' | 'stale_preflight' | 'expired_preflight' | 'unbuilt_tool' | 'insufficient_credits';
644
+ nodeId?: string;
645
+ message: string;
646
+ }>;
647
+ };
648
+ /**
649
+ * Where Fuser's plans are described, when the plan or credits are why the run is blocked or refused.
650
+ */
651
+ plansUrl?: string;
652
+ } | {
653
+ status: 'started';
654
+ runId: string;
655
+ /**
656
+ * True when this idempotencyKey had already started the run.
657
+ */
658
+ replayed: boolean;
659
+ quote: {
660
+ nodeIds: Array<string>;
661
+ credits: number;
662
+ /**
663
+ * Chat nodes and paid tools, included in credits at a rough guess. The run is charged what they actually cost.
664
+ */
665
+ guessedNodeIds: Array<string>;
666
+ unpricedNodeIds: Array<string>;
667
+ blockers: Array<{
668
+ code: 'active_run_exists' | 'compositor_participates' | 'unsupported_node' | 'missing_required_input' | 'dependency_cycle' | 'no_executable_nodes' | 'stale_preflight' | 'expired_preflight' | 'unbuilt_tool' | 'insufficient_credits';
669
+ nodeId?: string;
670
+ message: string;
671
+ }>;
672
+ };
673
+ run?: {
674
+ runId: string;
675
+ status: 'running' | 'completed' | 'failed' | 'cancelled';
676
+ quotedCredits: number;
677
+ /**
678
+ * ISO 8601.
679
+ */
680
+ startedAt: string;
681
+ /**
682
+ * ISO 8601.
683
+ */
684
+ completedAt?: string;
685
+ nodes: Array<{
686
+ nodeId: string;
687
+ type: string | null;
688
+ status: 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'cancelled' | 'unknown';
689
+ error?: string;
690
+ /**
691
+ * Links to the node's current results.
692
+ */
693
+ outputs: Array<string>;
694
+ /**
695
+ * The node's text result (a chat reply, or a tool's text or json), cut at 4,000 characters.
696
+ */
697
+ text?: string;
698
+ }>;
699
+ /**
700
+ * Where Fuser's plans are described, when a node failed because the plan doesn't include it.
701
+ */
702
+ plansUrl?: string;
703
+ };
704
+ } | {
705
+ status: 'refused';
706
+ reason: 'blocked' | 'over_budget' | 'insufficient_credits' | 'missing_max_credits' | 'unpriced' | 'start_failed';
707
+ error: string;
708
+ quote?: {
709
+ nodeIds: Array<string>;
710
+ credits: number;
711
+ /**
712
+ * Chat nodes and paid tools, included in credits at a rough guess. The run is charged what they actually cost.
713
+ */
714
+ guessedNodeIds: Array<string>;
715
+ unpricedNodeIds: Array<string>;
716
+ blockers: Array<{
717
+ code: 'active_run_exists' | 'compositor_participates' | 'unsupported_node' | 'missing_required_input' | 'dependency_cycle' | 'no_executable_nodes' | 'stale_preflight' | 'expired_preflight' | 'unbuilt_tool' | 'insufficient_credits';
718
+ nodeId?: string;
719
+ message: string;
720
+ }>;
721
+ };
722
+ /**
723
+ * Where Fuser's plans are described, when the plan or credits are why the run is blocked or refused.
724
+ */
725
+ plansUrl?: string;
726
+ };
727
+ };
728
+ type RunGetData = {
729
+ body?: never;
730
+ path?: never;
731
+ query: {
732
+ canvasId: string;
733
+ runId: string;
734
+ waitSeconds?: number;
735
+ };
736
+ url: '/v1/run_get';
737
+ };
738
+ type RunGetErrors = {
739
+ /**
740
+ * The input is invalid.
741
+ */
742
+ 400: ApiError;
743
+ /**
744
+ * No valid API key.
745
+ */
746
+ 401: ApiError;
747
+ /**
748
+ * The key or user can't do this.
749
+ */
750
+ 403: ApiError;
751
+ /**
752
+ * The canvas, run, node or upload was not found.
753
+ */
754
+ 404: ApiError;
755
+ /**
756
+ * Too many requests; wait Retry-After seconds.
757
+ */
758
+ 429: ApiError;
759
+ /**
760
+ * Something went wrong on our side.
761
+ */
762
+ 500: ApiError;
763
+ };
764
+ type RunGetResponses = {
765
+ /**
766
+ * Successful response
767
+ */
768
+ 200: {
769
+ runId: string;
770
+ status: 'running' | 'completed' | 'failed' | 'cancelled';
771
+ quotedCredits: number;
772
+ /**
773
+ * ISO 8601.
774
+ */
775
+ startedAt: string;
776
+ /**
777
+ * ISO 8601.
778
+ */
779
+ completedAt?: string;
780
+ nodes: Array<{
781
+ nodeId: string;
782
+ type: string | null;
783
+ status: 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped' | 'cancelled' | 'unknown';
784
+ error?: string;
785
+ /**
786
+ * Links to the node's current results.
787
+ */
788
+ outputs: Array<string>;
789
+ /**
790
+ * The node's text result (a chat reply, or a tool's text or json), cut at 4,000 characters.
791
+ */
792
+ text?: string;
793
+ }>;
794
+ /**
795
+ * Where Fuser's plans are described, when a node failed because the plan doesn't include it.
796
+ */
797
+ plansUrl?: string;
798
+ };
799
+ };
800
+ type RunCancelData = {
801
+ body: {
802
+ canvasId: string;
803
+ runId: string;
804
+ };
805
+ path?: never;
806
+ query?: never;
807
+ url: '/v1/run_cancel';
808
+ };
809
+ type RunCancelErrors = {
810
+ /**
811
+ * The input is invalid.
812
+ */
813
+ 400: ApiError;
814
+ /**
815
+ * No valid API key.
816
+ */
817
+ 401: ApiError;
818
+ /**
819
+ * The key or user can't do this.
820
+ */
821
+ 403: ApiError;
822
+ /**
823
+ * The canvas, run, node or upload was not found.
824
+ */
825
+ 404: ApiError;
826
+ /**
827
+ * Too many requests; wait Retry-After seconds.
828
+ */
829
+ 429: ApiError;
830
+ /**
831
+ * Something went wrong on our side.
832
+ */
833
+ 500: ApiError;
834
+ };
835
+ type RunCancelResponses = {
836
+ /**
837
+ * Successful response
838
+ */
839
+ 200: {
840
+ cancelled: boolean;
841
+ };
842
+ };
843
+ type MediaImportData = {
844
+ body: {
845
+ canvasId: string;
846
+ url: string;
847
+ };
848
+ path?: never;
849
+ query?: never;
850
+ url: '/v1/media_import';
851
+ };
852
+ type MediaImportErrors = {
853
+ /**
854
+ * The input is invalid.
855
+ */
856
+ 400: ApiError;
857
+ /**
858
+ * No valid API key.
859
+ */
860
+ 401: ApiError;
861
+ /**
862
+ * The key or user can't do this.
863
+ */
864
+ 403: ApiError;
865
+ /**
866
+ * The canvas, run, node or upload was not found.
867
+ */
868
+ 404: ApiError;
869
+ /**
870
+ * Too many requests; wait Retry-After seconds.
871
+ */
872
+ 429: ApiError;
873
+ /**
874
+ * Something went wrong on our side.
875
+ */
876
+ 500: ApiError;
877
+ };
878
+ type MediaImportResponses = {
879
+ /**
880
+ * Successful response
881
+ */
882
+ 200: {
883
+ url: string;
884
+ mimeType: string;
885
+ };
886
+ };
887
+ type UploadStartData = {
888
+ body: {
889
+ /**
890
+ * Canvas the files belong to.
891
+ */
892
+ canvasId: string;
893
+ /**
894
+ * Files you can send yourself, up to 50. Leave empty to only get uploadPage for the user.
895
+ */
896
+ files?: Array<{
897
+ /**
898
+ * The file name, with extension.
899
+ */
900
+ fileName: string;
901
+ /**
902
+ * MIME type, e.g. image/jpeg.
903
+ */
904
+ contentType: string;
905
+ /**
906
+ * Size in bytes.
907
+ */
908
+ size: number;
909
+ /**
910
+ * Base64 SHA-256 of the file, e.g. from `openssl dgst -sha256 -binary FILE | base64`.
911
+ */
912
+ sha256: string;
913
+ }>;
914
+ };
915
+ path?: never;
916
+ query?: never;
917
+ url: '/v1/upload_start';
918
+ };
919
+ type UploadStartErrors = {
920
+ /**
921
+ * The input is invalid.
922
+ */
923
+ 400: ApiError;
924
+ /**
925
+ * No valid API key.
926
+ */
927
+ 401: ApiError;
928
+ /**
929
+ * The key or user can't do this.
930
+ */
931
+ 403: ApiError;
932
+ /**
933
+ * The canvas, run, node or upload was not found.
934
+ */
935
+ 404: ApiError;
936
+ /**
937
+ * Too many requests; wait Retry-After seconds.
938
+ */
939
+ 429: ApiError;
940
+ /**
941
+ * Something went wrong on our side.
942
+ */
943
+ 500: ApiError;
944
+ };
945
+ type UploadStartResponses = {
946
+ /**
947
+ * Successful response
948
+ */
949
+ 200: {
950
+ /**
951
+ * Pass to upload_finish.
952
+ */
953
+ uploadId: string;
954
+ /**
955
+ * A page where the user picks the files in their browser. Give it to them only if you cannot send the files yourself.
956
+ */
957
+ uploadPage: string;
958
+ expiresAt: string;
959
+ files: Array<{
960
+ fileName: string;
961
+ status: 'upload';
962
+ method: 'PUT';
963
+ url: string;
964
+ /**
965
+ * Send these headers with the file as the body.
966
+ */
967
+ headers: {
968
+ [key: string]: string;
969
+ };
970
+ } | {
971
+ fileName: string;
972
+ status: 'done';
973
+ asset: {
974
+ url: string;
975
+ mimeType: string;
976
+ };
977
+ }>;
978
+ };
979
+ };
980
+ type UploadFinishData = {
981
+ body: {
982
+ uploadId: string;
983
+ };
984
+ path?: never;
985
+ query?: never;
986
+ url: '/v1/upload_finish';
987
+ };
988
+ type UploadFinishErrors = {
989
+ /**
990
+ * The input is invalid.
991
+ */
992
+ 400: ApiError;
993
+ /**
994
+ * No valid API key.
995
+ */
996
+ 401: ApiError;
997
+ /**
998
+ * The key or user can't do this.
999
+ */
1000
+ 403: ApiError;
1001
+ /**
1002
+ * The canvas, run, node or upload was not found.
1003
+ */
1004
+ 404: ApiError;
1005
+ /**
1006
+ * Too many requests; wait Retry-After seconds.
1007
+ */
1008
+ 429: ApiError;
1009
+ /**
1010
+ * Something went wrong on our side.
1011
+ */
1012
+ 500: ApiError;
1013
+ };
1014
+ type UploadFinishResponses = {
1015
+ /**
1016
+ * Successful response
1017
+ */
1018
+ 200: {
1019
+ /**
1020
+ * Every file sent so far, in the order given to upload_start, with its link or why it failed. Files the user adds on the upload page follow once they finish there.
1021
+ */
1022
+ files: Array<{
1023
+ url: string;
1024
+ mimeType: string;
1025
+ status: 'done';
1026
+ fileName: string;
1027
+ } | {
1028
+ status: 'failed';
1029
+ fileName: string;
1030
+ error: string;
1031
+ }>;
1032
+ };
1033
+ };
1034
+ type MediaViewData = {
1035
+ body: {
1036
+ /**
1037
+ * Fuser media links, from run_get results, canvas_get values or media_import.
1038
+ */
1039
+ urls: Array<string>;
1040
+ /**
1041
+ * high shows images at 1024 px instead of 512, for reading small text (up to 8 at a time).
1042
+ */
1043
+ detail?: 'normal' | 'high';
1044
+ };
1045
+ path?: never;
1046
+ query?: never;
1047
+ url: '/v1/media_view';
1048
+ };
1049
+ type MediaViewErrors = {
1050
+ /**
1051
+ * The input is invalid.
1052
+ */
1053
+ 400: ApiError;
1054
+ /**
1055
+ * No valid API key.
1056
+ */
1057
+ 401: ApiError;
1058
+ /**
1059
+ * The key or user can't do this.
1060
+ */
1061
+ 403: ApiError;
1062
+ /**
1063
+ * The canvas, run, node or upload was not found.
1064
+ */
1065
+ 404: ApiError;
1066
+ /**
1067
+ * Too many requests; wait Retry-After seconds.
1068
+ */
1069
+ 429: ApiError;
1070
+ /**
1071
+ * Something went wrong on our side.
1072
+ */
1073
+ 500: ApiError;
1074
+ };
1075
+ type MediaViewResponses = {
1076
+ /**
1077
+ * Successful response
1078
+ */
1079
+ 200: {
1080
+ items: Array<{
1081
+ url: string;
1082
+ kind: 'image' | 'video' | 'audio' | 'mesh' | 'unknown';
1083
+ facts?: {
1084
+ [key: string]: string | number | boolean;
1085
+ };
1086
+ previews: Array<{
1087
+ mimeType: string;
1088
+ /**
1089
+ * Base64 image bytes.
1090
+ */
1091
+ data: string;
1092
+ atSeconds?: number;
1093
+ }>;
1094
+ note?: string;
1095
+ }>;
1096
+ };
1097
+ };
1098
+ type MediaSearchData = {
1099
+ body: {
1100
+ /**
1101
+ * What you are looking for, in plain words.
1102
+ */
1103
+ query?: string;
1104
+ /**
1105
+ * A mediaId from an earlier result: find ones like it.
1106
+ */
1107
+ similarTo?: string;
1108
+ type?: 'image' | 'video' | 'audio' | 'mesh' | 'all';
1109
+ /**
1110
+ * upload = files you added, generation = made in Fuser.
1111
+ */
1112
+ source?: 'upload' | 'generation' | 'stock' | 'all';
1113
+ /**
1114
+ * Only media on this canvas.
1115
+ */
1116
+ canvasId?: string;
1117
+ /**
1118
+ * Search a workspace's shared library (from account_get) instead of your own.
1119
+ */
1120
+ workspaceId?: string;
1121
+ limit?: number;
1122
+ /**
1123
+ * nextCursor from the previous page, passed back unchanged.
1124
+ */
1125
+ cursor?: string;
1126
+ };
1127
+ path?: never;
1128
+ query?: never;
1129
+ url: '/v1/media_search';
1130
+ };
1131
+ type MediaSearchErrors = {
1132
+ /**
1133
+ * The input is invalid.
1134
+ */
1135
+ 400: ApiError;
1136
+ /**
1137
+ * No valid API key.
1138
+ */
1139
+ 401: ApiError;
1140
+ /**
1141
+ * The key or user can't do this.
1142
+ */
1143
+ 403: ApiError;
1144
+ /**
1145
+ * The canvas, run, node or upload was not found.
1146
+ */
1147
+ 404: ApiError;
1148
+ /**
1149
+ * Too many requests; wait Retry-After seconds.
1150
+ */
1151
+ 429: ApiError;
1152
+ /**
1153
+ * Something went wrong on our side.
1154
+ */
1155
+ 500: ApiError;
1156
+ };
1157
+ type MediaSearchResponses = {
1158
+ /**
1159
+ * Successful response
1160
+ */
1161
+ 200: {
1162
+ assets: Array<{
1163
+ mediaId: string;
1164
+ url: string;
1165
+ type: string | null;
1166
+ title: string | null;
1167
+ description: string | null;
1168
+ createdAt: string | null;
1169
+ canvases: Array<{
1170
+ canvasId: string;
1171
+ title: string;
1172
+ }>;
1173
+ }>;
1174
+ nextCursor: string | null;
1175
+ };
1176
+ };
1177
+ type MediaExportData = {
1178
+ body: {
1179
+ canvasId: string;
1180
+ /**
1181
+ * Only these nodes. Omit for every node on the canvas.
1182
+ */
1183
+ nodeIds?: Array<string>;
1184
+ /**
1185
+ * results: what the canvas generated. all: also the images and videos placed on it (the user's uploads and references).
1186
+ */
1187
+ include?: 'results' | 'all';
1188
+ };
1189
+ path?: never;
1190
+ query?: never;
1191
+ url: '/v1/media_export';
1192
+ };
1193
+ type MediaExportErrors = {
1194
+ /**
1195
+ * The input is invalid.
1196
+ */
1197
+ 400: ApiError;
1198
+ /**
1199
+ * No valid API key.
1200
+ */
1201
+ 401: ApiError;
1202
+ /**
1203
+ * The key or user can't do this.
1204
+ */
1205
+ 403: ApiError;
1206
+ /**
1207
+ * The canvas, run, node or upload was not found.
1208
+ */
1209
+ 404: ApiError;
1210
+ /**
1211
+ * Too many requests; wait Retry-After seconds.
1212
+ */
1213
+ 429: ApiError;
1214
+ /**
1215
+ * Something went wrong on our side.
1216
+ */
1217
+ 500: ApiError;
1218
+ };
1219
+ type MediaExportResponses = {
1220
+ /**
1221
+ * Successful response
1222
+ */
1223
+ 200: {
1224
+ /**
1225
+ * Opens a download of the zip. Give it to the user.
1226
+ */
1227
+ url: string;
1228
+ expiresAt: string;
1229
+ fileCount: number;
1230
+ files: Array<{
1231
+ name: string;
1232
+ nodeId: string;
1233
+ url: string;
1234
+ }>;
1235
+ };
1236
+ };
1237
+ type AccountGetData = {
1238
+ body?: never;
1239
+ path?: never;
1240
+ query?: never;
1241
+ url: '/v1/account_get';
1242
+ };
1243
+ type AccountGetErrors = {
1244
+ /**
1245
+ * The input is invalid.
1246
+ */
1247
+ 400: ApiError;
1248
+ /**
1249
+ * No valid API key.
1250
+ */
1251
+ 401: ApiError;
1252
+ /**
1253
+ * The key or user can't do this.
1254
+ */
1255
+ 403: ApiError;
1256
+ /**
1257
+ * The canvas, run, node or upload was not found.
1258
+ */
1259
+ 404: ApiError;
1260
+ /**
1261
+ * Too many requests; wait Retry-After seconds.
1262
+ */
1263
+ 429: ApiError;
1264
+ /**
1265
+ * Something went wrong on our side.
1266
+ */
1267
+ 500: ApiError;
1268
+ };
1269
+ type AccountGetResponses = {
1270
+ /**
1271
+ * Successful response
1272
+ */
1273
+ 200: {
1274
+ name: string | null;
1275
+ email: string;
1276
+ personalCredits: number;
1277
+ /**
1278
+ * What the plan allows. Check it before a big build, and when something is refused for the plan, tell the user what the plan doesn't include and share plansUrl.
1279
+ */
1280
+ personalPlan: {
1281
+ name: string;
1282
+ trial: boolean;
1283
+ canvases: {
1284
+ used: number | null;
1285
+ /**
1286
+ * Null when unlimited.
1287
+ */
1288
+ limit: number | null;
1289
+ };
1290
+ nodesPerCanvas: number | null;
1291
+ /**
1292
+ * Whether a whole canvas can run at once.
1293
+ */
1294
+ runAll: boolean;
1295
+ /**
1296
+ * Whether tool_build can write tools.
1297
+ */
1298
+ buildTools: boolean;
1299
+ /**
1300
+ * Whether media_search takes query and similarTo.
1301
+ */
1302
+ searchByMeaning: boolean;
1303
+ /**
1304
+ * Whether you manage this plan; in a workspace only owners and admins do.
1305
+ */
1306
+ managesPlan: boolean;
1307
+ /**
1308
+ * Where Fuser's plans are described.
1309
+ */
1310
+ plansUrl: string;
1311
+ };
1312
+ workspaces: Array<{
1313
+ workspaceId: string;
1314
+ name: string;
1315
+ role: 'owner' | 'admin' | 'member';
1316
+ credits: number;
1317
+ /**
1318
+ * False when the workspace has no active plan or is paused.
1319
+ */
1320
+ canSpend: boolean;
1321
+ /**
1322
+ * Your own cap in this workspace, if one is set.
1323
+ */
1324
+ monthlySpendLimit: {
1325
+ limit: number;
1326
+ remaining: number;
1327
+ } | null;
1328
+ /**
1329
+ * What the plan allows. Check it before a big build, and when something is refused for the plan, tell the user what the plan doesn't include and share plansUrl.
1330
+ */
1331
+ plan: {
1332
+ name: string;
1333
+ trial: boolean;
1334
+ canvases: {
1335
+ used: number | null;
1336
+ /**
1337
+ * Null when unlimited.
1338
+ */
1339
+ limit: number | null;
1340
+ };
1341
+ nodesPerCanvas: number | null;
1342
+ /**
1343
+ * Whether a whole canvas can run at once.
1344
+ */
1345
+ runAll: boolean;
1346
+ /**
1347
+ * Whether tool_build can write tools.
1348
+ */
1349
+ buildTools: boolean;
1350
+ /**
1351
+ * Whether media_search takes query and similarTo.
1352
+ */
1353
+ searchByMeaning: boolean;
1354
+ /**
1355
+ * Whether you manage this plan; in a workspace only owners and admins do.
1356
+ */
1357
+ managesPlan: boolean;
1358
+ /**
1359
+ * Where Fuser's plans are described.
1360
+ */
1361
+ plansUrl: string;
1362
+ };
1363
+ }>;
1364
+ };
1365
+ };
1366
+ type ToolSearchData = {
1367
+ body?: never;
1368
+ path?: never;
1369
+ query: {
1370
+ canvasId?: string;
1371
+ /**
1372
+ * A few words, e.g. "join videos" or "halftone".
1373
+ */
1374
+ query: string;
1375
+ limit?: number;
1376
+ };
1377
+ url: '/v1/tool_search';
1378
+ };
1379
+ type ToolSearchErrors = {
1380
+ /**
1381
+ * The input is invalid.
1382
+ */
1383
+ 400: ApiError;
1384
+ /**
1385
+ * No valid API key.
1386
+ */
1387
+ 401: ApiError;
1388
+ /**
1389
+ * The key or user can't do this.
1390
+ */
1391
+ 403: ApiError;
1392
+ /**
1393
+ * The canvas, run, node or upload was not found.
1394
+ */
1395
+ 404: ApiError;
1396
+ /**
1397
+ * Too many requests; wait Retry-After seconds.
1398
+ */
1399
+ 429: ApiError;
1400
+ /**
1401
+ * Something went wrong on our side.
1402
+ */
1403
+ 500: ApiError;
1404
+ };
1405
+ type ToolSearchResponses = {
1406
+ /**
1407
+ * Successful response
1408
+ */
1409
+ 200: {
1410
+ tools: Array<{
1411
+ toolId: string;
1412
+ description: string | null;
1413
+ featured: boolean;
1414
+ tool: {
1415
+ title: string;
1416
+ /**
1417
+ * free tools cost nothing to run; paid ones call AI helpers and cost credits per run.
1418
+ */
1419
+ mode: 'free' | 'paid';
1420
+ inputs: Array<{
1421
+ socket: string;
1422
+ kind: 'image' | 'video' | 'audio' | 'mesh' | 'text';
1423
+ many: boolean;
1424
+ required: boolean;
1425
+ }>;
1426
+ controls: Array<{
1427
+ socket: string;
1428
+ label: string;
1429
+ kind: 'slider';
1430
+ default: number;
1431
+ min: number;
1432
+ max: number;
1433
+ } | {
1434
+ socket: string;
1435
+ label: string;
1436
+ kind: 'dropdown';
1437
+ default: string;
1438
+ options: Array<string>;
1439
+ } | {
1440
+ socket: string;
1441
+ label: string;
1442
+ kind: 'switch';
1443
+ default: boolean;
1444
+ }>;
1445
+ outputs: Array<{
1446
+ socket: string;
1447
+ kind: 'image' | 'video' | 'audio' | 'text' | 'json';
1448
+ }>;
1449
+ };
1450
+ }>;
1451
+ };
1452
+ };
1453
+ type ToolBuildData = {
1454
+ body: {
1455
+ canvasId: string;
1456
+ /**
1457
+ * The Tool node (type UtilityNode).
1458
+ */
1459
+ nodeId: string;
1460
+ /**
1461
+ * What the tool does, in plain words, with its inputs and the controls worth having: "join the videos in order into one clip, with a crossfade length slider". On a built tool, the change to make.
1462
+ */
1463
+ prompt?: string;
1464
+ /**
1465
+ * A saved tool from tool_search to place instead.
1466
+ */
1467
+ toolId?: string;
1468
+ /**
1469
+ * Wait up to this long (at most 45) for the build. Builds usually take 30–90 seconds; call again without prompt to keep waiting.
1470
+ */
1471
+ waitSeconds?: number;
1472
+ };
1473
+ path?: never;
1474
+ query?: never;
1475
+ url: '/v1/tool_build';
1476
+ };
1477
+ type ToolBuildErrors = {
1478
+ /**
1479
+ * The input is invalid.
1480
+ */
1481
+ 400: ApiError;
1482
+ /**
1483
+ * No valid API key.
1484
+ */
1485
+ 401: ApiError;
1486
+ /**
1487
+ * The key or user can't do this.
1488
+ */
1489
+ 403: ApiError;
1490
+ /**
1491
+ * The canvas, run, node or upload was not found.
1492
+ */
1493
+ 404: ApiError;
1494
+ /**
1495
+ * Too many requests; wait Retry-After seconds.
1496
+ */
1497
+ 429: ApiError;
1498
+ /**
1499
+ * Something went wrong on our side.
1500
+ */
1501
+ 500: ApiError;
1502
+ };
1503
+ type ToolBuildResponses = {
1504
+ /**
1505
+ * Successful response
1506
+ */
1507
+ 200: {
1508
+ status: 'building';
1509
+ revision: number;
1510
+ } | {
1511
+ status: 'built';
1512
+ /**
1513
+ * The built tool. Wire inputs and set controls by these socket names.
1514
+ */
1515
+ tool: {
1516
+ title: string;
1517
+ /**
1518
+ * free tools cost nothing to run; paid ones call AI helpers and cost credits per run.
1519
+ */
1520
+ mode: 'free' | 'paid';
1521
+ inputs: Array<{
1522
+ socket: string;
1523
+ kind: 'image' | 'video' | 'audio' | 'mesh' | 'text';
1524
+ many: boolean;
1525
+ required: boolean;
1526
+ }>;
1527
+ controls: Array<{
1528
+ socket: string;
1529
+ label: string;
1530
+ kind: 'slider';
1531
+ default: number;
1532
+ min: number;
1533
+ max: number;
1534
+ } | {
1535
+ socket: string;
1536
+ label: string;
1537
+ kind: 'dropdown';
1538
+ default: string;
1539
+ options: Array<string>;
1540
+ } | {
1541
+ socket: string;
1542
+ label: string;
1543
+ kind: 'switch';
1544
+ default: boolean;
1545
+ }>;
1546
+ outputs: Array<{
1547
+ socket: string;
1548
+ kind: 'image' | 'video' | 'audio' | 'text' | 'json';
1549
+ }>;
1550
+ };
1551
+ revision: number;
1552
+ } | {
1553
+ status: 'failed' | 'refused';
1554
+ error: string;
1555
+ /**
1556
+ * The tool as it was before this build, if any.
1557
+ */
1558
+ tool?: {
1559
+ title: string;
1560
+ /**
1561
+ * free tools cost nothing to run; paid ones call AI helpers and cost credits per run.
1562
+ */
1563
+ mode: 'free' | 'paid';
1564
+ inputs: Array<{
1565
+ socket: string;
1566
+ kind: 'image' | 'video' | 'audio' | 'mesh' | 'text';
1567
+ many: boolean;
1568
+ required: boolean;
1569
+ }>;
1570
+ controls: Array<{
1571
+ socket: string;
1572
+ label: string;
1573
+ kind: 'slider';
1574
+ default: number;
1575
+ min: number;
1576
+ max: number;
1577
+ } | {
1578
+ socket: string;
1579
+ label: string;
1580
+ kind: 'dropdown';
1581
+ default: string;
1582
+ options: Array<string>;
1583
+ } | {
1584
+ socket: string;
1585
+ label: string;
1586
+ kind: 'switch';
1587
+ default: boolean;
1588
+ }>;
1589
+ outputs: Array<{
1590
+ socket: string;
1591
+ kind: 'image' | 'video' | 'audio' | 'text' | 'json';
1592
+ }>;
1593
+ };
1594
+ revision: number;
1595
+ } | {
1596
+ status: 'unbuilt';
1597
+ revision: number;
1598
+ };
1599
+ };
1600
+ //#endregion
1601
+ //#region src/errors.d.ts
1602
+ interface FuserErrorDetails {
1603
+ /** The tool that failed, e.g. `run_start`. */
1604
+ tool: string;
1605
+ status?: number;
1606
+ /** The API's error kind, e.g. `NOT_FOUND`. */
1607
+ code?: string;
1608
+ /** Which conflict a 409 is, e.g. `stale_revision`. */
1609
+ reason?: string;
1610
+ issues?: ApiError['issues'];
1611
+ requestId?: string;
1612
+ retryAfterMs?: number;
1613
+ body?: unknown;
1614
+ cause?: unknown;
1615
+ }
1616
+ /** Every error the SDK throws. Subclasses say what went wrong. */
1617
+ export declare class FuserError extends Error {
1618
+ name: string;
1619
+ readonly tool: string;
1620
+ readonly status: number | undefined;
1621
+ readonly code: string | undefined;
1622
+ readonly reason: string | undefined;
1623
+ readonly issues: ApiError['issues'];
1624
+ readonly requestId: string | undefined;
1625
+ readonly retryAfterMs: number | undefined;
1626
+ readonly body: unknown;
1627
+ constructor(message: string, details: FuserErrorDetails);
1628
+ }
1629
+ export declare class BadRequestError extends FuserError {
1630
+ name: string;
1631
+ }
1632
+ export declare class AuthenticationError extends FuserError {
1633
+ name: string;
1634
+ }
1635
+ export declare class PermissionDeniedError extends FuserError {
1636
+ name: string;
1637
+ }
1638
+ export declare class NotFoundError extends FuserError {
1639
+ name: string;
1640
+ }
1641
+ export declare class ConflictError extends FuserError {
1642
+ name: string;
1643
+ }
1644
+ export declare class RateLimitError extends FuserError {
1645
+ name: string;
1646
+ }
1647
+ export declare class InternalServerError extends FuserError {
1648
+ name: string;
1649
+ }
1650
+ export declare class ConnectionError extends FuserError {
1651
+ name: string;
1652
+ }
1653
+ export declare class TimeoutError extends FuserError {
1654
+ name: string;
1655
+ }
1656
+ /** `run.start(...).wait()` on a run Fuser refused to start. */
1657
+ export declare class RunRefusedError extends FuserError {
1658
+ name: string;
1659
+ }
1660
+ //#endregion
1661
+ //#region src/generated/core/auth.gen.d.ts
1662
+ type AuthToken = string | undefined;
1663
+ interface Auth {
1664
+ /**
1665
+ * Which part of the request do we use to send the auth?
1666
+ *
1667
+ * @default 'header'
1668
+ */
1669
+ in?: 'header' | 'query' | 'cookie';
1670
+ /**
1671
+ * A unique identifier for the security scheme.
1672
+ *
1673
+ * Defined only when there are multiple security schemes whose `Auth`
1674
+ * shape would otherwise be identical.
1675
+ */
1676
+ key?: string;
1677
+ /**
1678
+ * Header or query parameter name.
1679
+ *
1680
+ * @default 'Authorization'
1681
+ */
1682
+ name?: string;
1683
+ scheme?: 'basic' | 'bearer';
1684
+ type: 'apiKey' | 'http';
1685
+ }
1686
+ //#endregion
1687
+ //#region src/generated/core/pathSerializer.gen.d.ts
1688
+ interface SerializerOptions<T> {
1689
+ /**
1690
+ * @default true
1691
+ */
1692
+ explode: boolean;
1693
+ style: T;
1694
+ }
1695
+ type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited';
1696
+ type ObjectStyle = 'form' | 'deepObject';
1697
+ //#endregion
1698
+ //#region src/generated/core/bodySerializer.gen.d.ts
1699
+ type QuerySerializer = (query: Record<string, unknown>) => string;
1700
+ type BodySerializer = (body: unknown) => unknown;
1701
+ type QuerySerializerOptionsObject = {
1702
+ allowReserved?: boolean;
1703
+ array?: Partial<SerializerOptions<ArrayStyle>>;
1704
+ object?: Partial<SerializerOptions<ObjectStyle>>;
1705
+ };
1706
+ type QuerySerializerOptions = QuerySerializerOptionsObject & {
1707
+ /**
1708
+ * Per-parameter serialization overrides. When provided, these settings
1709
+ * override the global array/object settings for specific parameter names.
1710
+ */
1711
+ parameters?: Record<string, QuerySerializerOptionsObject>;
1712
+ };
1713
+ //#endregion
1714
+ //#region src/generated/core/types.gen.d.ts
1715
+ type HttpMethod = 'connect' | 'delete' | 'get' | 'head' | 'options' | 'patch' | 'post' | 'put' | 'trace';
1716
+ type Client$1<RequestFn = never, Config = unknown, MethodFn = never, BuildUrlFn = never, SseFn = never> = {
1717
+ /**
1718
+ * Returns the final request URL.
1719
+ */
1720
+ buildUrl: BuildUrlFn;
1721
+ getConfig: () => Config;
1722
+ request: RequestFn;
1723
+ setConfig: (config: Config) => Config;
1724
+ } & { [K in HttpMethod]: MethodFn; } & ([SseFn] extends [never] ? {
1725
+ sse?: never;
1726
+ } : {
1727
+ sse: { [K in HttpMethod]: SseFn; };
1728
+ });
1729
+ interface Config$1 {
1730
+ /**
1731
+ * Auth token or a function returning auth token. The resolved value will be
1732
+ * added to the request payload as defined by its `security` array.
1733
+ */
1734
+ auth?: ((auth: Auth) => Promise<AuthToken> | AuthToken) | AuthToken;
1735
+ /**
1736
+ * A function for serializing request body parameter. By default,
1737
+ * {@link JSON.stringify()} will be used.
1738
+ */
1739
+ bodySerializer?: BodySerializer | null;
1740
+ /**
1741
+ * An object containing any HTTP headers that you want to pre-populate your
1742
+ * `Headers` object with.
1743
+ *
1744
+ * {@link https://developer.mozilla.org/docs/Web/API/Headers/Headers#init See more}
1745
+ */
1746
+ headers?: RequestInit['headers'] | Record<string, string | number | boolean | (string | number | boolean)[] | null | undefined | unknown>;
1747
+ /**
1748
+ * The request method.
1749
+ *
1750
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#method See more}
1751
+ */
1752
+ method?: Uppercase<HttpMethod>;
1753
+ /**
1754
+ * A function for serializing request query parameters. By default, arrays
1755
+ * will be exploded in form style, objects will be exploded in deepObject
1756
+ * style, and reserved characters are percent-encoded.
1757
+ *
1758
+ * This method will have no effect if the native `paramsSerializer()` Axios
1759
+ * API function is used.
1760
+ *
1761
+ * {@link https://swagger.io/docs/specification/serialization/#query View examples}
1762
+ */
1763
+ querySerializer?: QuerySerializer | QuerySerializerOptions;
1764
+ /**
1765
+ * A function validating request data. This is useful if you want to ensure
1766
+ * the request conforms to the desired shape, so it can be safely sent to
1767
+ * the server.
1768
+ */
1769
+ requestValidator?: (data: unknown) => Promise<unknown>;
1770
+ /**
1771
+ * A function transforming response data before it's returned. This is useful
1772
+ * for post-processing data, e.g., converting ISO strings into Date objects.
1773
+ */
1774
+ responseTransformer?: (data: unknown) => Promise<unknown>;
1775
+ /**
1776
+ * A function validating response data. This is useful if you want to ensure
1777
+ * the response conforms to the desired shape, so it can be safely passed to
1778
+ * the transformers and returned to the user.
1779
+ */
1780
+ responseValidator?: (data: unknown) => Promise<unknown>;
1781
+ }
1782
+ /**
1783
+ * Arbitrary metadata passed through the `meta` request option.
1784
+ */
1785
+ interface ClientMeta {}
1786
+ //#endregion
1787
+ //#region src/generated/core/serverSentEvents.gen.d.ts
1788
+ type ServerSentEventsOptions<TData = unknown> = Omit<RequestInit, 'method'> & Pick<Config$1, 'method' | 'responseTransformer' | 'responseValidator'> & {
1789
+ /**
1790
+ * Fetch API implementation. You can use this option to provide a custom
1791
+ * fetch instance.
1792
+ *
1793
+ * @default globalThis.fetch
1794
+ */
1795
+ fetch?: typeof fetch;
1796
+ /**
1797
+ * Implementing clients can call request interceptors inside this hook.
1798
+ */
1799
+ onRequest?: (url: string, init: RequestInit) => Promise<Request>;
1800
+ /**
1801
+ * Callback invoked when a network or parsing error occurs during streaming.
1802
+ *
1803
+ * This option applies only if the endpoint returns a stream of events.
1804
+ *
1805
+ * @param error The error that occurred.
1806
+ */
1807
+ onSseError?: (error: unknown) => void;
1808
+ /**
1809
+ * Callback invoked when an event is streamed from the server.
1810
+ *
1811
+ * This option applies only if the endpoint returns a stream of events.
1812
+ *
1813
+ * @param event Event streamed from the server.
1814
+ * @returns Nothing (void).
1815
+ */
1816
+ onSseEvent?: (event: StreamEvent<TData>) => void;
1817
+ serializedBody?: RequestInit['body'];
1818
+ /**
1819
+ * Default retry delay in milliseconds.
1820
+ *
1821
+ * This option applies only if the endpoint returns a stream of events.
1822
+ *
1823
+ * @default 3000
1824
+ */
1825
+ sseDefaultRetryDelay?: number;
1826
+ /**
1827
+ * Maximum number of retry attempts before giving up.
1828
+ */
1829
+ sseMaxRetryAttempts?: number;
1830
+ /**
1831
+ * Maximum retry delay in milliseconds.
1832
+ *
1833
+ * Applies only when exponential backoff is used.
1834
+ *
1835
+ * This option applies only if the endpoint returns a stream of events.
1836
+ *
1837
+ * @default 30000
1838
+ */
1839
+ sseMaxRetryDelay?: number;
1840
+ /**
1841
+ * Optional sleep function for retry backoff.
1842
+ *
1843
+ * Defaults to using `setTimeout`.
1844
+ */
1845
+ sseSleepFn?: (ms: number) => Promise<void>;
1846
+ url: string;
1847
+ };
1848
+ interface StreamEvent<TData = unknown> {
1849
+ data: TData;
1850
+ event?: string;
1851
+ id?: string;
1852
+ retry?: number;
1853
+ }
1854
+ type ServerSentEventsResult<TData = unknown, TReturn = void, TNext = unknown> = {
1855
+ stream: AsyncGenerator<TData extends Record<string, unknown> ? TData[keyof TData] : TData, TReturn, TNext>;
1856
+ };
1857
+ //#endregion
1858
+ //#region src/generated/client/utils.gen.d.ts
1859
+ type ErrInterceptor<Err, Res, Req, Options> = (error: Err,
1860
+ /** response may be undefined due to a network error where no response object is produced */
1861
+ response: Res | undefined,
1862
+ /** request may be undefined, because error may be from building the request object itself */
1863
+ request: Req | undefined, options: Options) => Err | Promise<Err>;
1864
+ type ReqInterceptor<Req, Options> = (request: Req, options: Options) => Req | Promise<Req>;
1865
+ type ResInterceptor<Res, Req, Options> = (response: Res, request: Req, options: Options) => Res | Promise<Res>;
1866
+ declare class Interceptors<Interceptor> {
1867
+ fns: Array<Interceptor | null>;
1868
+ clear(): void;
1869
+ eject(id: number | Interceptor): void;
1870
+ exists(id: number | Interceptor): boolean;
1871
+ getInterceptorIndex(id: number | Interceptor): number;
1872
+ update(id: number | Interceptor, fn: Interceptor): number | Interceptor | false;
1873
+ use(fn: Interceptor): number;
1874
+ }
1875
+ interface Middleware<Req, Res, Err, Options> {
1876
+ error: Interceptors<ErrInterceptor<Err, Res, Req, Options>>;
1877
+ request: Interceptors<ReqInterceptor<Req, Options>>;
1878
+ response: Interceptors<ResInterceptor<Res, Req, Options>>;
1879
+ }
1880
+ //#endregion
1881
+ //#region src/generated/client/types.gen.d.ts
1882
+ type ResponseStyle = 'data' | 'fields';
1883
+ interface Config<T extends ClientOptions = ClientOptions> extends Omit<RequestInit, 'body' | 'headers' | 'method'>, Config$1 {
1884
+ /**
1885
+ * Base URL for all requests made by this client.
1886
+ */
1887
+ baseUrl?: T['baseUrl'];
1888
+ /**
1889
+ * Fetch API implementation. You can use this option to provide a custom
1890
+ * fetch instance.
1891
+ *
1892
+ * @default globalThis.fetch
1893
+ */
1894
+ fetch?: typeof fetch;
1895
+ /**
1896
+ * Please don't use the Fetch client for Next.js applications. The `next`
1897
+ * options won't have any effect.
1898
+ *
1899
+ * Install {@link https://www.npmjs.com/package/@hey-api/client-next `@hey-api/client-next`} instead.
1900
+ */
1901
+ next?: never;
1902
+ /**
1903
+ * Return the response data parsed in a specified format. By default, `auto`
1904
+ * will infer the appropriate method from the `Content-Type` response header.
1905
+ * You can override this behavior with any of the {@link Body} methods.
1906
+ * Select `stream` if you don't want to parse response data at all.
1907
+ *
1908
+ * @default 'auto'
1909
+ */
1910
+ parseAs?: 'arrayBuffer' | 'auto' | 'blob' | 'formData' | 'json' | 'stream' | 'text';
1911
+ /**
1912
+ * Should we return only data or multiple fields (data, error, response, etc.)?
1913
+ *
1914
+ * @default 'fields'
1915
+ */
1916
+ responseStyle?: ResponseStyle;
1917
+ /**
1918
+ * Throw an error instead of returning it in the response?
1919
+ *
1920
+ * @default false
1921
+ */
1922
+ throwOnError?: T['throwOnError'];
1923
+ }
1924
+ interface RequestOptions$1<TData = unknown, TResponseStyle extends ResponseStyle = 'fields', ThrowOnError extends boolean = boolean, Url extends string = string> extends Config<{
1925
+ responseStyle: TResponseStyle;
1926
+ throwOnError: ThrowOnError;
1927
+ }>, Pick<ServerSentEventsOptions<TData>, 'onRequest' | 'onSseError' | 'onSseEvent' | 'sseDefaultRetryDelay' | 'sseMaxRetryAttempts' | 'sseMaxRetryDelay'> {
1928
+ /**
1929
+ * Any body that you want to add to your request.
1930
+ *
1931
+ * {@link https://developer.mozilla.org/docs/Web/API/fetch#body}
1932
+ */
1933
+ body?: unknown;
1934
+ path?: Record<string, unknown>;
1935
+ query?: Record<string, unknown>;
1936
+ /**
1937
+ * Security mechanism(s) to use for the request.
1938
+ */
1939
+ security?: ReadonlyArray<Auth>;
1940
+ url: Url;
1941
+ }
1942
+ interface ResolvedRequestOptions<TResponseStyle extends ResponseStyle = 'fields', ThrowOnError extends boolean = boolean, Url extends string = string> extends RequestOptions$1<unknown, TResponseStyle, ThrowOnError, Url> {
1943
+ headers: Headers;
1944
+ serializedBody?: string;
1945
+ }
1946
+ type RequestResult<TData = unknown, TError = unknown, ThrowOnError extends boolean = boolean, TResponseStyle extends ResponseStyle = 'fields'> = ThrowOnError extends true ? Promise<TResponseStyle extends 'data' ? TData extends Record<string, unknown> ? TData[keyof TData] : TData : {
1947
+ data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
1948
+ request: Request;
1949
+ response: Response;
1950
+ }> : Promise<TResponseStyle extends 'data' ? (TData extends Record<string, unknown> ? TData[keyof TData] : TData) | undefined : ({
1951
+ data: TData extends Record<string, unknown> ? TData[keyof TData] : TData;
1952
+ error: undefined;
1953
+ } | {
1954
+ data: undefined;
1955
+ error: TError extends Record<string, unknown> ? TError[keyof TError] : TError;
1956
+ }) & {
1957
+ /** request may be undefined, because error may be from building the request object itself */
1958
+ request?: Request;
1959
+ /** response may be undefined, because error may be from building the request object itself or from a network error */
1960
+ response?: Response;
1961
+ }>;
1962
+ interface ClientOptions {
1963
+ baseUrl?: string;
1964
+ responseStyle?: ResponseStyle;
1965
+ throwOnError?: boolean;
1966
+ }
1967
+ type MethodFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions$1<TData, TResponseStyle, ThrowOnError>, 'method'>) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
1968
+ type SseFn = <TData = unknown, _TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions$1<never, TResponseStyle, ThrowOnError>, 'method'>) => Promise<ServerSentEventsResult<TData>>;
1969
+ type RequestFn = <TData = unknown, TError = unknown, ThrowOnError extends boolean = false, TResponseStyle extends ResponseStyle = 'fields'>(options: Omit<RequestOptions$1<TData, TResponseStyle, ThrowOnError>, 'method'> & Pick<Required<RequestOptions$1<TData, TResponseStyle, ThrowOnError>>, 'method'>) => RequestResult<TData, TError, ThrowOnError, TResponseStyle>;
1970
+ type BuildUrlFn = <TData extends {
1971
+ body?: unknown;
1972
+ path?: Record<string, unknown>;
1973
+ query?: Record<string, unknown>;
1974
+ url: string;
1975
+ }>(options: TData & Options$1<TData>) => string;
1976
+ type Client = Client$1<RequestFn, Config, MethodFn, BuildUrlFn, SseFn> & {
1977
+ interceptors: Middleware<Request, Response, unknown, ResolvedRequestOptions>;
1978
+ };
1979
+ interface TDataShape {
1980
+ body?: unknown;
1981
+ headers?: unknown;
1982
+ path?: unknown;
1983
+ query?: unknown;
1984
+ url: string;
1985
+ }
1986
+ type OmitKeys<T, K> = Pick<T, Exclude<keyof T, K>>;
1987
+ type Options$1<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown, TResponseStyle extends ResponseStyle = 'fields'> = OmitKeys<RequestOptions$1<TResponse, TResponseStyle, ThrowOnError>, 'body' | 'path' | 'query' | 'url'> & ([TData] extends [never] ? unknown : Omit<TData, 'url'>);
1988
+ declare namespace sdk_gen_d_exports {
1989
+ export { Options, accountGet, canvasArrange, canvasEdit, canvasGet, canvasList, catalogSearch, mediaExport, mediaImport, mediaSearch, mediaView, runCancel, runGet, runStart, toolBuild, toolSearch, uploadFinish, uploadStart };
1990
+ }
1991
+ type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean, TResponse = unknown> = Options$1<TData, ThrowOnError, TResponse> & {
1992
+ /**
1993
+ * You can provide a client instance returned by `createClient()` instead of
1994
+ * individual options. This might be also useful if you want to implement a
1995
+ * custom client.
1996
+ */
1997
+ client?: Client;
1998
+ /**
1999
+ * You can pass arbitrary values through the `meta` object. This can be
2000
+ * used to access values that aren't defined as part of the SDK function.
2001
+ */
2002
+ meta?: keyof ClientMeta extends never ? Record<string, unknown> : ClientMeta;
2003
+ };
2004
+ /**
2005
+ * List canvases
2006
+ *
2007
+ * Canvases you can open, most recently edited first, with a link to each. Reuse one only when the user points to it; put new work on a new canvas, and never present results that were already there as new.
2008
+ */
2009
+ declare const canvasList: <ThrowOnError extends boolean = false>(options?: Options<CanvasListData, ThrowOnError>) => RequestResult<CanvasListResponses, CanvasListErrors, ThrowOnError>;
2010
+ /**
2011
+ * Read a canvas
2012
+ *
2013
+ * A compact view of a canvas: a summary, then pages of nodes (id, type, label, socket keys, literal values, result links) and their edges. On a big canvas, find nodes with search or read specific ones with nodeIds instead of paging through everything.
2014
+ */
2015
+ declare const canvasGet: <ThrowOnError extends boolean = false>(options: Options<CanvasGetData, ThrowOnError>) => RequestResult<CanvasGetResponses, CanvasGetErrors, ThrowOnError>;
2016
+ /**
2017
+ * Edit a canvas
2018
+ *
2019
+ * Apply a graph diff to a canvas all at once: add nodes and edges, change inputs, disconnect edges, delete nodes. Every change lands or none does. Keep each edit to about 30 new nodes; build a bigger canvas one section per edit, so a mistake costs one small resend.
2020
+ */
2021
+ declare const canvasEdit: <ThrowOnError extends boolean = false>(options: Options<CanvasEditData, ThrowOnError>) => RequestResult<CanvasEditResponses, CanvasEditErrors, ThrowOnError>;
2022
+ /**
2023
+ * Arrange nodes on a canvas
2024
+ *
2025
+ * Lay out existing nodes with Fuser's layout instead of working out positions. Without layout it tidies them along their wiring, inputs to the left of what they feed; with layout it puts them in a row, column or grid in nodeIds order. Without an origin the block stays where the nodes are and slides clear of the nodes around it. Use it when the user asks to rearrange, line up or tidy nodes, or after resizing nodes that now overlap. It changes positions only.
2026
+ */
2027
+ declare const canvasArrange: <ThrowOnError extends boolean = false>(options: Options<CanvasArrangeData, ThrowOnError>) => RequestResult<CanvasArrangeResponses, CanvasArrangeErrors, ThrowOnError>;
2028
+ /**
2029
+ * Find node types
2030
+ *
2031
+ * Node types a canvas_edit diff may use, with what each is good at, its input ids and its output socket. Call it with no query first: it returns the recommended node for each common job. Search only when none of them fits.
2032
+ */
2033
+ declare const catalogSearch: <ThrowOnError extends boolean = false>(options?: Options<CatalogSearchData, ThrowOnError>) => RequestResult<CatalogSearchResponses, CatalogSearchErrors, ThrowOnError>;
2034
+ /**
2035
+ * Run a canvas
2036
+ *
2037
+ * Run the whole canvas or named nodes. Prices the run first and refuses it when it costs more than maxCredits; dryRun returns only the price. Starts a run once per idempotencyKey; check on it with run_get, not by calling run_start again.
2038
+ */
2039
+ declare const runStart: <ThrowOnError extends boolean = false>(options: Options<RunStartData, ThrowOnError>) => RequestResult<RunStartResponses, RunStartErrors, ThrowOnError>;
2040
+ /**
2041
+ * Check a run
2042
+ *
2043
+ * Status of a run you started, per node, with links to each node's results.
2044
+ */
2045
+ declare const runGet: <ThrowOnError extends boolean = false>(options: Options<RunGetData, ThrowOnError>) => RequestResult<RunGetResponses, RunGetErrors, ThrowOnError>;
2046
+ /**
2047
+ * Cancel a run
2048
+ *
2049
+ * Stop a run you started. Nodes already finished keep their results.
2050
+ */
2051
+ declare const runCancel: <ThrowOnError extends boolean = false>(options: Options<RunCancelData, ThrowOnError>) => RequestResult<RunCancelResponses, RunCancelErrors, ThrowOnError>;
2052
+ /**
2053
+ * Import an image or video
2054
+ *
2055
+ * Copy an image or video from a public URL into the canvas's assets and get a Fuser link for it. Use it before putting a web link on the canvas: it says straight away when the link can't be fetched, and the copy won't expire. For a file on the user's machine use upload_start.
2056
+ */
2057
+ declare const mediaImport: <ThrowOnError extends boolean = false>(options: Options<MediaImportData, ThrowOnError>) => RequestResult<MediaImportResponses, MediaImportErrors, ThrowOnError>;
2058
+ /**
2059
+ * Upload files
2060
+ *
2061
+ * Step 1 of putting files from the user's machine on a canvas, for agents that run commands on that machine (Claude Code, Codex, an IDE). List the files (up to 50): each comes back with a link to PUT it to, or done if Fuser already has it. Then call upload_finish with uploadId. In a chat app use upload_box instead; a cloud code sandbox can't reach these links.
2062
+ */
2063
+ declare const uploadStart: <ThrowOnError extends boolean = false>(options: Options<UploadStartData, ThrowOnError>) => RequestResult<UploadStartResponses, UploadStartErrors, ThrowOnError>;
2064
+ /**
2065
+ * Finish uploading files
2066
+ *
2067
+ * Step 2: returns a link for every file that arrived, to use as an ImageNode or VideoNode input, and says why for any that did not. For files the user is adding on the upload page, call it after they say they are done.
2068
+ */
2069
+ declare const uploadFinish: <ThrowOnError extends boolean = false>(options: Options<UploadFinishData, ThrowOnError>) => RequestResult<UploadFinishResponses, UploadFinishErrors, ThrowOnError>;
2070
+ /**
2071
+ * Look at media
2072
+ *
2073
+ * See Fuser images and 3D models as small previews, and the first frame of a video, with facts such as size, length and transparency. Look at results before describing or judging them.
2074
+ */
2075
+ declare const mediaView: <ThrowOnError extends boolean = false>(options: Options<MediaViewData, ThrowOnError>) => RequestResult<MediaViewResponses, MediaViewErrors, ThrowOnError>;
2076
+ /**
2077
+ * Find your media
2078
+ *
2079
+ * Search the images, videos, audio and 3D files you made or uploaded, by meaning ("the coral reef image", "a dog running on a beach") or by similarity to one you have. Without query or similarTo it lists the newest first. Look at matches with media_view.
2080
+ */
2081
+ declare const mediaSearch: <ThrowOnError extends boolean = false>(options: Options<MediaSearchData, ThrowOnError>) => RequestResult<MediaSearchResponses, MediaSearchErrors, ThrowOnError>;
2082
+ /**
2083
+ * Download media as a zip
2084
+ *
2085
+ * A link that downloads a canvas's results as one zip file, for when the user wants their files ('download everything', 'send me the images as a zip'). Give the user the link; it works for an hour. It changes nothing on the canvas.
2086
+ */
2087
+ declare const mediaExport: <ThrowOnError extends boolean = false>(options: Options<MediaExportData, ThrowOnError>) => RequestResult<MediaExportResponses, MediaExportErrors, ThrowOnError>;
2088
+ /**
2089
+ * Read your account
2090
+ *
2091
+ * Who you are, your personal credits and plan, and each workspace you belong to with your role, its plan, the team's credits and your monthly spend limit there. Runs on a workspace canvas spend that workspace's credits if you belong to it; runs on a personal canvas, or a workspace canvas shared with you from outside, spend yours.
2092
+ */
2093
+ declare const accountGet: <ThrowOnError extends boolean = false>(options?: Options<AccountGetData, ThrowOnError>) => RequestResult<AccountGetResponses, AccountGetErrors, ThrowOnError>;
2094
+ /**
2095
+ * Find a saved tool
2096
+ *
2097
+ * Search the canvas's tool library (tools you or your workspace built) and Fuser's featured tools by title and description. Place a match with tool_build toolId. Only worth it when a tool for the job likely exists; building a new one with tool_build prompt is fine too.
2098
+ */
2099
+ declare const toolSearch: <ThrowOnError extends boolean = false>(options: Options<ToolSearchData, ThrowOnError>) => RequestResult<ToolSearchResponses, ToolSearchErrors, ThrowOnError>;
2100
+ /**
2101
+ * Build a tool
2102
+ *
2103
+ * Turn a Tool node (type UtilityNode, added with canvas_edit) into a working tool: describe it in prompt and Fuser writes its code, or place a saved one with toolId. Tools do what generators can't: join, cut, trim or speed up videos, mix audio, crop, grid, filter, measure and convert between images, video, audio, 3D models, text and JSON (not PDF, ZIP or other files). Call it again with a prompt to change a built tool, or with neither to check on a build. Once built, wire its input sockets and set its controls with canvas_edit, then run it like any node; free tools cost nothing to run.
2104
+ */
2105
+ declare const toolBuild: <ThrowOnError extends boolean = false>(options: Options<ToolBuildData, ThrowOnError>) => RequestResult<ToolBuildResponses, ToolBuildErrors, ThrowOnError>;
2106
+ //#endregion
2107
+ //#region src/pages.d.ts
2108
+ interface Page {
2109
+ nextCursor: string | null;
2110
+ }
2111
+ /**
2112
+ * A paged list: await it for the first page, or `for await` it for every
2113
+ * item on every page.
2114
+ */
2115
+ export declare class PagePromise<P extends Page, I> implements PromiseLike<P>, AsyncIterable<I> {
2116
+ #private;
2117
+ constructor(load: (cursor?: string) => Promise<P>, items: (page: P) => readonly I[]);
2118
+ then<A = P, B = never>(onfulfilled?: ((value: P) => A | PromiseLike<A>) | null, onrejected?: ((reason: unknown) => B | PromiseLike<B>) | null): Promise<A | B>;
2119
+ pages(): AsyncGenerator<P>;
2120
+ [Symbol.asyncIterator](): AsyncGenerator<I>;
2121
+ /** Every item on every page. */
2122
+ all(): Promise<I[]>;
2123
+ }
2124
+ //#endregion
2125
+ //#region src/fuser.d.ts
2126
+ type Sdk = typeof sdk_gen_d_exports;
2127
+ /** A generated operation, e.g. `canvasEdit`. */
2128
+ type OperationKey = keyof Sdk;
2129
+ type Snake<S extends string> = S extends `${infer Head}${infer Rest}` ? `${Head extends Lowercase<Head> ? Head : `_${Lowercase<Head>}`}${Snake<Rest>}` : S;
2130
+ /** An MCP tool and REST path name, e.g. `canvas_edit`. */
2131
+ type ToolName = Snake<OperationKey>;
2132
+ type KeyOf<N extends ToolName> = { [K in OperationKey]: Snake<K> extends N ? K : never; }[OperationKey];
2133
+ type OptionsOf<K extends OperationKey> = NonNullable<Parameters<Sdk[K]>[0]>;
2134
+ type Field<K extends OperationKey, F extends 'body' | 'query'> = OptionsOf<K> extends { [P in F]?: infer V; } ? NonNullable<V> : never;
2135
+ type InOf<K extends OperationKey> = [Field<K, 'body'>] extends [never] ? 'query' : 'body';
2136
+ type ArgsOf<K extends OperationKey> = [Field<K, InOf<K>>] extends [never] ? void : Field<K, InOf<K>>;
2137
+ type ResultOf<K extends OperationKey> = Extract<Awaited<ReturnType<Sdk[K]>>, {
2138
+ error: undefined;
2139
+ }>['data'];
2140
+ /** Exactly the arguments an agent passes to the MCP tool. */
2141
+ type ToolArgs<N extends ToolName> = ArgsOf<KeyOf<N>>;
2142
+ /** Exactly the JSON the MCP tool returns. */
2143
+ type ToolResult<N extends ToolName> = ResultOf<KeyOf<N>>;
2144
+ type Resource = ToolName extends (infer N) ? N extends `${infer R}_${string}` ? R : never : never;
2145
+ /**
2146
+ * One namespace per resource and one method per tool: `canvas_list` is
2147
+ * `fuser.canvas.list()`. A new or renamed tool fails the build until the
2148
+ * class covers it.
2149
+ */
2150
+ type Surface = { [R in Resource]: { [N in ToolName as N extends `${R}_${infer M}` ? M : never]: (args: ToolArgs<N>, options?: RequestOptions) => PromiseLike<ToolResult<N>>; }; };
2151
+ interface RequestOptions {
2152
+ signal?: AbortSignal;
2153
+ /** Per attempt, on top of any `waitSeconds`. */
2154
+ timeoutMs?: number;
2155
+ maxRetries?: number;
2156
+ headers?: Record<string, string>;
2157
+ }
2158
+ interface WaitOptions {
2159
+ /** Give up after this long. Defaults to 30 minutes for runs, 10 for builds. */
2160
+ timeoutMs?: number;
2161
+ signal?: AbortSignal;
2162
+ }
2163
+ interface FuserOptions {
2164
+ /** Defaults to the `FUSER_API_KEY` environment variable. */
2165
+ apiKey?: string;
2166
+ /** Defaults to `https://api.fuser.studio`. */
2167
+ baseUrl?: string;
2168
+ fetch?: typeof fetch;
2169
+ /** Per attempt. Defaults to 60 seconds. */
2170
+ timeoutMs?: number;
2171
+ /** Defaults to 2. */
2172
+ maxRetries?: number;
2173
+ beforeSend?: (request: Request) => Request | void | Promise<Request | void>;
2174
+ afterSend?: (response: Response, request: Request) => void | Promise<void>;
2175
+ /** An API key acts as you; only set this if the page is yours alone. */
2176
+ dangerouslyAllowBrowser?: boolean;
2177
+ }
2178
+ type RunStartResult = ToolResult<'run_start'>;
2179
+ type RunSummary = ToolResult<'run_get'>;
2180
+ type ToolBuildResult = ToolResult<'tool_build'>;
2181
+ declare abstract class StartedCall<T> implements PromiseLike<T> {
2182
+ protected readonly started: Promise<T>;
2183
+ constructor(started: Promise<T>);
2184
+ then<A = T, B = never>(onfulfilled?: ((value: T) => A | PromiseLike<A>) | null, onrejected?: ((reason: unknown) => B | PromiseLike<B>) | null): Promise<A | B>;
2185
+ }
2186
+ /** `run.start()`: await for the start result, or `.wait()` for the finished run. */
2187
+ export declare class RunCall extends StartedCall<RunStartResult> {
2188
+ #private;
2189
+ constructor(started: Promise<RunStartResult>, wait: (runId: string, options?: WaitOptions) => Promise<RunSummary>);
2190
+ /** The run once it stops running. Throws if it was refused or only priced. */
2191
+ wait(options?: WaitOptions): Promise<RunSummary>;
2192
+ }
2193
+ /** `tool.build()`: await for its state now, or `.wait()` until it's built. */
2194
+ export declare class ToolBuildCall extends StartedCall<ToolBuildResult> {
2195
+ #private;
2196
+ constructor(started: Promise<ToolBuildResult>, check: (signal?: AbortSignal) => Promise<ToolBuildResult>);
2197
+ /** The tool once its build stops; check `status` for built or failed. */
2198
+ wait(options?: WaitOptions): Promise<ToolBuildResult>;
2199
+ }
2200
+ interface UploadInput {
2201
+ fileName: string;
2202
+ data: Blob | ArrayBuffer | Uint8Array;
2203
+ /** Required unless `data` is a Blob with a type. */
2204
+ contentType?: string;
2205
+ }
2206
+ /**
2207
+ * The Fuser API. Each tool is a method named after it: `canvas_edit` is
2208
+ * `fuser.canvas.edit()`, with the same arguments and result as the MCP tool.
2209
+ */
2210
+ export declare class Fuser implements Surface {
2211
+ #private;
2212
+ readonly client: Client;
2213
+ readonly account: {
2214
+ get: (_args?: void | undefined, options?: RequestOptions) => Promise<{
2215
+ name: string | null;
2216
+ email: string;
2217
+ personalCredits: number;
2218
+ personalPlan: {
2219
+ name: string;
2220
+ trial: boolean;
2221
+ canvases: {
2222
+ used: number | null;
2223
+ limit: number | null;
2224
+ };
2225
+ nodesPerCanvas: number | null;
2226
+ runAll: boolean;
2227
+ buildTools: boolean;
2228
+ searchByMeaning: boolean;
2229
+ managesPlan: boolean;
2230
+ plansUrl: string;
2231
+ };
2232
+ workspaces: Array<{
2233
+ workspaceId: string;
2234
+ name: string;
2235
+ role: "owner" | "admin" | "member";
2236
+ credits: number;
2237
+ canSpend: boolean;
2238
+ monthlySpendLimit: {
2239
+ limit: number;
2240
+ remaining: number;
2241
+ } | null;
2242
+ plan: {
2243
+ name: string;
2244
+ trial: boolean;
2245
+ canvases: {
2246
+ used: number | null;
2247
+ limit: number | null;
2248
+ };
2249
+ nodesPerCanvas: number | null;
2250
+ runAll: boolean;
2251
+ buildTools: boolean;
2252
+ searchByMeaning: boolean;
2253
+ managesPlan: boolean;
2254
+ plansUrl: string;
2255
+ };
2256
+ }>;
2257
+ }>;
2258
+ };
2259
+ readonly canvas: {
2260
+ /** Await for a page, or `for await` for every canvas. */
2261
+ list: (args?: ToolArgs<"canvas_list">, options?: RequestOptions) => PagePromise<{
2262
+ canvases: Array<{
2263
+ canvasId: string;
2264
+ title: string;
2265
+ workspaceId: string | null;
2266
+ updatedAt: string | null;
2267
+ url: string;
2268
+ }>;
2269
+ nextCursor: string | null;
2270
+ } & {
2271
+ nextCursor: string | null;
2272
+ }, {
2273
+ canvasId: string;
2274
+ title: string;
2275
+ workspaceId: string | null;
2276
+ updatedAt: string | null;
2277
+ url: string;
2278
+ }>;
2279
+ /** Await for a page, or `for await` for every node. */
2280
+ get: (args: ToolArgs<"canvas_get">, options?: RequestOptions) => PagePromise<{
2281
+ canvasId: string;
2282
+ title: string;
2283
+ url: string;
2284
+ revision: number;
2285
+ summary: {
2286
+ nodeCount: number;
2287
+ edgeCount: number;
2288
+ nodesByType: {
2289
+ [key: string]: number;
2290
+ };
2291
+ bounds: {
2292
+ x: number;
2293
+ y: number;
2294
+ width: number;
2295
+ height: number;
2296
+ } | null;
2297
+ };
2298
+ nodes: Array<{
2299
+ id: string;
2300
+ type?: string;
2301
+ label?: string;
2302
+ x?: number;
2303
+ y?: number;
2304
+ width?: number;
2305
+ height?: number;
2306
+ group?: string;
2307
+ in: Array<string>;
2308
+ out: Array<string>;
2309
+ values?: {
2310
+ [key: string]: string;
2311
+ };
2312
+ results?: Array<string>;
2313
+ }>;
2314
+ edges: Array<{
2315
+ from: string;
2316
+ to: string;
2317
+ }>;
2318
+ nextCursor: string | null;
2319
+ } & {
2320
+ nextCursor: string | null;
2321
+ }, {
2322
+ id: string;
2323
+ type?: string;
2324
+ label?: string;
2325
+ x?: number;
2326
+ y?: number;
2327
+ width?: number;
2328
+ height?: number;
2329
+ group?: string;
2330
+ in: Array<string>;
2331
+ out: Array<string>;
2332
+ values?: {
2333
+ [key: string]: string;
2334
+ };
2335
+ results?: Array<string>;
2336
+ }>;
2337
+ /** `idempotencyKey` defaults to a new one per call. */
2338
+ edit: (args: Omit<ToolArgs<"canvas_edit">, "idempotencyKey"> & {
2339
+ idempotencyKey?: string;
2340
+ }, options?: RequestOptions) => Promise<{
2341
+ canvasId: string;
2342
+ url: string;
2343
+ revision: number;
2344
+ createdNodeIds: {
2345
+ [key: string]: string;
2346
+ };
2347
+ warnings: Array<string>;
2348
+ overlaps: Array<{
2349
+ nodeId: string;
2350
+ overlapsWith: string;
2351
+ }>;
2352
+ replayed: boolean;
2353
+ }>;
2354
+ arrange: (args: ToolArgs<"canvas_arrange">, options?: RequestOptions) => Promise<{
2355
+ canvasId: string;
2356
+ url: string;
2357
+ revision: number;
2358
+ arranged: number;
2359
+ moved: number;
2360
+ bounds: {
2361
+ x: number;
2362
+ y: number;
2363
+ width: number;
2364
+ height: number;
2365
+ };
2366
+ overlaps: Array<{
2367
+ nodeId: string;
2368
+ overlapsWith: string;
2369
+ }>;
2370
+ }>;
2371
+ };
2372
+ readonly catalog: {
2373
+ search: (args?: ToolArgs<"catalog_search">, options?: RequestOptions) => Promise<{
2374
+ matched: boolean;
2375
+ note?: string;
2376
+ recommended: Array<{
2377
+ job: string;
2378
+ type: string;
2379
+ inputs?: {
2380
+ [key: string]: string;
2381
+ };
2382
+ credits?: number;
2383
+ }>;
2384
+ nodeTypes: Array<{
2385
+ type: string;
2386
+ category: "image" | "video" | "text" | "mesh" | "primitive";
2387
+ purpose: string;
2388
+ inputs: Array<{
2389
+ id: string;
2390
+ kind: "text" | "number" | "boolean" | "enum" | "image" | "video" | "media";
2391
+ description: string;
2392
+ required?: boolean;
2393
+ multiple?: boolean;
2394
+ values?: Array<string>;
2395
+ min?: number;
2396
+ max?: number;
2397
+ defaultValue?: string | number | boolean;
2398
+ }>;
2399
+ output: string;
2400
+ notes?: Array<string>;
2401
+ prices?: Array<{
2402
+ variant: string;
2403
+ credits: number;
2404
+ settings: string;
2405
+ }>;
2406
+ }>;
2407
+ }>;
2408
+ };
2409
+ readonly run: {
2410
+ /** `idempotencyKey` defaults to a new one per call. Add `.wait()` to wait. */
2411
+ start: (args: ToolArgs<"run_start">, options?: RequestOptions) => RunCall;
2412
+ get: (args: ToolArgs<"run_get">, options?: RequestOptions) => Promise<{
2413
+ runId: string;
2414
+ status: "running" | "completed" | "failed" | "cancelled";
2415
+ quotedCredits: number;
2416
+ startedAt: string;
2417
+ completedAt?: string;
2418
+ nodes: Array<{
2419
+ nodeId: string;
2420
+ type: string | null;
2421
+ status: "pending" | "running" | "succeeded" | "failed" | "skipped" | "cancelled" | "unknown";
2422
+ error?: string;
2423
+ outputs: Array<string>;
2424
+ text?: string;
2425
+ }>;
2426
+ plansUrl?: string;
2427
+ }>;
2428
+ cancel: (args: ToolArgs<"run_cancel">, options?: RequestOptions) => Promise<{
2429
+ cancelled: boolean;
2430
+ }>;
2431
+ /** Checks a run until it stops running. */
2432
+ wait: (args: {
2433
+ canvasId: string;
2434
+ runId: string;
2435
+ }, options?: WaitOptions) => Promise<{
2436
+ runId: string;
2437
+ status: "running" | "completed" | "failed" | "cancelled";
2438
+ quotedCredits: number;
2439
+ startedAt: string;
2440
+ completedAt?: string;
2441
+ nodes: Array<{
2442
+ nodeId: string;
2443
+ type: string | null;
2444
+ status: "pending" | "running" | "succeeded" | "failed" | "skipped" | "cancelled" | "unknown";
2445
+ error?: string;
2446
+ outputs: Array<string>;
2447
+ text?: string;
2448
+ }>;
2449
+ plansUrl?: string;
2450
+ }>;
2451
+ };
2452
+ readonly media: {
2453
+ export: (args: ToolArgs<"media_export">, options?: RequestOptions) => Promise<{
2454
+ url: string;
2455
+ expiresAt: string;
2456
+ fileCount: number;
2457
+ files: Array<{
2458
+ name: string;
2459
+ nodeId: string;
2460
+ url: string;
2461
+ }>;
2462
+ }>;
2463
+ import: (args: ToolArgs<"media_import">, options?: RequestOptions) => Promise<{
2464
+ url: string;
2465
+ mimeType: string;
2466
+ }>;
2467
+ /** Await for a page, or `for await` for every match. */
2468
+ search: (args: ToolArgs<"media_search">, options?: RequestOptions) => PagePromise<{
2469
+ assets: Array<{
2470
+ mediaId: string;
2471
+ url: string;
2472
+ type: string | null;
2473
+ title: string | null;
2474
+ description: string | null;
2475
+ createdAt: string | null;
2476
+ canvases: Array<{
2477
+ canvasId: string;
2478
+ title: string;
2479
+ }>;
2480
+ }>;
2481
+ nextCursor: string | null;
2482
+ } & {
2483
+ nextCursor: string | null;
2484
+ }, {
2485
+ mediaId: string;
2486
+ url: string;
2487
+ type: string | null;
2488
+ title: string | null;
2489
+ description: string | null;
2490
+ createdAt: string | null;
2491
+ canvases: Array<{
2492
+ canvasId: string;
2493
+ title: string;
2494
+ }>;
2495
+ }>;
2496
+ view: (args: ToolArgs<"media_view">, options?: RequestOptions) => Promise<{
2497
+ items: Array<{
2498
+ url: string;
2499
+ kind: "image" | "video" | "audio" | "mesh" | "unknown";
2500
+ facts?: {
2501
+ [key: string]: string | number | boolean;
2502
+ };
2503
+ previews: Array<{
2504
+ mimeType: string;
2505
+ data: string;
2506
+ atSeconds?: number;
2507
+ }>;
2508
+ note?: string;
2509
+ }>;
2510
+ }>;
2511
+ };
2512
+ readonly upload: {
2513
+ start: (args: ToolArgs<"upload_start">, options?: RequestOptions) => Promise<{
2514
+ uploadId: string;
2515
+ uploadPage: string;
2516
+ expiresAt: string;
2517
+ files: Array<{
2518
+ fileName: string;
2519
+ status: "upload";
2520
+ method: "PUT";
2521
+ url: string;
2522
+ headers: {
2523
+ [key: string]: string;
2524
+ };
2525
+ } | {
2526
+ fileName: string;
2527
+ status: "done";
2528
+ asset: {
2529
+ url: string;
2530
+ mimeType: string;
2531
+ };
2532
+ }>;
2533
+ }>;
2534
+ finish: (args: ToolArgs<"upload_finish">, options?: RequestOptions) => Promise<{
2535
+ files: Array<{
2536
+ url: string;
2537
+ mimeType: string;
2538
+ status: "done";
2539
+ fileName: string;
2540
+ } | {
2541
+ status: "failed";
2542
+ fileName: string;
2543
+ error: string;
2544
+ }>;
2545
+ }>;
2546
+ /** Hashes, starts, sends and finishes in one call. */
2547
+ files: (canvasId: string, files: UploadInput[], options?: RequestOptions) => Promise<({
2548
+ url: string;
2549
+ mimeType: string;
2550
+ status: "done";
2551
+ fileName: string;
2552
+ } | {
2553
+ status: "failed";
2554
+ fileName: string;
2555
+ error: string;
2556
+ })[]>;
2557
+ };
2558
+ readonly tool: {
2559
+ search: (args: ToolArgs<"tool_search">, options?: RequestOptions) => Promise<{
2560
+ tools: Array<{
2561
+ toolId: string;
2562
+ description: string | null;
2563
+ featured: boolean;
2564
+ tool: {
2565
+ title: string;
2566
+ mode: "free" | "paid";
2567
+ inputs: Array<{
2568
+ socket: string;
2569
+ kind: "image" | "video" | "audio" | "mesh" | "text";
2570
+ many: boolean;
2571
+ required: boolean;
2572
+ }>;
2573
+ controls: Array<{
2574
+ socket: string;
2575
+ label: string;
2576
+ kind: "slider";
2577
+ default: number;
2578
+ min: number;
2579
+ max: number;
2580
+ } | {
2581
+ socket: string;
2582
+ label: string;
2583
+ kind: "dropdown";
2584
+ default: string;
2585
+ options: Array<string>;
2586
+ } | {
2587
+ socket: string;
2588
+ label: string;
2589
+ kind: "switch";
2590
+ default: boolean;
2591
+ }>;
2592
+ outputs: Array<{
2593
+ socket: string;
2594
+ kind: "image" | "video" | "audio" | "text" | "json";
2595
+ }>;
2596
+ };
2597
+ }>;
2598
+ }>;
2599
+ /** Add `.wait()` to wait until it's built. */
2600
+ build: (args: ToolArgs<"tool_build">, options?: RequestOptions) => ToolBuildCall;
2601
+ };
2602
+ constructor(options?: FuserOptions);
2603
+ /** Calls a tool by its MCP name, with the exact arguments an agent sent. */
2604
+ call<N extends ToolName>(name: N, args: ToolArgs<N>, options?: RequestOptions): Promise<ToolResult<N>>;
2605
+ }
2606
+ //#endregion
2607
+ export type { FuserErrorDetails, FuserOptions, RequestOptions, ToolArgs, ToolName, ToolResult, UploadInput, WaitOptions };