@slopmachine/core 0.1.26 → 0.3.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/src/index.ts CHANGED
@@ -1,11 +1,124 @@
1
1
  import { AspectRatio as ImageAspectRatio, VideoAspectRatio } from "@pixerate/schemas";
2
- export type { ImageAspectRatio };
2
+ export type { ImageAspectRatio, VideoAspectRatio };
3
+
4
+ export interface PipelineStepResult {
5
+ stepId: string;
6
+ stepName?: string;
7
+ type: string;
8
+ outputUrl?: string;
9
+ outputText?: string;
10
+ outputData?: any;
11
+ computeTimeMs?: number;
12
+ fuelCost?: number;
13
+ error?: string;
14
+ }
15
+
16
+ export interface PipelineResult {
17
+ id: string;
18
+ pipelineId: string;
19
+ siloId: string;
20
+ url?: string;
21
+ text?: string;
22
+ data?: any;
23
+ resultType: string;
24
+ status: "completed" | "failed" | "pending";
25
+ stepResults: PipelineStepResult[];
26
+ totalComputeTimeMs: number;
27
+ totalFuelCost: number;
28
+ metadata?: Record<string, any>;
29
+ timestamp: any;
30
+ error?: string;
31
+ }
32
+
33
+ export interface SlopPipelineOptions {
34
+ /**
35
+ * The unique identifier of the pipeline to execute.
36
+ */
37
+ pipelineId: string;
38
+ /**
39
+ * Optional silo identifier for direct pipeline path resolution.
40
+ */
41
+ siloId?: string;
42
+ /**
43
+ * Dynamic runtime prompt to feed into the pipeline.
44
+ */
45
+ prompt?: string;
46
+ /**
47
+ * Variables to interpolate into prompt or step configs.
48
+ */
49
+ variables?: Record<string, string | number | undefined | null>;
50
+ /**
51
+ * Arbitrary user metadata to attach to the pipeline result document.
52
+ */
53
+ metadata?: Record<string, any>;
54
+ /**
55
+ * Whether to wait for full execution (default true) or return a job ID immediately.
56
+ */
57
+ sync?: boolean;
58
+ /**
59
+ * Whether to redirect to the primary media output URL upon completion.
60
+ */
61
+ redirect?: boolean;
62
+ /**
63
+ * Result ID to retrieve a specific previously generated result.
64
+ */
65
+ resultId?: string;
66
+ /**
67
+ * Base URL for the renderPipeline cloud function endpoint.
68
+ */
69
+ baseUrl?: string;
70
+ }
71
+
72
+ export interface ExecutePipelineOptions {
73
+ /**
74
+ * The unique identifier of the pipeline to execute.
75
+ */
76
+ pipelineId: string;
77
+ /**
78
+ * Optional silo identifier for direct pipeline path resolution.
79
+ */
80
+ siloId?: string;
81
+ /**
82
+ * Dynamic runtime prompt to feed into the pipeline.
83
+ */
84
+ prompt?: string;
85
+ /**
86
+ * Variables to interpolate into prompt or step configs.
87
+ */
88
+ variables?: Record<string, string | number | undefined | null>;
89
+ /**
90
+ * Arbitrary user metadata to attach to the pipeline result document.
91
+ */
92
+ metadata?: Record<string, any>;
93
+ /**
94
+ * Base URL for the renderPipeline cloud function endpoint.
95
+ */
96
+ baseUrl?: string;
97
+ }
3
98
 
4
99
  export interface SlopImageOptions {
5
100
  /**
6
101
  * The unique identifier of your Slop Machine bucket.
102
+ * Required when using a bucket unless pipelineId is provided.
7
103
  */
8
- bucketId: string;
104
+ bucketId?: string;
105
+ /**
106
+ * The unique identifier of your Slop Machine pipeline.
107
+ * Required when targeting a pipeline instead of a bucket.
108
+ */
109
+ pipelineId?: string;
110
+ /**
111
+ * Optional silo identifier.
112
+ */
113
+ siloId?: string;
114
+ /**
115
+ * Dynamic runtime prompt (used when targeting a pipeline).
116
+ */
117
+ prompt?: string;
118
+ /**
119
+ * Arbitrary user metadata to attach to the generation request / result document.
120
+ */
121
+ metadata?: Record<string, any>;
9
122
  /**
10
123
  * The specific version of the prompt/settings to use.
11
124
  * If omitted, the latest version will be used.
@@ -68,24 +181,57 @@ export function interpolatePrompt(
68
181
  /**
69
182
  * Builds a URL to render or retrieve an image from Slop Machine.
70
183
  *
184
+ * Supports both standard Buckets (via `bucketId`) and multi-step Pipelines (via `pipelineId`).
185
+ *
71
186
  * @param options - Configuration options for the image generation.
72
187
  * @returns A string containing the fully constructed URL.
73
188
  */
74
189
  export function buildImageUrl(options: SlopImageOptions): string {
75
190
  const {
76
191
  bucketId,
192
+ pipelineId,
193
+ siloId,
194
+ prompt,
195
+ metadata,
77
196
  version,
78
197
  resultId,
79
198
  aspectRatio = "1:1",
80
199
  quality = "fast",
81
200
  variables = {},
82
- baseUrl = "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderImage",
201
+ baseUrl,
83
202
  original,
84
203
  attachments,
85
204
  } = options;
86
205
 
206
+ if (pipelineId) {
207
+ const endpoint =
208
+ baseUrl ||
209
+ "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderPipeline";
210
+ const params = new URLSearchParams();
211
+ params.set("pipelineId", pipelineId);
212
+ params.set("redirect", "true");
213
+
214
+ if (siloId) params.set("siloId", siloId);
215
+ if (prompt) params.set("prompt", prompt);
216
+ if (resultId) params.set("resultId", resultId);
217
+
218
+ if (Object.keys(variables).length > 0) {
219
+ params.set("variables", JSON.stringify(variables));
220
+ }
221
+ if (metadata && Object.keys(metadata).length > 0) {
222
+ params.set("metadata", JSON.stringify(metadata));
223
+ }
224
+
225
+ return `${endpoint}?${params.toString()}`;
226
+ }
227
+
228
+ const endpoint =
229
+ baseUrl ||
230
+ "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderImage";
87
231
  const params = new URLSearchParams();
88
- params.set("bucketId", bucketId);
232
+ if (bucketId) {
233
+ params.set("bucketId", bucketId);
234
+ }
89
235
 
90
236
  if (!resultId) {
91
237
  if (aspectRatio) {
@@ -108,6 +254,10 @@ export function buildImageUrl(options: SlopImageOptions): string {
108
254
  params.set("variables", JSON.stringify(variables));
109
255
  }
110
256
 
257
+ if (metadata && Object.keys(metadata).length > 0) {
258
+ params.set("metadata", JSON.stringify(metadata));
259
+ }
260
+
111
261
  if (attachments && attachments.length > 0) {
112
262
  params.set("attachments", JSON.stringify(attachments));
113
263
  }
@@ -115,7 +265,7 @@ export function buildImageUrl(options: SlopImageOptions): string {
115
265
  params.set("resultId", resultId);
116
266
  }
117
267
 
118
- return `${baseUrl}?${params.toString()}`;
268
+ return `${endpoint}?${params.toString()}`;
119
269
  }
120
270
 
121
271
  /**
@@ -139,13 +289,29 @@ export function preloadImage(options: SlopImageOptions): Promise<void> {
139
289
  });
140
290
  }
141
291
 
142
- export type { VideoAspectRatio };
143
-
144
292
  export interface SlopVideoOptions {
145
293
  /**
146
294
  * The unique identifier of your Slop Machine bucket.
295
+ * Required when using a bucket unless pipelineId is provided.
147
296
  */
148
- bucketId: string;
297
+ bucketId?: string;
298
+ /**
299
+ * The unique identifier of your Slop Machine pipeline.
300
+ * Required when targeting a pipeline instead of a bucket.
301
+ */
302
+ pipelineId?: string;
303
+ /**
304
+ * Optional silo identifier.
305
+ */
306
+ siloId?: string;
307
+ /**
308
+ * Dynamic runtime prompt (used when targeting a pipeline).
309
+ */
310
+ prompt?: string;
311
+ /**
312
+ * Arbitrary user metadata to attach to the generation request / result document.
313
+ */
314
+ metadata?: Record<string, any>;
149
315
  /**
150
316
  * The specific version of the prompt/settings to use.
151
317
  * If omitted, the latest version will be used.
@@ -168,7 +334,7 @@ export interface SlopVideoOptions {
168
334
  variables?: Record<string, string | number | undefined | null>;
169
335
  /**
170
336
  * The duration of the generated video in seconds.
171
- * Must be between 4 and 8. Defaults to 4.
337
+ * If not specified, defaults to the bucket version's configured duration (or 4).
172
338
  */
173
339
  duration?: number;
174
340
  /**
@@ -183,18 +349,19 @@ export interface SlopVideoOptions {
183
349
  */
184
350
  baseUrl?: string;
185
351
  /**
186
- * If `true` (or `?raw=true`), bypasses the WebP optimized media and returns the original generated file.
187
- * Defaults to false.
352
+ * If true, serves the original generated uncompressed asset directly from storage.
188
353
  */
189
354
  original?: boolean;
190
355
  /**
191
- * Array of attachment URLs to include with the request.
356
+ * Array of runtime image attachments (URLs) to use with the video model.
357
+ * Only allowed if the bucket version has runtime attachments enabled.
192
358
  */
193
359
  attachments?: string[];
194
360
  }
195
361
 
196
362
  /**
197
- * Builds a URL to render or retrieve a video from Slop Machine.
363
+ * Builds the URL to render or stream an AI-generated video.
364
+ * Supports both standard Buckets (via `bucketId`) and multi-step Pipelines (via `pipelineId`).
198
365
  *
199
366
  * @param options - Configuration options for the video generation.
200
367
  * @returns A string containing the fully constructed URL.
@@ -202,19 +369,50 @@ export interface SlopVideoOptions {
202
369
  export function buildVideoUrl(options: SlopVideoOptions): string {
203
370
  const {
204
371
  bucketId,
372
+ pipelineId,
373
+ siloId,
374
+ prompt,
375
+ metadata,
205
376
  version,
206
377
  resultId,
207
378
  aspectRatio = "16:9",
208
379
  quality = "fast",
209
380
  variables = {},
210
- duration = 4,
211
- baseUrl = "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderVideo",
381
+ duration,
382
+ baseUrl,
212
383
  original,
213
384
  attachments,
214
385
  } = options;
215
386
 
387
+ if (pipelineId) {
388
+ const endpoint =
389
+ baseUrl ||
390
+ "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderPipeline";
391
+ const params = new URLSearchParams();
392
+ params.set("pipelineId", pipelineId);
393
+ params.set("redirect", "true");
394
+
395
+ if (siloId) params.set("siloId", siloId);
396
+ if (prompt) params.set("prompt", prompt);
397
+ if (resultId) params.set("resultId", resultId);
398
+
399
+ if (Object.keys(variables).length > 0) {
400
+ params.set("variables", JSON.stringify(variables));
401
+ }
402
+ if (metadata && Object.keys(metadata).length > 0) {
403
+ params.set("metadata", JSON.stringify(metadata));
404
+ }
405
+
406
+ return `${endpoint}?${params.toString()}`;
407
+ }
408
+
409
+ const endpoint =
410
+ baseUrl ||
411
+ "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderVideo";
216
412
  const params = new URLSearchParams();
217
- params.set("bucketId", bucketId);
413
+ if (bucketId) {
414
+ params.set("bucketId", bucketId);
415
+ }
218
416
 
219
417
  if (!resultId) {
220
418
  if (aspectRatio) {
@@ -238,6 +436,10 @@ export function buildVideoUrl(options: SlopVideoOptions): string {
238
436
  params.set("variables", JSON.stringify(variables));
239
437
  }
240
438
 
439
+ if (metadata && Object.keys(metadata).length > 0) {
440
+ params.set("metadata", JSON.stringify(metadata));
441
+ }
442
+
241
443
  if (attachments && attachments.length > 0) {
242
444
  params.set("attachments", JSON.stringify(attachments));
243
445
  }
@@ -245,7 +447,7 @@ export function buildVideoUrl(options: SlopVideoOptions): string {
245
447
  params.set("resultId", resultId);
246
448
  }
247
449
 
248
- return `${baseUrl}?${params.toString()}`;
450
+ return `${endpoint}?${params.toString()}`;
249
451
  }
250
452
 
251
453
  /**
@@ -262,8 +464,6 @@ export function preloadVideo(options: SlopVideoOptions): Promise<void> {
262
464
  return;
263
465
  }
264
466
 
265
- // We can just fetch the URL to preload it into the browser's cache.
266
- // We use no-cors to avoid CORS errors for simple preloads
267
467
  fetch(buildVideoUrl(options), { mode: "no-cors" })
268
468
  .then(() => resolve())
269
469
  .catch((err) => reject(err));
@@ -273,8 +473,26 @@ export function preloadVideo(options: SlopVideoOptions): Promise<void> {
273
473
  export interface SlopTextOptions {
274
474
  /**
275
475
  * The unique identifier of your Slop Machine bucket.
476
+ * Required when using a bucket unless pipelineId is provided.
276
477
  */
277
- bucketId: string;
478
+ bucketId?: string;
479
+ /**
480
+ * The unique identifier of your Slop Machine pipeline.
481
+ * Required when targeting a pipeline instead of a bucket.
482
+ */
483
+ pipelineId?: string;
484
+ /**
485
+ * Optional silo identifier.
486
+ */
487
+ siloId?: string;
488
+ /**
489
+ * Dynamic runtime prompt (used when targeting a pipeline).
490
+ */
491
+ prompt?: string;
492
+ /**
493
+ * Arbitrary user metadata to attach to the generation request / result document.
494
+ */
495
+ metadata?: Record<string, any>;
278
496
  /**
279
497
  * The specific version of the prompt/settings to use.
280
498
  * If omitted, the latest version will be used.
@@ -304,34 +522,65 @@ export interface SlopTextOptions {
304
522
  /**
305
523
  * Builds a URL to render or retrieve text from Slop Machine.
306
524
  *
525
+ * Supports both standard Buckets (via `bucketId`) and multi-step Pipelines (via `pipelineId`).
526
+ *
307
527
  * @param options - Configuration options for the text generation.
308
528
  * @returns A string containing the fully constructed URL.
309
529
  */
310
530
  export function buildTextUrl(options: SlopTextOptions): string {
311
531
  const {
312
532
  bucketId,
533
+ pipelineId,
534
+ siloId,
535
+ prompt,
536
+ metadata,
313
537
  version,
314
538
  resultId,
315
539
  variables = {},
316
- baseUrl = "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderText",
540
+ baseUrl,
317
541
  attachments,
318
542
  } = options;
319
543
 
544
+ if (pipelineId) {
545
+ const endpoint =
546
+ baseUrl ||
547
+ "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderPipeline";
548
+ const params = new URLSearchParams();
549
+ params.set("pipelineId", pipelineId);
550
+ params.set("sync", "true");
551
+
552
+ if (siloId) params.set("siloId", siloId);
553
+ if (prompt) params.set("prompt", prompt);
554
+ if (resultId) params.set("resultId", resultId);
555
+
556
+ if (Object.keys(variables).length > 0) {
557
+ params.set("variables", JSON.stringify(variables));
558
+ }
559
+ if (metadata && Object.keys(metadata).length > 0) {
560
+ params.set("metadata", JSON.stringify(metadata));
561
+ }
562
+
563
+ return `${endpoint}?${params.toString()}`;
564
+ }
565
+
566
+ const endpoint =
567
+ baseUrl ||
568
+ "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderText";
320
569
  const params = new URLSearchParams();
321
- params.set("bucketId", bucketId);
570
+ if (bucketId) {
571
+ params.set("bucketId", bucketId);
572
+ }
322
573
 
323
574
  if (!resultId) {
324
575
  if (version) {
325
576
  params.set("version", String(version));
326
577
  }
327
- if (resultId) {
328
- params.set("resultId", resultId);
329
- }
330
-
331
578
  if (Object.keys(variables).length > 0) {
332
579
  params.set("variables", JSON.stringify(variables));
333
580
  }
334
-
581
+ if (metadata && Object.keys(metadata).length > 0) {
582
+ params.set("metadata", JSON.stringify(metadata));
583
+ }
335
584
  if (attachments && attachments.length > 0) {
336
585
  params.set("attachments", JSON.stringify(attachments));
337
586
  }
@@ -339,7 +588,7 @@ export function buildTextUrl(options: SlopTextOptions): string {
339
588
  params.set("resultId", resultId);
340
589
  }
341
590
 
342
- return `${baseUrl}?${params.toString()}`;
591
+ return `${endpoint}?${params.toString()}`;
343
592
  }
344
593
 
345
594
  /**
@@ -356,14 +605,101 @@ export function preloadText(options: SlopTextOptions): Promise<void> {
356
605
  return;
357
606
  }
358
607
 
359
- // Fetch the URL to preload it into the browser's cache.
360
- // We use no-cors to avoid CORS errors for simple preloads
361
608
  fetch(buildTextUrl(options), { mode: "no-cors" })
362
609
  .then(() => resolve())
363
610
  .catch((err) => reject(err));
364
611
  });
365
612
  }
366
613
 
614
+ /**
615
+ * Builds a URL to execute or inspect a multi-step Pipeline from Slop Machine.
616
+ *
617
+ * @param options - Configuration options for the pipeline execution.
618
+ * @returns A string containing the fully constructed URL.
619
+ */
620
+ export function buildPipelineUrl(options: SlopPipelineOptions): string {
621
+ const {
622
+ pipelineId,
623
+ siloId,
624
+ prompt,
625
+ variables = {},
626
+ metadata = {},
627
+ sync = true,
628
+ redirect = false,
629
+ resultId,
630
+ baseUrl = "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderPipeline",
631
+ } = options;
632
+
633
+ const params = new URLSearchParams();
634
+ params.set("pipelineId", pipelineId);
635
+
636
+ if (siloId) params.set("siloId", siloId);
637
+ if (prompt) params.set("prompt", prompt);
638
+ if (resultId) params.set("resultId", resultId);
639
+ if (sync !== undefined) params.set("sync", String(sync));
640
+ if (redirect) params.set("redirect", "true");
641
+
642
+ if (Object.keys(variables).length > 0) {
643
+ params.set("variables", JSON.stringify(variables));
644
+ }
645
+ if (Object.keys(metadata).length > 0) {
646
+ params.set("metadata", JSON.stringify(metadata));
647
+ }
648
+
649
+ return `${baseUrl}?${params.toString()}`;
650
+ }
651
+
652
+ /**
653
+ * Executes a Slop Machine multi-step Pipeline programmatically and returns the full typed result payload.
654
+ *
655
+ * @param options - Execution parameters including the pipelineId and runtime prompt/variables/metadata.
656
+ * @returns A promise resolving to the completed PipelineResult document.
657
+ */
658
+ export async function executePipeline(
659
+ options: ExecutePipelineOptions,
660
+ ): Promise<PipelineResult> {
661
+ const {
662
+ pipelineId,
663
+ siloId,
664
+ prompt,
665
+ variables,
666
+ metadata,
667
+ baseUrl = "https://us-central1-slopmachine-12bfb.cloudfunctions.net/renderPipeline",
668
+ } = options;
669
+
670
+ const response = await fetch(baseUrl, {
671
+ method: "POST",
672
+ headers: {
673
+ "Content-Type": "application/json",
674
+ },
675
+ body: JSON.stringify({
676
+ pipelineId,
677
+ ...(siloId ? { siloId } : {}),
678
+ ...(prompt ? { prompt } : {}),
679
+ variables,
680
+ metadata,
681
+ sync: true,
682
+ }),
683
+ });
684
+
685
+ if (!response.ok) {
686
+ let errorDetail = response.statusText;
687
+ try {
688
+ const errorJson = await response.json();
689
+ if (errorJson.error) {
690
+ errorDetail = errorJson.error;
691
+ }
692
+ } catch {
693
+ // Use statusText
694
+ }
695
+ throw new Error(
696
+ `Pipeline execution failed (${response.status}): ${errorDetail}`,
697
+ );
698
+ }
699
+
700
+ return (await response.json()) as PipelineResult;
701
+ }
702
+
367
703
  /**
368
704
  * Uploads a base64 encoded file as a temporary attachment to be used in generation requests.
369
705
  *