@imgly/plugin-ai-generation-web 0.1.9 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +270 -426
  3. package/dist/__tests__/ActionRegistry.test.d.ts +1 -0
  4. package/dist/__tests__/compactSeparators.test.d.ts +1 -0
  5. package/dist/__tests__/createConfirmationRenderFunction.test.d.ts +1 -0
  6. package/dist/{generation → assets}/getAssetResultForGenerated.d.ts +1 -1
  7. package/dist/{generation → assets}/getAssetResultForPlaceholder.d.ts +1 -1
  8. package/dist/assets/initializeHistoryAssetLibraryEntry.d.ts +7 -0
  9. package/dist/assets/initializeHistoryAssetSource.d.ts +7 -0
  10. package/dist/assets/initializeHistoryCompositeAssetSource.d.ts +11 -0
  11. package/dist/assets/integrateIntoDefaultAssetLibraryEntry.d.ts +8 -0
  12. package/dist/core/ActionRegistry.d.ts +201 -0
  13. package/dist/core/ProviderRegistry.d.ts +40 -0
  14. package/dist/core/constants.d.ts +1 -0
  15. package/dist/{generation → core}/provider.d.ts +38 -58
  16. package/dist/generation/CallbacksRegistry.d.ts +34 -0
  17. package/dist/generation/createGenerateFunction.d.ts +30 -0
  18. package/dist/generation/handleGenerateFromPanel.d.ts +50 -0
  19. package/dist/generation/handleGenerateFromQuickAction.d.ts +56 -0
  20. package/dist/generation/handleGenerationError.d.ts +2 -3
  21. package/dist/index.d.ts +21 -25
  22. package/dist/index.mjs +9 -6
  23. package/dist/index.mjs.map +4 -4
  24. package/dist/{generation/middleware → middleware}/alwaysOnTopMiddleware.d.ts +1 -1
  25. package/dist/{generation/middleware → middleware}/dryRunMiddleware.d.ts +2 -1
  26. package/dist/{generation/middleware → middleware}/editModeMiddleware.d.ts +1 -1
  27. package/dist/{generation/middleware → middleware}/highlightBlocksMiddleware.d.ts +1 -1
  28. package/dist/middleware/lockEditModeMiddleware.d.ts +17 -0
  29. package/dist/{generation/middleware → middleware}/lockMiddleware.d.ts +1 -1
  30. package/dist/middleware/loggingMiddleware.d.ts +6 -0
  31. package/dist/{generation/middleware → middleware}/middleware.d.ts +1 -1
  32. package/dist/{generation/middleware → middleware}/pendingMiddleware.d.ts +3 -3
  33. package/dist/{generation/middleware → middleware}/rateLimitMiddleware.d.ts +1 -1
  34. package/dist/{generation/middleware → middleware}/uploadMiddleware.d.ts +1 -1
  35. package/dist/{generation/openapi → openapi}/getProperties.d.ts +1 -1
  36. package/dist/{generation/openapi → openapi}/renderProperty.d.ts +3 -3
  37. package/dist/{generation/quickAction/consumeGeneratedResult.d.ts → providers/getApplyCallbacks.d.ts} +13 -8
  38. package/dist/providers/getCanvasMenuComponentId.d.ts +3 -0
  39. package/dist/providers/initializeProvider.d.ts +22 -0
  40. package/dist/providers/initializeProviders.d.ts +38 -0
  41. package/dist/types.d.ts +101 -0
  42. package/dist/{common → ui/common}/renderImageUrlProperty.d.ts +1 -1
  43. package/dist/{common → ui/common}/renderStyleTransferProperty.d.ts +1 -1
  44. package/dist/{generation → ui/components}/renderGenerationComponents.d.ts +6 -5
  45. package/dist/ui/panels/createConfirmationRenderFunction.d.ts +16 -0
  46. package/dist/ui/panels/createPanelRenderFunction.d.ts +9 -0
  47. package/dist/ui/panels/createPanelRenderFunctionFromCustom.d.ts +6 -0
  48. package/dist/ui/panels/createPanelRenderFunctionFromSchema.d.ts +9 -0
  49. package/dist/ui/quickActions/createQuickActionMenuRenderFunction.d.ts +13 -0
  50. package/dist/ui/quickActions/getQuickActionOrder.d.ts +12 -0
  51. package/dist/ui/quickActions/initializeQuickActionComponents.d.ts +15 -0
  52. package/dist/ui/quickActions/types.d.ts +10 -0
  53. package/dist/ui/quickActions/utils.d.ts +7 -0
  54. package/dist/utils/checkAiPluginVersion.d.ts +10 -0
  55. package/dist/utils/compactSeparators.d.ts +7 -0
  56. package/dist/utils/lockSelectionToEditMode.d.ts +12 -0
  57. package/dist/{utils.d.ts → utils/utils.d.ts} +6 -1
  58. package/package.json +2 -2
  59. package/dist/generation/generate.d.ts +0 -16
  60. package/dist/generation/initProvider.d.ts +0 -20
  61. package/dist/generation/middleware/loggingMiddleware.d.ts +0 -4
  62. package/dist/generation/quickAction/common/QuickActionBaseButton.d.ts +0 -11
  63. package/dist/generation/quickAction/common/QuickActionBaseLibrary.d.ts +0 -23
  64. package/dist/generation/quickAction/common/QuickActionBasePrompt.d.ts +0 -13
  65. package/dist/generation/quickAction/common/QuickActionBaseSelect.d.ts +0 -28
  66. package/dist/generation/quickAction/common/QuickActionChangeImage.d.ts +0 -17
  67. package/dist/generation/quickAction/common/QuickActionCombineImages.d.ts +0 -17
  68. package/dist/generation/quickAction/common/QuickActionEditTextStyle.d.ts +0 -17
  69. package/dist/generation/quickAction/common/QuickActionImageVariant.d.ts +0 -17
  70. package/dist/generation/quickAction/common/QuickActionSwapImageBackground.d.ts +0 -17
  71. package/dist/generation/quickAction/generate.d.ts +0 -19
  72. package/dist/generation/quickAction/getQuickActionMenu.d.ts +0 -10
  73. package/dist/generation/quickAction/registerQuickActionMenuComponent.d.ts +0 -12
  74. package/dist/generation/quickAction/types.d.ts +0 -25
  75. package/dist/generation/quickAction/utils.d.ts +0 -13
  76. package/dist/generation/registerPanelInputCustom.d.ts +0 -6
  77. package/dist/generation/registerPanelInputSchema.d.ts +0 -9
  78. package/dist/generation/types.d.ts +0 -79
  79. /package/dist/{generation → assets}/previewUri.d.ts +0 -0
  80. /package/dist/{generation/openapi → openapi}/dereferenceDocument.d.ts +0 -0
  81. /package/dist/{generation/openapi → openapi}/isOpenAPISchema.d.ts +0 -0
  82. /package/dist/{generation/openapi → openapi}/types.d.ts +0 -0
  83. /package/dist/{registerDockComponent.d.ts → ui/components/registerDockComponent.d.ts} +0 -0
  84. /package/dist/{icons.d.ts → ui/icons.d.ts} +0 -0
  85. /package/dist/{generation/quickAction/common → ui/quickActions}/enableImageFill.d.ts +0 -0
package/README.md CHANGED
@@ -4,10 +4,15 @@ A powerful toolkit for implementing AI generation providers in CreativeEditor SD
4
4
 
5
5
  ## Overview
6
6
 
7
+ **Note**: This package is only relevant if you need to create new AI providers or extend existing functionality. For simple integration of AI features, use the [@imgly/plugin-ai-apps-web](https://github.com/imgly/plugins/tree/main/packages/plugin-ai-apps-web) package instead.
8
+
7
9
  This package provides the foundation for creating AI generation plugins for CreativeEditor SDK. It offers a standardized interface for implementing AI generation providers that can create images, videos, audio, or text assets. The package includes utilities for handling:
8
10
 
9
- - Provider registration and initialization
10
- - User interface generation
11
+ - Provider registration and initialization
12
+ - User interface generation
13
+ - Global action registry for quick actions and plugin actions
14
+ - Type-safe quick action definitions
15
+ - Cross-plugin action support
11
16
 
12
17
  ## Getting Started
13
18
 
@@ -19,13 +24,13 @@ npm install @imgly/plugin-ai-generation-web
19
24
 
20
25
  ### Creating a Custom Provider
21
26
 
22
- The core of this package is the `Provider` interface which defines the contract for AI generation providers. Before we go into details, here's how to implement a basic provider:
27
+ The core of this package is the `Provider` interface which defines the contract for AI generation providers. Here's how to implement a basic provider:
23
28
 
24
29
  ```typescript
25
30
  import {
26
31
  Provider,
27
32
  ImageOutput,
28
- initProvider,
33
+ initializeProvider,
29
34
  loggingMiddleware,
30
35
  CommonProviderConfiguration
31
36
  } from '@imgly/plugin-ai-generation-web';
@@ -68,18 +73,22 @@ function createMyImageProvider(config: MyProviderConfiguration): Provider<'image
68
73
  })
69
74
  },
70
75
 
71
- // Optional: Quick actions for the quick action (sub)menu in the canvas menu
76
+ // Quick actions supported by this provider
72
77
  quickActions: {
73
- actions: [
74
- {
75
- id: 'enhance-image',
76
- version: '1',
77
- enable: true,
78
- render: (context, quickActionContext) => {
79
- // Render quick action UI
80
- }
78
+ supported: {
79
+ 'ly.img.editImage': {
80
+ mapInput: (input) => ({
81
+ prompt: input.prompt,
82
+ image_url: input.uri
83
+ })
84
+ },
85
+ 'ly.img.styleTransfer': {
86
+ mapInput: (input) => ({
87
+ prompt: input.style,
88
+ image_url: input.uri
89
+ })
81
90
  }
82
- ]
91
+ }
83
92
  }
84
93
  },
85
94
 
@@ -124,7 +133,7 @@ function createMyImageProvider(config: MyProviderConfiguration): Provider<'image
124
133
 
125
134
  // Usage example
126
135
  const myImageProvider = createMyImageProvider({
127
- proxyUrl: 'https://your-api-proxy.example.com',
136
+ proxyUrl: 'http://your-proxy-server.com/api/proxy',
128
137
  headers: {
129
138
  'x-client-version': '1.0.0',
130
139
  'x-request-source': 'cesdk-plugin'
@@ -135,6 +144,35 @@ const myImageProvider = createMyImageProvider({
135
144
  });
136
145
  ```
137
146
 
147
+ ## Action Registry
148
+
149
+ The package includes a global `ActionRegistry` for managing quick actions and plugin actions. To register a new action:
150
+
151
+ ```typescript
152
+ import { ActionRegistry } from '@imgly/plugin-ai-generation-web';
153
+
154
+ // Get the global registry instance
155
+ const registry = ActionRegistry.get();
156
+
157
+ // Register a quick action
158
+ const unregister = registry.register({
159
+ id: 'my-quick-action',
160
+ type: 'quick',
161
+ kind: 'image',
162
+ label: 'My Quick Action',
163
+ enable: true,
164
+ render: (context) => {
165
+ // Render the quick action UI
166
+ context.builder.Button('my-button', {
167
+ label: 'Generate',
168
+ onClick: async () => {
169
+ await context.generate({ prompt: 'Hello world' });
170
+ }
171
+ });
172
+ }
173
+ });
174
+ ```
175
+
138
176
  ## Provider Interface
139
177
 
140
178
  The Provider interface is generic and type-safe, supporting four output kinds:
@@ -173,7 +211,7 @@ The `headers` property allows you to include custom HTTP headers in all API requ
173
211
  - Passing through metadata required by your API
174
212
  - Adding correlation IDs for request tracing
175
213
 
176
- **Implementation Note:** When implementing your provider's `generate` function, ensure you merge the custom headers with any required headers for your API. For example:
214
+ **Implementation Note:** When implementing your provider's `generate` function, ensure you merge the custom headers with any required headers for your API:
177
215
 
178
216
  ```typescript
179
217
  // In your generate function
@@ -188,39 +226,25 @@ const response = await fetch(apiUrl, {
188
226
  });
189
227
  ```
190
228
 
191
- Example provider configuration:
192
-
193
- ```typescript
194
- const myProvider = createMyProvider({
195
- proxyUrl: 'https://api.example.com',
196
- headers: {
197
- 'x-client-version': '1.0.0',
198
- 'x-request-source': 'cesdk-plugin'
199
- },
200
- debug: false,
201
- middleware: [loggingMiddleware()]
202
- });
203
- ```
204
-
205
229
  ### Key Provider Options
206
230
 
207
- - **id**: Unique identifier for your provider
208
- - **kind**: Type of asset generated ('image', 'video', 'audio', 'text')
209
- - **name**: Optional human-readable name
210
- - **initialize**: Setup function called when the provider is loaded
211
- - **input**: Configuration for input UI and parameters
212
- - **output**: Configuration for generation and result handling
231
+ - **id**: Unique identifier for your provider
232
+ - **kind**: Type of asset generated ('image', 'video', 'audio', 'text')
233
+ - **name**: Optional human-readable name
234
+ - **initialize**: Setup function called when the provider is loaded
235
+ - **input**: Configuration for input UI and parameters
236
+ - **output**: Configuration for generation and result handling
213
237
 
214
238
  #### Provider Output Options
215
239
 
216
240
  The `output` property has several important options:
217
241
 
218
- - **generate**: Main function that performs the actual generation
219
- - **history**: Asset storage strategy ('false', '@imgly/local', '@imgly/indexedDB', or custom ID)
220
- - **abortable**: Whether generation can be cancelled by the user
221
- - **middleware**: Array of middleware functions for pre/post-processing
222
- - **notification**: Success and error notification configuration
223
- - **generationHintText**: Text to display below the generation button
242
+ - **generate**: Main function that performs the actual generation
243
+ - **history**: Asset storage strategy ('false', '@imgly/local', '@imgly/indexedDB', or custom ID)
244
+ - **abortable**: Whether generation can be cancelled by the user
245
+ - **middleware**: Array of middleware functions for pre/post-processing
246
+ - **notification**: Success and error notification configuration
247
+ - **generationHintText**: Text to display below the generation button
224
248
 
225
249
  ##### Notification Configuration
226
250
 
@@ -265,7 +289,7 @@ generate: async (input, options) => {
265
289
  return { kind: 'image', url: result.url };
266
290
  }
267
291
 
268
- // Streaming response (right now only supported for text)
292
+ // Streaming response (currently only supported for text)
269
293
  generate: async function* (input, options) {
270
294
  const stream = api.streamGenerationResult(input);
271
295
 
@@ -277,7 +301,7 @@ generate: async function* (input, options) {
277
301
  }
278
302
 
279
303
  // Return final result
280
- return { kind: 'text', url: inferredText };
304
+ return { kind: 'text', text: inferredText };
281
305
  }
282
306
  ```
283
307
 
@@ -317,7 +341,7 @@ input: {
317
341
  imageUrl: (context, property) => {
318
342
  const valueState = context.state('imageUrl', '');
319
343
  context.builder.TextInput('imageUrl', {
320
- label: 'Image URL',
344
+ inputLabel: 'Image URL',
321
345
  ...valueState
322
346
  });
323
347
 
@@ -367,16 +391,16 @@ input: {
367
391
 
368
392
  #### Benefits of Schema-based Input
369
393
 
370
- - Built-in validation based on schema constraints
371
- - AI provider like fal.ai provide schemas for their models
372
- - Automatic UI component generation based on property types
373
- - Extensions like `x-imgly-builder` to specify component types
374
- - Property ordering via `orderExtensionKeyword`
375
- - Customizable property rendering with `renderCustomProperty`
394
+ - Built-in validation based on schema constraints
395
+ - AI providers like fal.ai provide schemas for their models
396
+ - Automatic UI component generation based on property types
397
+ - Extensions like `x-imgly-builder` to specify component types
398
+ - Property ordering via `orderExtensionKeyword`
399
+ - Customizable property rendering with `renderCustomProperty`
376
400
 
377
401
  ### 2. Custom Input Panels
378
402
 
379
- The `custom` type gives you complete control over UI components.
403
+ The `custom` type gives you complete control over UI components. For more details on how to build custom panels and see all available builder components, refer to the [Create a Custom Panel](https://img.ly/docs/cesdk/js/user-interface/ui-extensions/create-custom-panel-d87b83/) guide.
380
404
 
381
405
  ```typescript
382
406
  input: {
@@ -386,14 +410,14 @@ input: {
386
410
  // Use the builder pattern to create UI components
387
411
  const promptState = context.state('prompt', '');
388
412
  context.builder.TextArea('prompt', {
389
- label: 'Prompt',
413
+ inputLabel: 'Prompt',
390
414
  ...promptState
391
415
  });
392
416
 
393
417
  // Set up width selection
394
418
  const widthState = context.state('width', 1024);
395
419
  context.builder.Select('width', {
396
- label: 'Width',
420
+ inputLabel: 'Width',
397
421
  options: [
398
422
  { value: 512, label: '512px' },
399
423
  { value: 1024, label: '1024px' },
@@ -425,9 +449,9 @@ input: {
425
449
 
426
450
  #### Benefits of Custom Input Panels
427
451
 
428
- - Complete control over UI components and layout
429
- - Complex logic between fields (dependencies, conditionals)
430
- - Dynamic UI that changes based on user interactions
452
+ - Complete control over UI components and layout
453
+ - Complex logic between fields (dependencies, conditionals)
454
+ - Dynamic UI that changes based on user interactions
431
455
 
432
456
  #### Panel User Flow Options
433
457
 
@@ -446,12 +470,11 @@ panel: {
446
470
  }
447
471
  ```
448
472
 
449
- - **userFlow**:
450
-
451
- - `placeholder`: Creates a block as a placeholder with loading state when generation starts
452
- - `generation-only`: Only triggers generation without creating a placeholder
473
+ - **userFlow**:
474
+ - `placeholder`: Creates a block as a placeholder with loading state when generation starts
475
+ - `generation-only`: Only triggers generation without creating a placeholder
453
476
 
454
- - **includeHistoryLibrary**: Controls whether the history library is shown in the panel
477
+ - **includeHistoryLibrary**: Controls whether the history library is shown in the panel
455
478
 
456
479
  ## The `getBlockInput` Function
457
480
 
@@ -459,9 +482,9 @@ The `getBlockInput` function is crucial for both panel types. It converts your i
459
482
 
460
483
  ### What It Does
461
484
 
462
- - Defines dimensions, duration, and appearance of asset blocks
463
- - Creates placeholders before generation completes
464
- - Maps your AI provider's inputs to standardized block parameters
485
+ - Defines dimensions, duration, and appearance of asset blocks
486
+ - Creates placeholders before generation completes
487
+ - Maps your AI provider's inputs to standardized block parameters
465
488
 
466
489
  ### Required Return Values by Output Kind
467
490
 
@@ -519,348 +542,152 @@ getBlockInput: async (input) => ({
519
542
 
520
543
  Quick Actions provide context-aware AI generation capabilities directly in CreativeEditor SDK's canvas menu. Unlike panels (which appear in the side panel), quick actions appear when users select elements on the canvas.
521
544
 
522
- Instead of adding a single button for every different generation provider, a single quick action menu is registered and used by all providers. This allows users to select the desired action without cluttering the UI.
545
+ ### Available Quick Action IDs
523
546
 
524
- ### Purpose of Quick Actions
547
+ Here are all the quick action IDs that can be used in the `supported` field of your provider configuration:
525
548
 
526
- - **Context-Aware**: Operate on selected blocks in the canvas
527
- - **Streamlined Workflow**: Allow users to apply AI transformations without switching to a panel
528
- - **Immediate Feedback**: Provide quick access to common AI operations
529
- - **In-Canvas Experience**: Keep users in their creative workflow
549
+ #### Image Quick Actions
530
550
 
531
- ### Quick Action Structure
551
+ - **`ly.img.artistTransfer`**: Transform image in the style of famous artists
552
+ - Input: `{ artist: string, uri: string }`
532
553
 
533
- ```typescript
534
- quickActions: {
535
- actions: [
536
- {
537
- // Unique identifier
538
- id: 'enhance-image',
554
+ - **`ly.img.combineImages`**: Combine multiple images with instructions
555
+ - Input: `{ prompt: string, uris: string[], exportFromBlockIds: number[] }`
539
556
 
540
- // Version for compatibility
541
- version: '1',
557
+ - **`ly.img.createVariant`**: Create a variation of the image
558
+ - Input: `{ prompt: string, uri: string }`
542
559
 
543
- // Enable/disable based on condition
544
- // E.g., you should check for the correct block type here.
545
- enable: true, // or a function: (context) => boolean
560
+ - **`ly.img.editImage`**: Change image based on description
561
+ - Input: `{ prompt: string, uri: string }`
546
562
 
547
- // Optional scope requirements
548
- scopes: ['text.edit'],
563
+ - **`ly.img.remixPage`**: Convert the page into a single image
564
+ - Input: `{ prompt: string, uri: string }`
549
565
 
550
- // Optional confirmation after generation
551
- confirmation: true,
566
+ - **`ly.img.remixPageWithPrompt`**: Remix the page with custom instructions
567
+ - Input: `{ prompt: string, uri: string }`
552
568
 
553
- // Prevent selection changes during confirmation
554
- lockDuringConfirmation: true,
569
+ - **`ly.img.styleTransfer`**: Transform image into different art styles
570
+ - Input: `{ style: string, uri: string }`
555
571
 
556
- // Basic menu item rendering
557
- render: (context, quickActionContext) => {
558
- // Add button to quick action menu
559
- },
572
+ - **`ly.img.swapBackground`**: Change the background of the image
573
+ - Input: `{ prompt: string, uri: string }`
560
574
 
561
- // Optional expanded mode rendering
562
- renderExpanded: (context, quickActionContext) => {
563
- // Render more complex interface
564
- }
565
- }
566
- ];
567
- }
568
- ```
575
+ - **`ly.img.gpt-image-1.changeStyleLibrary`**: Apply different art styles (GPT-specific)
576
+ - Input: `{ prompt: string, uri: string }`
569
577
 
570
- ### Quick Action Helper Components
578
+ #### Text Quick Actions
571
579
 
572
- The package provides several helper components for common quick action patterns:
580
+ - **`ly.img.changeTextTo`**: Change text to a different format or style
581
+ - Input: `{ prompt: string, customPrompt: string }`
573
582
 
574
- #### 1. QuickActionBaseButton
583
+ - **`ly.img.changeTone`**: Change the tone of the text
584
+ - Input: `{ prompt: string, type: string }`
575
585
 
576
- A simple button that triggers an action when clicked:
586
+ - **`ly.img.fix`**: Fix spelling and grammar
587
+ - Input: `{ prompt: string }`
577
588
 
578
- ```typescript
579
- import { QuickActionBaseButton } from '@imgly/plugin-ai-generation-web';
589
+ - **`ly.img.improve`**: Improve writing quality
590
+ - Input: `{ prompt: string }`
580
591
 
581
- const quickAction = QuickActionBaseButton<MyInput, ImageOutput>({
582
- quickAction: {
583
- id: 'enhanceImage',
584
- version: '1',
585
- enable: true
586
- },
587
- buttonOptions: {
588
- icon: '@imgly/MagicWand'
589
- },
590
- onClick: async (context) => {
591
- await context.generate({
592
- prompt: 'Enhance this image and improve quality'
593
- });
594
- }
595
- });
596
- ```
592
+ - **`ly.img.longer`**: Make text longer
593
+ - Input: `{ prompt: string }`
597
594
 
598
- #### 2. QuickActionBasePrompt
595
+ - **`ly.img.shorter`**: Make text shorter
596
+ - Input: `{ prompt: string }`
599
597
 
600
- A button that expands to show a text prompt input:
598
+ - **`ly.img.translate`**: Translate text to different languages
599
+ - Input: `{ prompt: string, language: string }`
601
600
 
602
- ```typescript
603
- import { QuickActionBasePrompt } from '@imgly/plugin-ai-generation-web';
601
+ #### Video Quick Actions
604
602
 
605
- const quickAction = QuickActionBasePrompt<MyInput, ImageOutput>({
606
- quickAction: {
607
- id: 'changeImage',
608
- version: '1',
609
- enable: true,
610
- confirmation: true
611
- },
612
- buttonOptions: {
613
- icon: '@imgly/Edit'
614
- },
615
- textAreaOptions: {
616
- placeholder: 'Describe the changes you want...'
617
- },
618
- onApply: async (prompt, context) => {
619
- return context.generate({
620
- prompt: prompt,
621
- // other parameters
622
- });
623
- }
624
- });
625
- ```
603
+ - **`ly.img.createVideo`**: Opens the image2video generation panel with the current image
604
+ - Input: `{ uri: string }`
626
605
 
627
- #### 3. QuickActionBaseSelect
606
+ ### Provider Quick Action Support
628
607
 
629
- A button that opens a menu with selectable options:
608
+ Providers declare which quick actions they support and how to map quick action inputs to provider inputs:
630
609
 
631
610
  ```typescript
632
- import { QuickActionBaseSelect } from '@imgly/plugin-ai-generation-web';
633
-
634
- const quickAction = QuickActionBaseSelect<MyInput, ImageOutput>({
635
- cesdk: cesdk,
636
- quickAction: {
637
- id: 'styleTransfer',
638
- version: '1',
639
- enable: true,
640
- confirmation: true
641
- },
642
- buttonOptions: {
643
- icon: '@imgly/Appearance'
644
- },
645
- items: [
646
- {
647
- id: 'water',
648
- label: 'Watercolor Painting',
649
- prompt: 'Convert to watercolor painting.'
650
- },
651
- {
652
- id: 'oil',
653
- label: 'Oil Painting',
654
- prompt: 'Render in oil painting style.'
611
+ const myProvider = {
612
+ // ... other provider config
613
+ input: {
614
+ // ... panel config
615
+ quickActions: {
616
+ supported: {
617
+ 'ly.img.editImage': {
618
+ mapInput: (quickActionInput) => ({
619
+ prompt: quickActionInput.prompt,
620
+ image_url: quickActionInput.uri
621
+ })
622
+ },
623
+ 'ly.img.styleTransfer': {
624
+ mapInput: (quickActionInput) => ({
625
+ style: quickActionInput.style,
626
+ image_url: quickActionInput.uri
627
+ })
628
+ }
629
+ }
630
+ }
655
631
  }
656
- ],
657
- mapInput: (input) => ({
658
- prompt: input.item.prompt,
659
- image_url: input.uri
660
- })
661
- });
662
- ```
663
-
664
- ### Ready-to-Use Image Quick Actions
665
-
666
- The package includes several ready-to-use quick actions for common image manipulation tasks:
667
-
668
- #### 1. QuickActionChangeImage
669
-
670
- Changes an image based on a text prompt:
671
-
672
- ```typescript
673
- import { QuickActionChangeImage } from '@imgly/plugin-ai-generation-web';
674
-
675
- const changeImageAction = QuickActionChangeImage<MyInput, ImageOutput>({
676
- cesdk: cesdk,
677
- mapInput: (input) => ({
678
- prompt: input.prompt,
679
- image_url: input.uri
680
- })
681
- });
682
- ```
683
-
684
- #### 2. QuickActionSwapImageBackground
685
-
686
- Changes just the background of an image:
687
-
688
- ```typescript
689
- import { QuickActionSwapImageBackground } from '@imgly/plugin-ai-generation-web';
690
-
691
- const swapBackgroundAction = QuickActionSwapImageBackground<MyInput, ImageOutput>({
692
- cesdk: cesdk,
693
- mapInput: (input) => ({
694
- prompt: input.prompt,
695
- image_url: input.uri
696
- })
697
- });
698
- ```
699
-
700
- #### 3. QuickActionImageVariant
701
-
702
- Creates a variant of an image by duplicating it first:
703
-
704
- ```typescript
705
- import { QuickActionImageVariant } from '@imgly/plugin-ai-generation-web';
706
-
707
- const imageVariantAction = QuickActionImageVariant<MyInput, ImageOutput>({
708
- cesdk: cesdk,
709
- onApply: async ({ prompt, uri, duplicatedBlockId }, context) => {
710
- return context.generate(
711
- {
712
- prompt,
713
- image_url: uri
714
- },
715
- {
716
- blockIds: [duplicatedBlockId]
717
- }
718
- );
719
- }
720
- });
632
+ };
721
633
  ```
722
634
 
723
- ### Simple Quick Action Example
635
+ ### Quick Action Expanded View
724
636
 
725
- ```typescript
726
- {
727
- id: 'enhance-image',
728
- version: '1',
729
- enable: true,
730
- render: ({ builder }, { generate, closeMenu }) => {
731
- builder.Button('enhance', {
732
- label: 'Enhance Image',
733
- icon: '@imgly/MagicWand',
734
- onClick: async () => {
735
- // Generate with fixed parameters
736
- await generate({
737
- prompt: 'Enhance this image and improve quality'
738
- });
739
- closeMenu();
740
- }
741
- });
742
- }
743
- }
744
- ```
637
+ Quick actions can have two rendering modes:
745
638
 
746
- ### Quick Action with Expanded Menu
639
+ 1. **Collapsed View**: Shows as a simple button in the quick action menu alongside other actions
640
+ 2. **Expanded View**: Takes over the entire menu space, hiding other actions while the user interacts with this specific action
747
641
 
748
- This example shows how to create a quick action that expands into a more complex UI with input fields. During expansion, the content of the complete menu is replaced with the `renderExpanded` function.
642
+ The expanded view is useful for quick actions that need user input (like text prompts). When a quick action is expanded, the complete menu is replaced with the expanded interface, and other menu items are not shown until the user either completes the action or cancels back to the collapsed view.
749
643
 
750
644
  ```typescript
751
- {
752
- id: 'change-image',
753
- version: '1',
754
- enable: true,
755
- render: ({ builder }, { toggleExpand }) => {
756
- // Render basic button that expands to complex UI
757
- builder.Button('change', {
758
- label: 'Change Image',
759
- icon: '@imgly/Edit',
760
- onClick: toggleExpand // Switch to expanded view
761
- });
762
- },
763
- renderExpanded: ({ builder, state }, { generate, toggleExpand }) => {
764
- // Create more complex UI with input fields
765
- const promptState = state('prompt', '');
766
-
767
- builder.TextArea('prompt', {
768
- label: 'Prompt',
769
- placeholder: 'Describe the changes you want...',
770
- ...promptState
771
- });
772
-
773
- builder.Separator('separator');
774
-
775
- // Add footer with cancel/apply buttons
776
- builder.ButtonRow('footer', {
777
- children: () => {
778
- builder.Button('cancel', {
779
- label: 'Back',
780
- onClick: toggleExpand // Return to basic view
781
- });
782
-
783
- builder.Button('apply', {
784
- label: 'Generate',
785
- color: 'accent',
786
- onClick: async () => {
787
- await generate({
788
- prompt: promptState.value
789
- });
790
- toggleExpand(); // Close expanded view after generation
791
- }
645
+ render: ({ builder, isExpanded, toggleExpand }) => {
646
+ if (isExpanded) {
647
+ // Expanded view - takes over the entire menu
648
+ builder.TextArea('prompt', { /* input fields */ });
649
+ builder.ButtonRow('actions', { /* confirm/cancel buttons */ });
650
+ } else {
651
+ // Collapsed view - simple button alongside other actions
652
+ builder.Button('expand', {
653
+ label: 'Edit Image...',
654
+ onClick: toggleExpand
792
655
  });
793
- }
794
- });
795
- }
656
+ }
796
657
  }
797
658
  ```
798
659
 
799
- ### Quick Action Context
800
-
801
- The `quickActionContext` parameter gives you access to:
802
-
803
- - **blockIds**: Array of currently selected block IDs
804
- - **closeMenu**: Function to close the quick action menu
805
- - **toggleExpand**: Function to toggle between basic and expanded views
806
- - **generate**: Function to trigger generation with input parameters
807
- - **handleGenerationError**: Function to handle and display generation errors
808
-
809
- ### Key Use Cases
810
-
811
- 1. **One-Click Actions**: Simple transformations with predefined parameters
812
- 2. **Context-Aware Generation**: Using properties of selected blocks as inputs
813
- 3. **Multi-Step Workflows**: Expanded UIs for complex generation tasks
814
- 4. **Block Manipulation**: Applying AI-generated content to existing blocks
815
- 5. **Visual Selection**: Displaying visual options that apply different styles
816
-
817
- ### Quick Action vs Panel: When to Use Each
818
-
819
- **Use Quick Actions when:**
820
-
821
- - The operation is context-dependent on selected blocks
822
- - The operation is commonly used and benefits from quick access
823
- - The input requirements are simple or can be preset
824
- - The action works directly with content already on the canvas
825
-
826
- **Use Panels when:**
827
-
828
- - The operation requires complex input forms
829
- - The generation is independent of canvas selections
830
- - Users need to browse a history of generated assets
831
- - The operation creates entirely new content rather than modifying existing content
832
-
833
660
  ## Using Your Provider
834
661
 
835
- Once you've created your provider, you need to initialize it with CreativeEditor SDK and integrate it into the UI. This section covers how to use your provider effectively.
662
+ Once you've created your provider, you need to initialize it with CreativeEditor SDK and integrate it into the UI.
836
663
 
837
664
  ### Initializing Your Provider
838
665
 
839
- The most basic way is to use the `initProvider` function to register your provider with CreativeEditor SDK:
666
+ Use the `initializeProvider` function to register your provider:
840
667
 
841
668
  ```typescript
842
- import { initProvider } from '@imgly/plugin-ai-generation-web';
669
+ import { initializeProvider } from '@imgly/plugin-ai-generation-web';
843
670
 
844
- // Create your provider with custom headers
671
+ // Create your provider
845
672
  const myProvider = createMyProvider({
846
- proxyUrl: 'https://your-api-proxy.example.com',
673
+ proxyUrl: 'http://your-proxy-server.com/api/proxy',
847
674
  headers: {
848
675
  'x-custom-header': 'value',
849
676
  'x-client-version': '1.0.0'
850
677
  }
851
678
  });
852
679
 
853
- // Initialize the provider with CreativeEditor SDK
680
+ // Initialize the provider
854
681
  function setupMyProvider(cesdk) {
855
- const result = initProvider(
682
+ const result = initializeProvider(
856
683
  myProvider,
857
684
  {
858
685
  engine: cesdk.engine,
859
686
  cesdk
860
687
  },
861
688
  {
862
- debug: false, // Enable/disable debug logging
863
- dryRun: false // Enable/disable dry run mode (no actual API calls)
689
+ debug: false,
690
+ dryRun: false
864
691
  }
865
692
  );
866
693
 
@@ -868,22 +695,17 @@ function setupMyProvider(cesdk) {
868
695
  }
869
696
  ```
870
697
 
871
- Now you can render the provider's UI components in your application. The `initProvider` function takes care of registering the provider with CreativeEditor SDK and setting up the necessary UI components (see the next section for the ids of the panel).
872
-
873
- Alternatively, the `initProvider` function returns an object with `renderBuilderFunctions` which contains render functions that can be used to create custom UI.
874
-
875
698
  ### Panel IDs and Registration
876
699
 
877
- When a provider is initialized, it automatically registers panels with specific IDs. These panel IDs follow a consistent pattern:
700
+ When a provider is initialized, it automatically registers panels with specific IDs:
878
701
 
879
702
  ```
880
- ly.img.ai/{provider-id}
703
+ ly.img.ai.{provider-id}
881
704
  ```
882
705
 
883
706
  For example:
884
-
885
- - A provider with ID `my-image-provider` registers a panel with ID `ly.img.ai/my-image-provider`
886
- - A provider with ID `fal-ai/recraft-v3` registers a panel with ID `ly.img.ai/fal-ai/recraft-v3`
707
+ - A provider with ID `my-image-provider` registers a panel with ID `ly.img.ai.my-image-provider`
708
+ - A provider with ID `fal-ai/recraft-v3` registers a panel with ID `ly.img.ai.fal-ai/recraft-v3`
887
709
 
888
710
  You can programmatically get a panel ID using the `getPanelId` function:
889
711
 
@@ -891,35 +713,29 @@ You can programmatically get a panel ID using the `getPanelId` function:
891
713
  import { getPanelId } from '@imgly/plugin-ai-generation-web';
892
714
 
893
715
  // Get panel ID for a provider
894
- const panelId = getPanelId('my-image-provider'); // returns "ly.img.ai/my-image-provider"
716
+ const panelId = getPanelId('my-image-provider');
895
717
 
896
718
  // Open the panel
897
719
  cesdk.ui.openPanel(panelId);
898
720
  ```
899
721
 
900
- For quick actions in the canvas menu, the following format is used:
722
+ ### Quick Action Menu Registration
723
+
724
+ Quick actions are automatically registered in canvas menus with these IDs:
901
725
 
902
726
  ```
903
727
  ly.img.ai.{kind}.canvasMenu
904
728
  ```
905
729
 
906
730
  For example:
907
-
908
- - Image quick actions: `ly.img.ai.image.canvasMenu`
909
- - Video quick actions: `ly.img.ai.video.canvasMenu`
910
- - Audio quick actions: `ly.img.ai.audio.canvasMenu`
911
- - Text quick actions: `ly.img.ai.text.canvasMenu`
731
+ - Image quick actions: `ly.img.ai.image.canvasMenu`
732
+ - Video quick actions: `ly.img.ai.video.canvasMenu`
733
+ - Audio quick actions: `ly.img.ai.audio.canvasMenu`
734
+ - Text quick actions: `ly.img.ai.text.canvasMenu`
912
735
 
913
736
  ### Using with Existing AI Generation Plugins
914
737
 
915
- IMG.LY offers several pre-built AI generation packages that contain a few popular providers as well as combining different models for the same `kind`, e.g. to combine text2image and image2image models in a single panel.
916
-
917
- - `@imgly/plugin-ai-image-generation-web`: For image generation
918
- - `@imgly/plugin-ai-video-generation-web`: For video generation
919
- - `@imgly/plugin-ai-audio-generation-web`: For audio generation
920
- - `@imgly/plugin-ai-text-generation-web`: For text generation
921
-
922
- You can use these packages with different AI provider implementations:
738
+ IMG.LY offers several pre-built AI generation packages that work with this base plugin:
923
739
 
924
740
  ```typescript
925
741
  import CreativeEditorSDK from '@cesdk/cesdk-js';
@@ -929,36 +745,23 @@ import ImageGeneration from '@imgly/plugin-ai-image-generation-web';
929
745
  import FalAiImage from '@imgly/plugin-ai-image-generation-web/fal-ai';
930
746
  import VideoGeneration from '@imgly/plugin-ai-video-generation-web';
931
747
  import FalAiVideo from '@imgly/plugin-ai-video-generation-web/fal-ai';
932
- import AudioGeneration from '@imgly/plugin-ai-audio-generation-web';
933
- import Elevenlabs from '@imgly/plugin-ai-audio-generation-web/elevenlabs';
934
- import TextGeneration from '@imgly/plugin-ai-text-generation-web';
935
- import Anthropic from '@imgly/plugin-ai-text-generation-web/anthropic';
936
748
 
937
749
  // Initialize CreativeEditor SDK
938
750
  CreativeEditorSDK.create(domElement, {
939
751
  license: 'your-license-key'
940
- // Other configuration options...
941
752
  }).then(async (cesdk) => {
942
753
  // Add default asset sources
943
754
  await cesdk.addDefaultAssetSources();
944
755
 
945
- // Text generation with Anthropic
946
- cesdk.addPlugin(
947
- TextGeneration({
948
- provider: Anthropic.AnthropicProvider({
949
- proxyUrl: 'https://your-anthropic-proxy.example.com'
950
- })
951
- })
952
- );
953
-
954
756
  // Image generation with Fal.ai models
955
757
  cesdk.addPlugin(
956
758
  ImageGeneration({
957
759
  text2image: FalAiImage.RecraftV3({
958
- proxyUrl: 'https://your-falai-proxy.example.com'
760
+ proxyUrl: 'http://your-proxy-server.com/api/proxy'
959
761
  }),
762
+ // Alternative: FalAiImage.Recraft20b({ proxyUrl: 'http://your-proxy-server.com/api/proxy' }),
960
763
  image2image: FalAiImage.GeminiFlashEdit({
961
- proxyUrl: 'https://your-falai-proxy.example.com'
764
+ proxyUrl: 'http://your-proxy-server.com/api/proxy'
962
765
  })
963
766
  })
964
767
  );
@@ -967,30 +770,15 @@ CreativeEditorSDK.create(domElement, {
967
770
  cesdk.addPlugin(
968
771
  VideoGeneration({
969
772
  text2video: FalAiVideo.MinimaxVideo01Live({
970
- proxyUrl: 'https://your-falai-proxy.example.com'
971
- }),
972
- image2video: FalAiVideo.MinimaxVideo01LiveImageToVideo({
973
- proxyUrl: 'https://your-falai-proxy.example.com'
974
- })
975
- })
976
- );
977
-
978
- // Audio generation
979
- cesdk.addPlugin(
980
- AudioGeneration({
981
- text2speech: Elevenlabs.ElevenMultilingualV2({
982
- proxyUrl: 'https://your-elevenlabs-proxy.example.com'
983
- }),
984
- text2sound: Elevenlabs.ElevenSoundEffects({
985
- proxyUrl: 'https://your-elevenlabs-proxy.example.com'
773
+ proxyUrl: 'http://your-proxy-server.com/api/proxy'
986
774
  })
987
775
  })
988
776
  );
989
777
 
990
- // Add the quick action menu to the canvas menu
778
+ // Add quick action menus to canvas
991
779
  cesdk.ui.setCanvasMenuOrder([
992
- 'ly.img.ai.text.canvasMenu',
993
780
  'ly.img.ai.image.canvasMenu',
781
+ 'ly.img.ai.video.canvasMenu',
994
782
  ...cesdk.ui.getCanvasMenuOrder()
995
783
  ]);
996
784
  });
@@ -1005,11 +793,6 @@ The package includes a middleware system to augment the generation flow:
1005
793
  #### Rate Limiting Middleware
1006
794
 
1007
795
  ```typescript
1008
- // NOTE:: This middleware will not protect against calling the server directly as
1009
- // many times as you want. It is only meant to be used for rate-limiting the UI before it
1010
- // hits the server.
1011
- // Always secure your API endpoints with authentication and authorization or server-side
1012
- // rate-limiting.
1013
796
  import { rateLimitMiddleware } from '@imgly/plugin-ai-generation-web';
1014
797
 
1015
798
  // Create a rate limiting middleware
@@ -1034,19 +817,16 @@ const provider = {
1034
817
  };
1035
818
  ```
1036
819
 
1037
- #### Upload Middleware
820
+ **Note**: This middleware provides client-side rate limiting for UI purposes only. Always implement proper server-side rate limiting and authentication for production APIs.
1038
821
 
1039
- The `uploadMiddleware` allows you to upload the output of a generation process to a server or cloud storage before it's returned to the user. This is useful when:
822
+ #### Upload Middleware
1040
823
 
1041
- - You need to store generated content on your own servers
1042
- - You want to process or transform the content before it's used
1043
- - You need to handle licensing or attribution for the generated content
1044
- - You need to apply additional validation or security checks
824
+ The `uploadMiddleware` allows you to upload generated content to your own servers:
1045
825
 
1046
826
  ```typescript
1047
827
  import { uploadMiddleware } from '@imgly/plugin-ai-generation-web';
1048
828
 
1049
- // Create an upload middleware with your custom upload function
829
+ // Create an upload middleware
1050
830
  const upload = uploadMiddleware(async (output) => {
1051
831
  // Upload the output to your server/storage
1052
832
  const response = await fetch('https://your-api.example.com/upload', {
@@ -1055,10 +835,9 @@ const upload = uploadMiddleware(async (output) => {
1055
835
  body: JSON.stringify(output)
1056
836
  });
1057
837
 
1058
- // Get the response which should include the new URL
1059
838
  const result = await response.json();
1060
839
 
1061
- // Return the output with the updated URL from your server
840
+ // Return the output with the updated URL
1062
841
  return {
1063
842
  ...output,
1064
843
  url: result.url
@@ -1075,12 +854,77 @@ const provider = {
1075
854
  };
1076
855
  ```
1077
856
 
1078
- **Important notes about uploadMiddleware:**
1079
- - It automatically detects and skips async generators (streaming results)
1080
- - For non-streaming results, it awaits the upload function and returns the updated output
1081
- - The upload function should return the same type of output object (but with modified properties like URL)
1082
- - You can chain it with other middleware functions
857
+ ### Provider Registry
858
+
859
+ The `ProviderRegistry` is a global singleton that manages all registered providers:
860
+
861
+ ```typescript
862
+ import { ProviderRegistry } from '@imgly/plugin-ai-generation-web';
863
+
864
+ // Get the global registry
865
+ const registry = ProviderRegistry.get();
866
+
867
+ // Get all registered providers
868
+ const allProviders = registry.getAll();
869
+
870
+ // Get providers by kind
871
+ const imageProviders = registry.getByKind('image');
872
+
873
+ // Find a specific provider
874
+ const myProvider = registry.getById('my-provider-id');
875
+ ```
1083
876
 
1084
877
  ## TypeScript Support
1085
878
 
1086
- This package is fully typed with TypeScript, providing excellent IntelliSense support during development.
879
+ This package is fully typed with TypeScript, providing excellent IntelliSense support during development:
880
+
881
+ - **Generic Provider Types**: Strongly typed providers with input/output validation
882
+ - **Quick Action Types**: Type-safe quick action definitions with proper input mapping
883
+ - **Registry Types**: Fully typed action and provider registries
884
+ - **Middleware Types**: Typed middleware functions for better composition
885
+
886
+ ## API Reference
887
+
888
+ ### Core Exports
889
+
890
+ ```typescript
891
+ // Provider types and interfaces
892
+ export { Provider, ImageOutput, VideoOutput, AudioOutput, TextOutput } from './core/provider';
893
+
894
+ // Action registry
895
+ export { ActionRegistry, QuickActionDefinition, PluginActionDefinition } from './core/ActionRegistry';
896
+
897
+ // Provider registry
898
+ export { ProviderRegistry } from './core/ProviderRegistry';
899
+
900
+ // Initialization functions
901
+ export { initializeProvider, initializeProviders } from './providers/';
902
+
903
+ // Middleware
904
+ export { loggingMiddleware, rateLimitMiddleware, uploadMiddleware } from './middleware/';
905
+
906
+ // Utilities
907
+ export { getPanelId, enableQuickActionForImageFill } from './utils/';
908
+ ```
909
+
910
+ ### Common Types
911
+
912
+ ```typescript
913
+ // Provider configuration
914
+ interface CommonProviderConfiguration<I, O extends Output> {
915
+ proxyUrl: string;
916
+ debug?: boolean;
917
+ middleware?: Middleware<I, O>[];
918
+ headers?: Record<string, string>;
919
+ }
920
+
921
+ // Quick action definition
922
+ interface QuickActionDefinition<Q extends Record<string, any>> {
923
+ id: string;
924
+ type: 'quick';
925
+ kind: OutputKind;
926
+ label?: string;
927
+ enable: boolean | ((context: { engine: CreativeEngine }) => boolean);
928
+ render: (context: QuickActionRenderContext<Q>) => void;
929
+ }
930
+ ```