@snaptrude/plugin-core 0.7.0 → 0.7.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.
@@ -10,6 +10,11 @@ const JsonValue: z.ZodType<JsonValue> = z.lazy(() =>
10
10
  z.union([JsonPrimitive, z.array(JsonValue), z.record(z.string(), JsonValue)]),
11
11
  )
12
12
 
13
+ export const PluginAIInspirationRunMode = z.enum(["blocking", "job"])
14
+ export type PluginAIInspirationRunMode = z.infer<
15
+ typeof PluginAIInspirationRunMode
16
+ >
17
+
13
18
  export const PluginAIInspirationOutputKind = z.enum([
14
19
  "source",
15
20
  "image",
@@ -24,6 +29,20 @@ export type PluginAIInspirationModelOutput = z.infer<
24
29
  typeof PluginAIInspirationModelOutput
25
30
  >
26
31
 
32
+ export const PluginAIInspirationRuntimeProvider = z.enum(["gpt", "fal"])
33
+ export type PluginAIInspirationRuntimeProvider = z.infer<
34
+ typeof PluginAIInspirationRuntimeProvider
35
+ >
36
+
37
+ export const PluginAIInspirationPromptStrategy = z.enum([
38
+ "gpt-image",
39
+ "fal-image",
40
+ "fal-video",
41
+ ])
42
+ export type PluginAIInspirationPromptStrategy = z.infer<
43
+ typeof PluginAIInspirationPromptStrategy
44
+ >
45
+
27
46
  export const PluginAIInspirationShapeKind = z.enum(["image", "view", "video"])
28
47
  export type PluginAIInspirationShapeKind = z.infer<
29
48
  typeof PluginAIInspirationShapeKind
@@ -53,6 +72,28 @@ export type PluginAIInspirationVideoDuration = z.infer<
53
72
  typeof PluginAIInspirationVideoDuration
54
73
  >
55
74
 
75
+ export const PluginAIInspirationJobStatus = z.enum([
76
+ "queued",
77
+ "running",
78
+ "completed",
79
+ "failed",
80
+ "cancelled",
81
+ ])
82
+ export type PluginAIInspirationJobStatus = z.infer<
83
+ typeof PluginAIInspirationJobStatus
84
+ >
85
+
86
+ export const PluginAIInspirationWorkflowRunState = z.enum([
87
+ "current",
88
+ "stale",
89
+ "running",
90
+ "failed",
91
+ "superseded",
92
+ ])
93
+ export type PluginAIInspirationWorkflowRunState = z.infer<
94
+ typeof PluginAIInspirationWorkflowRunState
95
+ >
96
+
56
97
  export const PluginAIInspirationRegionHint = z.object({
57
98
  x: z.number().finite(),
58
99
  y: z.number().finite(),
@@ -151,6 +192,23 @@ export const PluginAIInspirationModel = z.object({
151
192
  })
152
193
  export type PluginAIInspirationModel = z.infer<typeof PluginAIInspirationModel>
153
194
 
195
+ export const PluginAIInspirationModelCapability = z.object({
196
+ id: z.string(),
197
+ output: PluginAIInspirationModelOutput,
198
+ provider: PluginAIInspirationRuntimeProvider,
199
+ supportsRegionEdit: z.boolean(),
200
+ supportsReferenceImages: z.boolean(),
201
+ supportsStylePresets: z.boolean(),
202
+ supportsSiteContext: z.boolean(),
203
+ supportsSketchGuidance: z.boolean(),
204
+ supportsKeyframes: z.boolean(),
205
+ maxExtraImages: z.number().int().nonnegative(),
206
+ promptStrategy: PluginAIInspirationPromptStrategy,
207
+ })
208
+ export type PluginAIInspirationModelCapability = z.infer<
209
+ typeof PluginAIInspirationModelCapability
210
+ >
211
+
154
212
  export const PluginAIInspirationListModelsResult = z.object({
155
213
  defaultModelId: z.string(),
156
214
  models: z.array(PluginAIInspirationModel),
@@ -159,6 +217,20 @@ export type PluginAIInspirationListModelsResult = z.infer<
159
217
  typeof PluginAIInspirationListModelsResult
160
218
  >
161
219
 
220
+ export const PluginAIInspirationGetModelCapabilitiesArgs = z.object({
221
+ modelId: z.string().min(1),
222
+ })
223
+ export type PluginAIInspirationGetModelCapabilitiesArgs = z.infer<
224
+ typeof PluginAIInspirationGetModelCapabilitiesArgs
225
+ >
226
+
227
+ export const PluginAIInspirationGetModelCapabilitiesResult = z.object({
228
+ capability: PluginAIInspirationModelCapability,
229
+ })
230
+ export type PluginAIInspirationGetModelCapabilitiesResult = z.infer<
231
+ typeof PluginAIInspirationGetModelCapabilitiesResult
232
+ >
233
+
162
234
  export const PluginAIInspirationShapeRef = z.object({
163
235
  shapeId: z.string(),
164
236
  assetId: z.string().optional(),
@@ -188,6 +260,59 @@ export type PluginAIInspirationListSourcesResult = z.infer<
188
260
  typeof PluginAIInspirationListSourcesResult
189
261
  >
190
262
 
263
+ export const PluginAIInspirationGetSelectionResult = z.object({
264
+ selectedShapeIds: z.array(z.string()),
265
+ sources: z.array(PluginAIInspirationShapeRef),
266
+ })
267
+ export type PluginAIInspirationGetSelectionResult = z.infer<
268
+ typeof PluginAIInspirationGetSelectionResult
269
+ >
270
+
271
+ export const PluginAIInspirationPresetReferenceImage = z.object({
272
+ url: z.string(),
273
+ label: z.string().optional(),
274
+ weight: z.number().finite().optional(),
275
+ })
276
+ export type PluginAIInspirationPresetReferenceImage = z.infer<
277
+ typeof PluginAIInspirationPresetReferenceImage
278
+ >
279
+
280
+ export const PluginAIInspirationPreset = z.object({
281
+ id: z.string(),
282
+ name: z.string(),
283
+ source: z.enum(["curated", "user"]),
284
+ modelId: z.string(),
285
+ categoryId: z.string().optional(),
286
+ categoryLabel: z.string().optional(),
287
+ description: z.string().optional(),
288
+ previewImageUrl: z.string().optional(),
289
+ prompt: z.string().optional(),
290
+ stylePrompt: z.string().optional(),
291
+ tags: z.array(z.string()).optional(),
292
+ referenceImages: z.array(PluginAIInspirationPresetReferenceImage).optional(),
293
+ siteDefaults: PluginAIInspirationAppliedPreset.shape.siteDefaults.optional(),
294
+ })
295
+ export type PluginAIInspirationPreset = z.infer<
296
+ typeof PluginAIInspirationPreset
297
+ >
298
+
299
+ export const PluginAIInspirationPresetCategory = z.object({
300
+ id: z.string(),
301
+ label: z.string(),
302
+ description: z.string().optional(),
303
+ })
304
+ export type PluginAIInspirationPresetCategory = z.infer<
305
+ typeof PluginAIInspirationPresetCategory
306
+ >
307
+
308
+ export const PluginAIInspirationGetPresetCatalogResult = z.object({
309
+ categories: z.array(PluginAIInspirationPresetCategory),
310
+ presets: z.array(PluginAIInspirationPreset),
311
+ })
312
+ export type PluginAIInspirationGetPresetCatalogResult = z.infer<
313
+ typeof PluginAIInspirationGetPresetCatalogResult
314
+ >
315
+
191
316
  export const PluginAIInspirationOutput = z.object({
192
317
  outputType: z.enum(["image", "video"]),
193
318
  shapeId: z.string(),
@@ -230,13 +355,16 @@ export const PluginAIInspirationGenerateArgs = z.object({
230
355
  regionHint: PluginAIInspirationRegionHint.optional(),
231
356
  sketchGuidance: PluginAIInspirationSketchGuidance.optional(),
232
357
  video: PluginAIInspirationVideoOptions.optional(),
358
+ runMode: PluginAIInspirationRunMode.optional(),
233
359
  })
234
360
  export type PluginAIInspirationGenerateArgs = z.infer<
235
361
  typeof PluginAIInspirationGenerateArgs
236
362
  >
237
363
 
238
364
  export const PluginAIInspirationRunResult = z.object({
239
- outputs: z.array(PluginAIInspirationOutput).min(1),
365
+ jobId: z.string().optional(),
366
+ output: PluginAIInspirationOutput.optional(),
367
+ outputs: z.array(PluginAIInspirationOutput).optional(),
240
368
  metadata: PluginAIInspirationRunMetadata.optional(),
241
369
  })
242
370
  export type PluginAIInspirationRunResult = z.infer<
@@ -248,11 +376,335 @@ export const PluginAIInspirationRefineArgs = z.object({
248
376
  upscaleFactor: z
249
377
  .union([z.literal(1.5), z.literal(2), z.literal(4)])
250
378
  .optional(),
379
+ runMode: PluginAIInspirationRunMode.optional(),
251
380
  })
252
381
  export type PluginAIInspirationRefineArgs = z.infer<
253
382
  typeof PluginAIInspirationRefineArgs
254
383
  >
255
384
 
385
+ export const PluginAIInspirationJobProgress = z.object({
386
+ currentStep: z.number().int().nonnegative().optional(),
387
+ totalSteps: z.number().int().nonnegative().optional(),
388
+ message: z.string().optional(),
389
+ })
390
+ export type PluginAIInspirationJobProgress = z.infer<
391
+ typeof PluginAIInspirationJobProgress
392
+ >
393
+
394
+ export const PluginAIInspirationJob = z.object({
395
+ jobId: z.string(),
396
+ status: PluginAIInspirationJobStatus,
397
+ createdAt: z.number(),
398
+ updatedAt: z.number(),
399
+ completedAt: z.number().optional(),
400
+ method: z.string(),
401
+ progress: PluginAIInspirationJobProgress.optional(),
402
+ result: PluginAIInspirationRunResult.optional(),
403
+ error: z.string().optional(),
404
+ })
405
+ export type PluginAIInspirationJob = z.infer<typeof PluginAIInspirationJob>
406
+
407
+ export const PluginAIInspirationJobArgs = z.object({
408
+ jobId: z.string().min(1),
409
+ })
410
+ export type PluginAIInspirationJobArgs = z.infer<
411
+ typeof PluginAIInspirationJobArgs
412
+ >
413
+
414
+ export const PluginAIInspirationGetJobResult = z.object({
415
+ job: PluginAIInspirationJob,
416
+ })
417
+ export type PluginAIInspirationGetJobResult = z.infer<
418
+ typeof PluginAIInspirationGetJobResult
419
+ >
420
+
421
+ export const PluginAIInspirationCancelJobResult = z.object({
422
+ job: PluginAIInspirationJob,
423
+ })
424
+ export type PluginAIInspirationCancelJobResult = z.infer<
425
+ typeof PluginAIInspirationCancelJobResult
426
+ >
427
+
428
+ export const PluginAIInspirationListJobsResult = z.object({
429
+ jobs: z.array(PluginAIInspirationJob),
430
+ })
431
+ export type PluginAIInspirationListJobsResult = z.infer<
432
+ typeof PluginAIInspirationListJobsResult
433
+ >
434
+
435
+ export const PluginAIInspirationWorkflowVideoConfig = z.object({
436
+ mode: z.string().optional(),
437
+ motion: z.string().optional(),
438
+ duration: z.string().optional(),
439
+ endFrameShapeId: z.string().optional(),
440
+ })
441
+ export type PluginAIInspirationWorkflowVideoConfig = z.infer<
442
+ typeof PluginAIInspirationWorkflowVideoConfig
443
+ >
444
+
445
+ export const PluginAIInspirationGenerationInputSnapshot = z.object({
446
+ version: z.literal(1),
447
+ meta: z.record(z.string(), JsonValue),
448
+ regionHint: PluginAIInspirationRegionHint.optional(),
449
+ sketchGuidance: z.record(z.string(), JsonValue).optional(),
450
+ sourceCameraHeading: z.number().finite().optional(),
451
+ })
452
+ export type PluginAIInspirationGenerationInputSnapshot = z.infer<
453
+ typeof PluginAIInspirationGenerationInputSnapshot
454
+ >
455
+
456
+ export const PluginAIInspirationWorkflowOperation = z.object({
457
+ type: z.enum(["generate-image", "refine", "generate-video"]),
458
+ label: z.string(),
459
+ prompt: z.string().optional(),
460
+ modelId: z.string().optional(),
461
+ presetId: z.string().optional(),
462
+ presetName: z.string().optional(),
463
+ refineFactor: z.number().finite().optional(),
464
+ sourceRole: z.enum(["primary", "end-frame"]).optional(),
465
+ video: PluginAIInspirationWorkflowVideoConfig.optional(),
466
+ generationInput: PluginAIInspirationGenerationInputSnapshot.optional(),
467
+ })
468
+ export type PluginAIInspirationWorkflowOperation = z.infer<
469
+ typeof PluginAIInspirationWorkflowOperation
470
+ >
471
+
472
+ export const PluginAIInspirationWorkflowNode = z.object({
473
+ id: z.string(),
474
+ shapeId: z.string(),
475
+ assetId: z.string().optional(),
476
+ kind: PluginAIInspirationOutputKind,
477
+ state: z.string(),
478
+ runState: PluginAIInspirationWorkflowRunState.optional(),
479
+ staleReason: z.string().optional(),
480
+ incomingEdgeIds: z.array(z.string()),
481
+ outgoingEdgeIds: z.array(z.string()),
482
+ createdAt: z.number(),
483
+ updatedAt: z.number(),
484
+ })
485
+ export type PluginAIInspirationWorkflowNode = z.infer<
486
+ typeof PluginAIInspirationWorkflowNode
487
+ >
488
+
489
+ export const PluginAIInspirationWorkflowEdge = z.object({
490
+ id: z.string(),
491
+ sourceNodeId: z.string(),
492
+ targetNodeId: z.string(),
493
+ arrowShapeId: z.string().optional(),
494
+ operation: PluginAIInspirationWorkflowOperation,
495
+ state: z.string(),
496
+ runState: PluginAIInspirationWorkflowRunState.optional(),
497
+ staleReason: z.string().optional(),
498
+ supersededByEdgeId: z.string().optional(),
499
+ createdAt: z.number(),
500
+ updatedAt: z.number(),
501
+ })
502
+ export type PluginAIInspirationWorkflowEdge = z.infer<
503
+ typeof PluginAIInspirationWorkflowEdge
504
+ >
505
+
506
+ export const PluginAIInspirationWorkflow = z.object({
507
+ id: z.string(),
508
+ rootNodeIds: z.array(z.string()),
509
+ nodeIds: z.array(z.string()),
510
+ edgeIds: z.array(z.string()),
511
+ nodes: z.record(z.string(), PluginAIInspirationWorkflowNode),
512
+ edges: z.record(z.string(), PluginAIInspirationWorkflowEdge),
513
+ createdAt: z.number(),
514
+ updatedAt: z.number(),
515
+ })
516
+ export type PluginAIInspirationWorkflow = z.infer<
517
+ typeof PluginAIInspirationWorkflow
518
+ >
519
+
520
+ export const PluginAIInspirationGetWorkflowForShapeArgs = z.object({
521
+ shapeId: z.string().min(1),
522
+ })
523
+ export type PluginAIInspirationGetWorkflowForShapeArgs = z.infer<
524
+ typeof PluginAIInspirationGetWorkflowForShapeArgs
525
+ >
526
+
527
+ export const PluginAIInspirationGetWorkflowForShapeResult = z.object({
528
+ workflow: PluginAIInspirationWorkflow.nullable(),
529
+ node: PluginAIInspirationWorkflowNode.nullable(),
530
+ })
531
+ export type PluginAIInspirationGetWorkflowForShapeResult = z.infer<
532
+ typeof PluginAIInspirationGetWorkflowForShapeResult
533
+ >
534
+
535
+ export const PluginAIInspirationRerunPlanResult = z.discriminatedUnion(
536
+ "status",
537
+ [
538
+ z.object({
539
+ status: z.literal("ready"),
540
+ workflowId: z.string(),
541
+ sourceNode: PluginAIInspirationWorkflowNode,
542
+ edgeIds: z.array(z.string()),
543
+ edges: z.array(PluginAIInspirationWorkflowEdge),
544
+ recipe: z.lazy(() => PluginAIInspirationRecipe),
545
+ needsEndFrame: z.boolean(),
546
+ defaultEndFrameShapeId: z.string().nullable(),
547
+ }),
548
+ z.object({
549
+ status: z.literal("unavailable"),
550
+ reason: z.enum([
551
+ "not-in-workflow",
552
+ "source-only",
553
+ "running",
554
+ "missing-input",
555
+ ]),
556
+ }),
557
+ ],
558
+ )
559
+ export type PluginAIInspirationRerunPlanResult = z.infer<
560
+ typeof PluginAIInspirationRerunPlanResult
561
+ >
562
+
563
+ export const PluginAIInspirationRerunSelectedBranchArgs = z.object({
564
+ shapeId: z.string().min(1),
565
+ endFrameShapeId: z.string().optional(),
566
+ runMode: PluginAIInspirationRunMode.optional(),
567
+ })
568
+ export type PluginAIInspirationRerunSelectedBranchArgs = z.infer<
569
+ typeof PluginAIInspirationRerunSelectedBranchArgs
570
+ >
571
+
572
+ export const PluginAIInspirationRecipeSlot = z.object({
573
+ id: z.string(),
574
+ type: z.enum(["source-image", "end-frame"]),
575
+ label: z.string(),
576
+ required: z.boolean(),
577
+ })
578
+ export type PluginAIInspirationRecipeSlot = z.infer<
579
+ typeof PluginAIInspirationRecipeSlot
580
+ >
581
+
582
+ export const PluginAIInspirationRecipeStep = z.object({
583
+ id: z.string(),
584
+ operation: PluginAIInspirationWorkflowOperation,
585
+ outputKind: z.enum(["image", "video"]),
586
+ })
587
+ export type PluginAIInspirationRecipeStep = z.infer<
588
+ typeof PluginAIInspirationRecipeStep
589
+ >
590
+
591
+ export const PluginAIInspirationRecipeDraft = z.object({
592
+ name: z.string(),
593
+ summary: z.string(),
594
+ slots: z.array(PluginAIInspirationRecipeSlot),
595
+ steps: z.array(PluginAIInspirationRecipeStep).min(1).max(20),
596
+ outputKind: z.enum(["image", "video"]),
597
+ thumbnailUrl: z.string().optional(),
598
+ })
599
+ export type PluginAIInspirationRecipeDraft = z.infer<
600
+ typeof PluginAIInspirationRecipeDraft
601
+ >
602
+
603
+ export const PluginAIInspirationRecipe: z.ZodType<
604
+ PluginAIInspirationRecipeDraft & {
605
+ version: 1
606
+ id: string
607
+ fingerprint?: string
608
+ createdAt: number
609
+ updatedAt: number
610
+ }
611
+ > = PluginAIInspirationRecipeDraft.extend({
612
+ version: z.literal(1),
613
+ id: z.string(),
614
+ fingerprint: z.string().optional(),
615
+ createdAt: z.number(),
616
+ updatedAt: z.number(),
617
+ })
618
+ export type PluginAIInspirationRecipe = z.infer<
619
+ typeof PluginAIInspirationRecipe
620
+ >
621
+
622
+ export const PluginAIInspirationExtractionResult = z.discriminatedUnion(
623
+ "status",
624
+ [
625
+ z.object({
626
+ status: z.literal("ready"),
627
+ draft: PluginAIInspirationRecipeDraft,
628
+ }),
629
+ z.object({
630
+ status: z.literal("unavailable"),
631
+ reason: z.enum([
632
+ "not-in-workflow",
633
+ "source-only",
634
+ "missing-workflow",
635
+ "missing-node",
636
+ "missing-input",
637
+ "invalid-workflow",
638
+ ]),
639
+ }),
640
+ ],
641
+ )
642
+ export type PluginAIInspirationExtractionResult = z.infer<
643
+ typeof PluginAIInspirationExtractionResult
644
+ >
645
+
646
+ export const PluginAIInspirationListRecipesResult = z.object({
647
+ recipes: z.array(PluginAIInspirationRecipe),
648
+ })
649
+ export type PluginAIInspirationListRecipesResult = z.infer<
650
+ typeof PluginAIInspirationListRecipesResult
651
+ >
652
+
653
+ export const PluginAIInspirationSaveRecipeArgs = z.object({
654
+ draft: PluginAIInspirationRecipeDraft,
655
+ name: z.string().min(1),
656
+ })
657
+ export type PluginAIInspirationSaveRecipeArgs = z.infer<
658
+ typeof PluginAIInspirationSaveRecipeArgs
659
+ >
660
+
661
+ export const PluginAIInspirationSaveRecipeResult = z.discriminatedUnion(
662
+ "status",
663
+ [
664
+ z.object({ status: z.literal("saved"), recipe: PluginAIInspirationRecipe }),
665
+ z.object({
666
+ status: z.literal("duplicate"),
667
+ recipe: PluginAIInspirationRecipe,
668
+ }),
669
+ z.object({ status: z.literal("invalid-name"), recipe: z.null() }),
670
+ z.object({ status: z.literal("failed"), recipe: z.null() }),
671
+ ],
672
+ )
673
+ export type PluginAIInspirationSaveRecipeResult = z.infer<
674
+ typeof PluginAIInspirationSaveRecipeResult
675
+ >
676
+
677
+ export const PluginAIInspirationDeleteRecipeArgs = z.object({
678
+ recipeId: z.string().min(1),
679
+ })
680
+ export type PluginAIInspirationDeleteRecipeArgs = z.infer<
681
+ typeof PluginAIInspirationDeleteRecipeArgs
682
+ >
683
+
684
+ export const PluginAIInspirationDeleteRecipeResult = z.object({
685
+ deleted: z.boolean(),
686
+ })
687
+ export type PluginAIInspirationDeleteRecipeResult = z.infer<
688
+ typeof PluginAIInspirationDeleteRecipeResult
689
+ >
690
+
691
+ export const PluginAIInspirationExtractRecipeFromShapeArgs = z.object({
692
+ shapeId: z.string().min(1),
693
+ })
694
+ export type PluginAIInspirationExtractRecipeFromShapeArgs = z.infer<
695
+ typeof PluginAIInspirationExtractRecipeFromShapeArgs
696
+ >
697
+
698
+ export const PluginAIInspirationRunRecipeArgs = z.object({
699
+ recipeId: z.string().optional(),
700
+ recipe: PluginAIInspirationRecipe.optional(),
701
+ slotShapeIds: z.record(z.string(), z.string()),
702
+ runMode: PluginAIInspirationRunMode.optional(),
703
+ })
704
+ export type PluginAIInspirationRunRecipeArgs = z.infer<
705
+ typeof PluginAIInspirationRunRecipeArgs
706
+ >
707
+
256
708
  /**
257
709
  * Present-mode AI Inspiration APIs.
258
710
  *
@@ -260,6 +712,11 @@ export type PluginAIInspirationRefineArgs = z.infer<
260
712
  * AI quota. They create outputs on the Present canvas; pure backend generation
261
713
  * without canvas output is intentionally out of scope.
262
714
  *
715
+ * Long-running generations can be started with `runMode: "job"` and tracked via
716
+ * {@linkcode PluginPresentationAIInspirationApi.getJob} /
717
+ * {@linkcode PluginPresentationAIInspirationApi.listJobs}; the default
718
+ * `"blocking"` mode resolves with the canvas outputs directly.
719
+ *
263
720
  * Accessed via `snaptrude.presentation.aiInspiration`.
264
721
  */
265
722
  export abstract class PluginPresentationAIInspirationApi {
@@ -283,6 +740,29 @@ export abstract class PluginPresentationAIInspirationApi {
283
740
  */
284
741
  public abstract listModels(): PluginApiReturn<PluginAIInspirationListModelsResult>
285
742
 
743
+ /**
744
+ * Get capability flags for a model.
745
+ *
746
+ * @param args - Object containing `modelId`.
747
+ * @returns Capability flags such as reference, site-context, region, and keyframe support.
748
+ *
749
+ * @examplePrompt What can this model do?
750
+ * @examplePrompt Does the default model support reference images?
751
+ * @examplePrompt Check if the video model supports keyframes
752
+ *
753
+ * # Example
754
+ * ```ts
755
+ * const { defaultModelId } = await snaptrude.presentation.aiInspiration.listModels()
756
+ * const { capability } = await snaptrude.presentation.aiInspiration.getModelCapabilities({
757
+ * modelId: defaultModelId,
758
+ * })
759
+ * console.log(capability.supportsReferenceImages, capability.maxExtraImages)
760
+ * ```
761
+ */
762
+ public abstract getModelCapabilities(
763
+ args: PluginAIInspirationGetModelCapabilitiesArgs,
764
+ ): PluginApiReturn<PluginAIInspirationGetModelCapabilitiesResult>
765
+
286
766
  /**
287
767
  * List image/view/video sources on the current Present page.
288
768
  *
@@ -303,12 +783,47 @@ export abstract class PluginPresentationAIInspirationApi {
303
783
  args: PluginAIInspirationListSourcesArgs,
304
784
  ): PluginApiReturn<PluginAIInspirationListSourcesResult>
305
785
 
786
+ /**
787
+ * Get selected Present canvas shapes that AI Inspiration can use.
788
+ *
789
+ * @returns Selected shape IDs and resolved source references.
790
+ *
791
+ * @examplePrompt Generate from what I have selected
792
+ * @examplePrompt Which of my selected shapes can be used as AI sources?
793
+ *
794
+ * # Example
795
+ * ```ts
796
+ * const { selectedShapeIds, sources } = await snaptrude.presentation.aiInspiration.getSelection()
797
+ * console.log(selectedShapeIds.length, "selected,", sources.length, "usable")
798
+ * ```
799
+ */
800
+ public abstract getSelection(): PluginApiReturn<PluginAIInspirationGetSelectionResult>
801
+
802
+ /**
803
+ * Get the curated AI Inspiration preset catalog.
804
+ *
805
+ * @returns Preset categories and presets.
806
+ *
807
+ * @examplePrompt What style presets are available?
808
+ * @examplePrompt List the curated AI generation presets
809
+ * @examplePrompt Show me the exterior render styles
810
+ *
811
+ * # Example
812
+ * ```ts
813
+ * const { categories, presets } = await snaptrude.presentation.aiInspiration.getPresetCatalog()
814
+ * const exterior = presets.filter((p) => p.categoryLabel === "Exterior")
815
+ * console.log(categories.map((c) => c.label), exterior.map((p) => p.name))
816
+ * ```
817
+ */
818
+ public abstract getPresetCatalog(): PluginApiReturn<PluginAIInspirationGetPresetCatalogResult>
819
+
306
820
  /**
307
821
  * Generate an image or video from a Present canvas source.
308
822
  *
309
823
  * @param args - Generation options including source, prompt, model, references, site context,
310
- * region guidance, sketch guidance, and video options.
311
- * @returns The created canvas output(s).
824
+ * region guidance, sketch guidance, video options, and run mode.
825
+ * @returns The created canvas output(s) in blocking mode, or a `jobId` when
826
+ * called with `runMode: "job"`.
312
827
  *
313
828
  * @examplePrompt Generate an image from this sketch
314
829
  * @examplePrompt Render the selected view as a photorealistic image
@@ -326,7 +841,7 @@ export abstract class PluginPresentationAIInspirationApi {
326
841
  * referenceShapeIds: refs.slice(0, 2).map((r) => r.shapeId),
327
842
  * referenceStrength: "medium",
328
843
  * })
329
- * for (const out of outputs) console.log(out.outputType, out.shapeId, out.outputUrl)
844
+ * for (const out of outputs ?? []) console.log(out.outputType, out.shapeId, out.outputUrl)
330
845
  * ```
331
846
  */
332
847
  public abstract generate(
@@ -336,8 +851,9 @@ export abstract class PluginPresentationAIInspirationApi {
336
851
  /**
337
852
  * Refine/upscale an AI Inspiration source image.
338
853
  *
339
- * @param args - Source shape and optional upscale factor.
340
- * @returns The refined canvas output(s).
854
+ * @param args - Source shape, optional upscale factor, and run mode.
855
+ * @returns The refined canvas output(s) in blocking mode, or a `jobId` when
856
+ * called with `runMode: "job"`.
341
857
  *
342
858
  * @examplePrompt Upscale this AI image
343
859
  * @examplePrompt Refine and sharpen the selected render
@@ -352,11 +868,249 @@ export abstract class PluginPresentationAIInspirationApi {
352
868
  * sourceShapeId: image.shapeId,
353
869
  * upscaleFactor: 2,
354
870
  * })
355
- * console.log(outputs[0].shapeId)
871
+ * console.log(outputs?.[0]?.shapeId)
356
872
  * }
357
873
  * ```
358
874
  */
359
875
  public abstract refine(
360
876
  args: PluginAIInspirationRefineArgs,
361
877
  ): PluginApiReturn<PluginAIInspirationRunResult>
878
+
879
+ /**
880
+ * Get a transient AI Inspiration job by ID.
881
+ *
882
+ * @param args - Object containing `jobId`.
883
+ * @returns The job with status, progress, and result when completed.
884
+ *
885
+ * @examplePrompt Is my render finished?
886
+ * @examplePrompt Check on the generation job
887
+ *
888
+ * # Example
889
+ * ```ts
890
+ * const { jobId } = await snaptrude.presentation.aiInspiration.generate({
891
+ * sourceShapeId: source.shapeId,
892
+ * prompt: "Aerial dusk render",
893
+ * runMode: "job",
894
+ * })
895
+ * const { job } = await snaptrude.presentation.aiInspiration.getJob({ jobId })
896
+ * console.log(job.status, job.progress?.message)
897
+ * ```
898
+ */
899
+ public abstract getJob(
900
+ args: PluginAIInspirationJobArgs,
901
+ ): PluginApiReturn<PluginAIInspirationGetJobResult>
902
+
903
+ /**
904
+ * Cancel a transient AI Inspiration job.
905
+ *
906
+ * @param args - Object containing `jobId`.
907
+ * @returns The job after the cancel request.
908
+ *
909
+ * @examplePrompt Cancel the running generation
910
+ * @examplePrompt Stop that AI job
911
+ *
912
+ * # Example
913
+ * ```ts
914
+ * const { job } = await snaptrude.presentation.aiInspiration.cancelJob({ jobId })
915
+ * console.log(job.status) // "cancelled" (or a terminal state it already reached)
916
+ * ```
917
+ */
918
+ public abstract cancelJob(
919
+ args: PluginAIInspirationJobArgs,
920
+ ): PluginApiReturn<PluginAIInspirationCancelJobResult>
921
+
922
+ /**
923
+ * List transient AI Inspiration jobs created in the current host session.
924
+ *
925
+ * @returns Jobs with their statuses, newest first.
926
+ *
927
+ * @examplePrompt What AI jobs are running?
928
+ * @examplePrompt Show my generation queue
929
+ *
930
+ * # Example
931
+ * ```ts
932
+ * const { jobs } = await snaptrude.presentation.aiInspiration.listJobs()
933
+ * const running = jobs.filter((j) => j.status === "running" || j.status === "queued")
934
+ * console.log(running.map((j) => `${j.jobId}: ${j.method}`))
935
+ * ```
936
+ */
937
+ public abstract listJobs(): PluginApiReturn<PluginAIInspirationListJobsResult>
938
+
939
+ /**
940
+ * Get the sanitized workflow graph containing a Present shape.
941
+ *
942
+ * @param args - Object containing `shapeId`.
943
+ * @returns The workflow and matching node, or `null` values when the shape is not in a workflow.
944
+ *
945
+ * @examplePrompt Show the generation history of this image
946
+ * @examplePrompt What workflow produced this shape?
947
+ *
948
+ * # Example
949
+ * ```ts
950
+ * const { workflow, node } = await snaptrude.presentation.aiInspiration.getWorkflowForShape({
951
+ * shapeId: selected.shapeId,
952
+ * })
953
+ * if (workflow && node) console.log(node.id, workflow.edgeIds.length, "edges")
954
+ * ```
955
+ */
956
+ public abstract getWorkflowForShape(
957
+ args: PluginAIInspirationGetWorkflowForShapeArgs,
958
+ ): PluginApiReturn<PluginAIInspirationGetWorkflowForShapeResult>
959
+
960
+ /**
961
+ * Build a rerun plan for the selected workflow branch ending at a shape.
962
+ *
963
+ * @param args - Object containing `shapeId`.
964
+ * @returns Ready plan data or an unavailable reason.
965
+ *
966
+ * @examplePrompt Can I rerun the steps that produced this output?
967
+ * @examplePrompt Preview the rerun for this generated image
968
+ *
969
+ * # Example
970
+ * ```ts
971
+ * const plan = await snaptrude.presentation.aiInspiration.getSelectedBranchRerunPlan({
972
+ * shapeId: selected.shapeId,
973
+ * })
974
+ * if (plan.status === "ready") console.log(plan.edges.map((e) => e.operation.label))
975
+ * else console.log("Cannot rerun:", plan.reason)
976
+ * ```
977
+ */
978
+ public abstract getSelectedBranchRerunPlan(
979
+ args: PluginAIInspirationGetWorkflowForShapeArgs,
980
+ ): PluginApiReturn<PluginAIInspirationRerunPlanResult>
981
+
982
+ /**
983
+ * Rerun the selected workflow branch and supersede the previous branch.
984
+ *
985
+ * @param args - Selected shape, optional end frame shape, and run mode.
986
+ * @returns New canvas outputs in blocking mode, or a `jobId` when called with
987
+ * `runMode: "job"`.
988
+ *
989
+ * @examplePrompt Rerun this generation branch
990
+ * @examplePrompt Regenerate this output with the same steps
991
+ *
992
+ * # Example
993
+ * ```ts
994
+ * const { outputs } = await snaptrude.presentation.aiInspiration.rerunSelectedBranch({
995
+ * shapeId: selected.shapeId,
996
+ * })
997
+ * console.log(outputs?.map((o) => o.shapeId))
998
+ * ```
999
+ */
1000
+ public abstract rerunSelectedBranch(
1001
+ args: PluginAIInspirationRerunSelectedBranchArgs,
1002
+ ): PluginApiReturn<PluginAIInspirationRunResult>
1003
+
1004
+ /**
1005
+ * Extract a reusable recipe draft from the workflow path ending at a shape.
1006
+ *
1007
+ * @param args - Object containing `shapeId`.
1008
+ * @returns A recipe draft or an unavailable reason.
1009
+ *
1010
+ * @examplePrompt Turn this workflow into a reusable recipe
1011
+ * @examplePrompt Save the generation steps behind this image
1012
+ *
1013
+ * # Example
1014
+ * ```ts
1015
+ * const extraction = await snaptrude.presentation.aiInspiration.extractRecipeFromShape({
1016
+ * shapeId: selected.shapeId,
1017
+ * })
1018
+ * if (extraction.status === "ready") console.log(extraction.draft.summary)
1019
+ * ```
1020
+ */
1021
+ public abstract extractRecipeFromShape(
1022
+ args: PluginAIInspirationExtractRecipeFromShapeArgs,
1023
+ ): PluginApiReturn<PluginAIInspirationExtractionResult>
1024
+
1025
+ /**
1026
+ * List project-level AI Inspiration recipes stored in Present document metadata.
1027
+ *
1028
+ * @returns Saved project recipes.
1029
+ *
1030
+ * @examplePrompt What AI recipes are saved in this project?
1031
+ * @examplePrompt List my generation recipes
1032
+ *
1033
+ * # Example
1034
+ * ```ts
1035
+ * const { recipes } = await snaptrude.presentation.aiInspiration.listRecipes()
1036
+ * console.log(recipes.map((r) => `${r.name} → ${r.outputKind}`))
1037
+ * ```
1038
+ */
1039
+ public abstract listRecipes(): PluginApiReturn<PluginAIInspirationListRecipesResult>
1040
+
1041
+ /**
1042
+ * Save a project-level AI Inspiration recipe.
1043
+ *
1044
+ * @param args - Recipe draft and desired name.
1045
+ * @returns Saved, duplicate, invalid-name, or failed status.
1046
+ *
1047
+ * @examplePrompt Save this recipe as "Dusk facade render"
1048
+ * @examplePrompt Store these generation steps for reuse
1049
+ *
1050
+ * # Example
1051
+ * ```ts
1052
+ * const extraction = await snaptrude.presentation.aiInspiration.extractRecipeFromShape({
1053
+ * shapeId: selected.shapeId,
1054
+ * })
1055
+ * if (extraction.status === "ready") {
1056
+ * const saved = await snaptrude.presentation.aiInspiration.saveRecipe({
1057
+ * draft: extraction.draft,
1058
+ * name: "Dusk facade render",
1059
+ * })
1060
+ * console.log(saved.status, saved.recipe?.id)
1061
+ * }
1062
+ * ```
1063
+ */
1064
+ public abstract saveRecipe(
1065
+ args: PluginAIInspirationSaveRecipeArgs,
1066
+ ): PluginApiReturn<PluginAIInspirationSaveRecipeResult>
1067
+
1068
+ /**
1069
+ * Delete a project-level AI Inspiration recipe.
1070
+ *
1071
+ * @param args - Object containing `recipeId`.
1072
+ * @returns Whether a recipe was deleted.
1073
+ *
1074
+ * @examplePrompt Delete the facade render recipe
1075
+ * @examplePrompt Remove that saved AI recipe
1076
+ *
1077
+ * # Example
1078
+ * ```ts
1079
+ * const { recipes } = await snaptrude.presentation.aiInspiration.listRecipes()
1080
+ * const stale = recipes.find((r) => r.name === "Old style test")
1081
+ * if (stale) {
1082
+ * const { deleted } = await snaptrude.presentation.aiInspiration.deleteRecipe({ recipeId: stale.id })
1083
+ * console.log(deleted)
1084
+ * }
1085
+ * ```
1086
+ */
1087
+ public abstract deleteRecipe(
1088
+ args: PluginAIInspirationDeleteRecipeArgs,
1089
+ ): PluginApiReturn<PluginAIInspirationDeleteRecipeResult>
1090
+
1091
+ /**
1092
+ * Run a saved or inline recipe against Present canvas slot shapes.
1093
+ *
1094
+ * @param args - Saved `recipeId` or inline `recipe`, slot shape IDs, and run mode.
1095
+ * @returns Canvas outputs in blocking mode, or a `jobId` when called with
1096
+ * `runMode: "job"`.
1097
+ *
1098
+ * @examplePrompt Apply my saved recipe to this image
1099
+ * @examplePrompt Run the dusk-render recipe on the selected view
1100
+ *
1101
+ * # Example
1102
+ * ```ts
1103
+ * const { recipes } = await snaptrude.presentation.aiInspiration.listRecipes()
1104
+ * const recipe = recipes[0]
1105
+ * const { sources } = await snaptrude.presentation.aiInspiration.listSources({})
1106
+ * const { outputs } = await snaptrude.presentation.aiInspiration.runRecipe({
1107
+ * recipeId: recipe.id,
1108
+ * slotShapeIds: { [recipe.slots[0].id]: sources[0].shapeId },
1109
+ * })
1110
+ * console.log(outputs?.map((o) => o.outputUrl))
1111
+ * ```
1112
+ */
1113
+ public abstract runRecipe(
1114
+ args: PluginAIInspirationRunRecipeArgs,
1115
+ ): PluginApiReturn<PluginAIInspirationRunResult>
362
1116
  }