@imgly/plugin-ai-generation-web 0.1.0-rc.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 (43) hide show
  1. package/README.md +798 -0
  2. package/dist/__tests__/middleware-disposer.test.d.ts +1 -0
  3. package/dist/__tests__/middleware-rateLimiting.test.d.ts +1 -0
  4. package/dist/__tests__/middleware.test.d.ts +1 -0
  5. package/dist/__tests__/utils.test.d.ts +1 -0
  6. package/dist/common/renderImageUrlProperty.d.ts +14 -0
  7. package/dist/generation/generate.d.ts +16 -0
  8. package/dist/generation/getAssetResultForGenerated.d.ts +4 -0
  9. package/dist/generation/getAssetResultForPlaceholder.d.ts +4 -0
  10. package/dist/generation/getDryRunOutput.d.ts +3 -0
  11. package/dist/generation/handleGenerationError.d.ts +9 -0
  12. package/dist/generation/initProvider.d.ts +20 -0
  13. package/dist/generation/middleware/alwaysOnTopMiddleware.d.ts +14 -0
  14. package/dist/generation/middleware/editModeMiddleware.d.ts +30 -0
  15. package/dist/generation/middleware/highlightBlocksMiddleware.d.ts +24 -0
  16. package/dist/generation/middleware/lockMiddleware.d.ts +19 -0
  17. package/dist/generation/middleware/loggingMiddleware.d.ts +4 -0
  18. package/dist/generation/middleware/middleware.d.ts +35 -0
  19. package/dist/generation/middleware/pendingMiddleware.d.ts +14 -0
  20. package/dist/generation/middleware/rateLimitMiddleware.d.ts +40 -0
  21. package/dist/generation/openapi/dereferenceDocument.d.ts +14 -0
  22. package/dist/generation/openapi/getProperties.d.ts +5 -0
  23. package/dist/generation/openapi/isOpenAPISchema.d.ts +9 -0
  24. package/dist/generation/openapi/renderProperty.d.ts +6 -0
  25. package/dist/generation/openapi/types.d.ts +41 -0
  26. package/dist/generation/previewUri.d.ts +2 -0
  27. package/dist/generation/provider.d.ts +373 -0
  28. package/dist/generation/quickAction/consumeGeneratedResult.d.ts +23 -0
  29. package/dist/generation/quickAction/getQuickActionMenu.d.ts +10 -0
  30. package/dist/generation/quickAction/registerQuickActionMenuComponent.d.ts +12 -0
  31. package/dist/generation/quickAction/types.d.ts +25 -0
  32. package/dist/generation/quickAction/utils.d.ts +13 -0
  33. package/dist/generation/registerPanelInputCustom.d.ts +6 -0
  34. package/dist/generation/registerPanelInputSchema.d.ts +9 -0
  35. package/dist/generation/renderGenerationComponents.d.ts +15 -0
  36. package/dist/generation/types.d.ts +56 -0
  37. package/dist/icons.d.ts +3 -0
  38. package/dist/index.d.ts +17 -0
  39. package/dist/index.mjs +81 -0
  40. package/dist/index.mjs.map +7 -0
  41. package/dist/registerDockComponent.d.ts +10 -0
  42. package/dist/utils.d.ts +66 -0
  43. package/package.json +67 -0
package/README.md ADDED
@@ -0,0 +1,798 @@
1
+ # IMG.LY AI Generation Utilities
2
+
3
+ A powerful toolkit for implementing AI generation providers in CreativeEditor SDK.
4
+
5
+ ## Overview
6
+
7
+ 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
+
9
+ - Provider registration and initialization
10
+ - User interface generation
11
+
12
+ ## Getting Started
13
+
14
+ ### Installation
15
+
16
+ ```bash
17
+ npm install @imgly/plugin-ai-generation-web
18
+ ```
19
+
20
+ ### Creating a Custom Provider
21
+
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:
23
+
24
+ ```typescript
25
+ import {
26
+ Provider,
27
+ ImageOutput,
28
+ initProvider,
29
+ loggingMiddleware
30
+ } from '@imgly/plugin-ai-generation-web';
31
+
32
+ // Create your image generation provider
33
+ const myImageProvider: Provider<'image', MyInputType, ImageOutput> = {
34
+ // Unique identifier for this provider
35
+ id: 'my-image-provider',
36
+
37
+ // Define output asset type, other options are 'video', 'audio', 'text'
38
+ kind: 'image',
39
+
40
+ // Initialize the provider
41
+ initialize: async ({ engine, cesdk }) => {
42
+ // Setup APIs, register further components, etc.
43
+ myAIApi.configure({ apiKey: 'YOUR_API_KEY' });
44
+ },
45
+
46
+ // Define input panel and UI components
47
+ input: {
48
+ // Define how the input panel is rendered
49
+ panel: {
50
+ // Option 1: Schema-based UI (using OpenAPI)
51
+ type: 'schema',
52
+ document: myApiSchema,
53
+ inputReference: '#/components/schemas/GenerationInput',
54
+ getBlockInput: async (input) => ({
55
+ image: { width: 1024, height: 1024 }
56
+ })
57
+ },
58
+
59
+ // Optional: Quick actions for the quick action (sub)menu in the canvas menu
60
+ quickActions: {
61
+ actions: [
62
+ {
63
+ id: 'enhance-image',
64
+ version: '1',
65
+ enable: true,
66
+ render: (context, quickActionContext) => {
67
+ // Render quick action UI
68
+ }
69
+ }
70
+ ]
71
+ }
72
+ },
73
+
74
+ // Define output generation behavior
75
+ output: {
76
+ // Allow cancellation
77
+ abortable: true,
78
+
79
+ // Store generated assets, options are:
80
+ // - false: No history
81
+ // - '@imgly/local': In-memory storage (lost on refresh)
82
+ // - '@imgly/indexedDB': Browser IndexedDB storage
83
+ // - any other string: Handled as a custom asset source ID
84
+ history: '@imgly/indexedDB',
85
+
86
+ // Add middleware for pre/post-processing of the generation
87
+ middleware: [loggingMiddleware()],
88
+
89
+ // Configure success/error notifications
90
+ notification: {
91
+ success: {
92
+ show: true,
93
+ message: 'Generation successful!'
94
+ }
95
+ },
96
+
97
+ // Core generation function
98
+ generate: async (input, { abortSignal, engine }) => {
99
+ // Call your AI API and return result
100
+ const response = await myAIApi.generateImage(input);
101
+
102
+ return {
103
+ kind: 'image',
104
+ url: response.imageUrl
105
+ };
106
+ }
107
+ }
108
+ };
109
+ ```
110
+
111
+ ## Provider Interface
112
+
113
+ The Provider interface is generic and type-safe, supporting four output kinds:
114
+
115
+ ```typescript
116
+ // K: Output kind ('image', 'video', 'audio', 'text')
117
+ // I: Input type specific to your provider, i.e. what does the generate function need
118
+ // O: Output type (ImageOutput, VideoOutput, AudioOutput, TextOutput)
119
+ // C: Chunk type for streaming (optional, defaults to O)
120
+ interface Provider<K extends OutputKind, I, O extends Output, C = O> { ... }
121
+ ```
122
+
123
+ ### Key Provider Options
124
+
125
+ - **id**: Unique identifier for your provider
126
+ - **kind**: Type of asset generated ('image', 'video', 'audio', 'text')
127
+ - **name**: Optional human-readable name
128
+ - **initialize**: Setup function called when the provider is loaded
129
+ - **input**: Configuration for input UI and parameters
130
+ - **output**: Configuration for generation and result handling
131
+
132
+ #### Provider Output Options
133
+
134
+ The `output` property has several important options:
135
+
136
+ - **generate**: Main function that performs the actual generation
137
+ - **history**: Asset storage strategy ('false', '@imgly/local', '@imgly/indexedDB', or custom ID)
138
+ - **abortable**: Whether generation can be cancelled by the user
139
+ - **middleware**: Array of middleware functions for pre/post-processing
140
+ - **notification**: Success and error notification configuration
141
+ - **generationHintText**: Text to display below the generation button
142
+
143
+ ##### Notification Configuration
144
+
145
+ The notification system allows fine-grained control over success and error messages:
146
+
147
+ ```typescript
148
+ notification: {
149
+ success: {
150
+ // Control whether to show notifications (can be dynamic)
151
+ show: true, // or (context) => shouldShow(context)
152
+
153
+ // Message text or i18n key (can be dynamic)
154
+ message: 'Generation successful!', // or (context) => getMessage(context)
155
+
156
+ // Optional action button
157
+ action: {
158
+ label: 'View', // or (context) => getLabel(context)
159
+ onClick: (context) => { /* handle click */ }
160
+ },
161
+
162
+ // How long to show the notification
163
+ duration: 'short' // or 'medium', 'long', 'infinite'
164
+ },
165
+
166
+ error: {
167
+ // Similar options for error notifications
168
+ show: true,
169
+ message: 'Generation failed', // or (context) => getErrorMessage(context)
170
+ // ...
171
+ }
172
+ }
173
+ ```
174
+
175
+ ##### Streaming Generation
176
+
177
+ The `generate` function can return a simple output object or an AsyncGenerator for streaming results:
178
+
179
+ ```typescript
180
+ // Simple response
181
+ generate: async (input, options) => {
182
+ const result = await api.generateImage(input);
183
+ return { kind: 'image', url: result.url };
184
+ }
185
+
186
+ // Streaming response (right now only supported for text)
187
+ generate: async function* (input, options) {
188
+ const stream = api.streamGenerationResult(input);
189
+
190
+ let inferredText: string = '';
191
+ // Yield interim results
192
+ for await (const chunk of stream) {
193
+ inferredText += chunk;
194
+ yield { kind: 'text', text: inferredText };
195
+ }
196
+
197
+ // Return final result
198
+ return { kind: 'text', url: inferredText };
199
+ }
200
+ ```
201
+
202
+ ##### Generation Hint Text
203
+
204
+ The `generationHintText` property allows providers to display helpful information below the generation button:
205
+
206
+ ```typescript
207
+ generationHintText: "Generation may take up to a minute. You can close this panel and will be notified when ready."
208
+ ```
209
+
210
+ ## Input Panel Types
211
+
212
+ The package supports two approaches for creating input panels:
213
+
214
+ ### 1. Schema-based Input Panels
215
+
216
+ The `schema` type uses OpenAPI specification to declaratively define your input form.
217
+
218
+ ```typescript
219
+ input: {
220
+ panel: {
221
+ type: 'schema',
222
+ // Complete OpenAPI v3 document describing your inputs
223
+ document: myOpenAPISchema,
224
+ // JSON pointer to your input schema within the document
225
+ inputReference: '#/components/schemas/GenerationInput',
226
+ // Optional property to control display order
227
+ orderExtensionKeyword: 'x-order-properties',
228
+ // Function that converts input to block parameters
229
+ getBlockInput: async (input) => ({
230
+ image: { width: 1024, height: 1024 }
231
+ }),
232
+ // Optional custom renderers for specific properties found in the schema
233
+ renderCustomProperty: {
234
+ // This is a custom renderer for a fictional `imageUrl` property
235
+ imageUrl: (context, property) => {
236
+ const valueState = context.state('imageUrl', '');
237
+ context.builder.TextInput('imageUrl', {
238
+ label: 'Image URL',
239
+ ...valueState
240
+ });
241
+
242
+ // Return a function that returns the value for this property
243
+ return () => { id: property.id, type: 'string', value: valueState.value };
244
+ }
245
+ }
246
+ }
247
+ }
248
+ ```
249
+
250
+ #### OpenAPI Schema Example
251
+
252
+ ```json
253
+ {
254
+ "openapi": "3.0.0",
255
+ "components": {
256
+ "schemas": {
257
+ "GenerationInput": {
258
+ "type": "object",
259
+ "required": ["prompt"],
260
+ "properties": {
261
+ "prompt": {
262
+ "type": "string",
263
+ "title": "Prompt",
264
+ "description": "Describe what you want to generate",
265
+ "x-imgly-builder": {
266
+ "component": "TextArea"
267
+ }
268
+ },
269
+ "width": {
270
+ "type": "integer",
271
+ "title": "Width",
272
+ "default": 1024,
273
+ "enum": [512, 1024, 2048],
274
+ "x-imgly-builder": {
275
+ "component": "Select"
276
+ }
277
+ }
278
+ },
279
+ "x-order-properties": ["prompt", "width"]
280
+ }
281
+ }
282
+ }
283
+ }
284
+ ```
285
+
286
+ #### Benefits of Schema-based Input
287
+
288
+ - Built-in validation based on schema constraints
289
+ - AI provider like fal.ai provide schemas for their models
290
+ - Automatic UI component generation based on property types
291
+ - Extensions like `x-imgly-builder` to specify component types
292
+ - Property ordering via `orderExtensionKeyword`
293
+ - Customizable property rendering with `renderCustomProperty`
294
+
295
+ ### 2. Custom Input Panels
296
+
297
+ The `custom` type gives you complete control over UI components.
298
+
299
+ ```typescript
300
+ input: {
301
+ panel: {
302
+ type: 'custom',
303
+ render: (context, options) => {
304
+ // Use the builder pattern to create UI components
305
+ const promptState = context.state('prompt', '');
306
+ context.builder.TextArea('prompt', {
307
+ label: 'Prompt',
308
+ ...promptState
309
+ });
310
+
311
+ // Set up width selection
312
+ const widthState = context.state('width', 1024);
313
+ context.builder.Select('width', {
314
+ label: 'Width',
315
+ options: [
316
+ { value: 512, label: '512px' },
317
+ { value: 1024, label: '1024px' },
318
+ { value: 2048, label: '2048px' }
319
+ ],
320
+ ...widthState
321
+ });
322
+
323
+ // Return functions to get input values and block parameters
324
+ return {
325
+ // The input for the generate function
326
+ getInput: () => ({
327
+ prompt: promptState.value,
328
+ width: widthState.value
329
+ }),
330
+ // The input for the block creation
331
+ getBlockInput: () => ({
332
+ image: {
333
+ width: widthState.value,
334
+ height: widthState.value,
335
+ label: `AI Image: ${promptState.value.substring(0, 20)}...`
336
+ }
337
+ })
338
+ };
339
+ }
340
+ }
341
+ }
342
+ ```
343
+
344
+ #### Benefits of Custom Input Panels
345
+
346
+ - Complete control over UI components and layout
347
+ - Complex logic between fields (dependencies, conditionals)
348
+ - Dynamic UI that changes based on user interactions
349
+
350
+ #### Panel User Flow Options
351
+
352
+ Both panel types accept additional configuration:
353
+
354
+ ```typescript
355
+ panel: {
356
+ type: 'schema', // or 'custom'
357
+ // ...panel type specific options
358
+
359
+ // Control the generation flow
360
+ userFlow: 'placeholder', // or 'generation-only' (default)
361
+
362
+ // Include/exclude history library from panel
363
+ includeHistoryLibrary: true // (default)
364
+ }
365
+ ```
366
+
367
+ - **userFlow**:
368
+
369
+ - `placeholder`: Creates a block as a placeholder with loading state when generation starts
370
+ - `generation-only`: Only triggers generation without creating a placeholder
371
+
372
+ - **includeHistoryLibrary**: Controls whether the history library is shown in the panel
373
+
374
+ ## The `getBlockInput` Function
375
+
376
+ The `getBlockInput` function is crucial for both panel types. It converts your input into the parameters needed to create a block in CreativeEditor SDK.
377
+
378
+ ### What It Does
379
+
380
+ - Defines dimensions, duration, and appearance of asset blocks
381
+ - Creates placeholders before generation completes
382
+ - Maps your AI provider's inputs to standardized block parameters
383
+
384
+ ### Required Return Values by Output Kind
385
+
386
+ Each output kind requires specific parameters:
387
+
388
+ #### For Images
389
+
390
+ ```typescript
391
+ getBlockInput: async (input) => ({
392
+ image: {
393
+ width: 1024, // Required - Width in pixels
394
+ height: 1024, // Required - Height in pixels
395
+ label: 'My Image' // Optional - Display name
396
+ }
397
+ });
398
+ ```
399
+
400
+ #### For Videos
401
+
402
+ ```typescript
403
+ getBlockInput: async (input) => ({
404
+ video: {
405
+ width: 1280, // Required - Width in pixels
406
+ height: 720, // Required - Height in pixels
407
+ duration: 10, // Required - Duration in seconds
408
+ label: 'My Video' // Optional - Display name
409
+ }
410
+ });
411
+ ```
412
+
413
+ #### For Audio
414
+
415
+ ```typescript
416
+ getBlockInput: async (input) => ({
417
+ audio: {
418
+ duration: 30, // Optional - Duration in seconds
419
+ thumbnailUrl: 'path/to/img.jpg', // Optional - URL for thumbnail
420
+ label: 'My Audio' // Optional - Display name
421
+ }
422
+ });
423
+ ```
424
+
425
+ #### For Text
426
+
427
+ ```typescript
428
+ getBlockInput: async (input) => ({
429
+ text: {
430
+ length: 250, // Required - Approximate character length
431
+ label: 'My Text' // Optional - Display name
432
+ }
433
+ });
434
+ ```
435
+
436
+ ## Quick Actions
437
+
438
+ 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.
439
+
440
+ 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.
441
+
442
+ ### Purpose of Quick Actions
443
+
444
+ - **Context-Aware**: Operate on selected blocks in the canvas
445
+ - **Streamlined Workflow**: Allow users to apply AI transformations without switching to a panel
446
+ - **Immediate Feedback**: Provide quick access to common AI operations
447
+ - **In-Canvas Experience**: Keep users in their creative workflow
448
+
449
+ ### Quick Action Structure
450
+
451
+ ```typescript
452
+ quickActions: {
453
+ actions: [
454
+ {
455
+ // Unique identifier
456
+ id: 'enhance-image',
457
+
458
+ // Version for compatibility
459
+ version: '1',
460
+
461
+ // Enable/disable based on condition
462
+ // E.g., you should check for the correct block type here.
463
+ enable: true, // or a function: (context) => boolean
464
+
465
+ // Optional scope requirements
466
+ scopes: ['text.edit'],
467
+
468
+ // Optional confirmation after generation
469
+ confirmation: true,
470
+
471
+ // Prevent selection changes during confirmation
472
+ lockDuringConfirmation: true,
473
+
474
+ // Basic menu item rendering
475
+ render: (context, quickActionContext) => {
476
+ // Add button to quick action menu
477
+ },
478
+
479
+ // Optional expanded mode rendering
480
+ renderExpanded: (context, quickActionContext) => {
481
+ // Render more complex interface
482
+ }
483
+ }
484
+ ];
485
+ }
486
+ ```
487
+
488
+ ### Simple Quick Action Example
489
+
490
+ ```typescript
491
+ {
492
+ id: 'enhance-image',
493
+ version: '1',
494
+ enable: true,
495
+ render: ({ builder }, { generate, closeMenu }) => {
496
+ builder.Button('enhance', {
497
+ label: 'Enhance Image',
498
+ icon: '@imgly/MagicWand',
499
+ onClick: async () => {
500
+ // Generate with fixed parameters
501
+ await generate({
502
+ prompt: 'Enhance this image and improve quality'
503
+ });
504
+ closeMenu();
505
+ }
506
+ });
507
+ }
508
+ }
509
+ ```
510
+
511
+ ### Quick Action with Expanded Menu
512
+
513
+ 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.
514
+
515
+ ```typescript
516
+ {
517
+ id: 'change-image',
518
+ version: '1',
519
+ enable: true,
520
+ render: ({ builder }, { toggleExpand }) => {
521
+ // Render basic button that expands to complex UI
522
+ builder.Button('change', {
523
+ label: 'Change Image',
524
+ icon: '@imgly/Edit',
525
+ onClick: toggleExpand // Switch to expanded view
526
+ });
527
+ },
528
+ renderExpanded: ({ builder, state }, { generate, toggleExpand }) => {
529
+ // Create more complex UI with input fields
530
+ const promptState = state('prompt', '');
531
+
532
+ builder.TextArea('prompt', {
533
+ label: 'Prompt',
534
+ placeholder: 'Describe the changes you want...',
535
+ ...promptState
536
+ });
537
+
538
+ builder.Separator('separator');
539
+
540
+ // Add footer with cancel/apply buttons
541
+ builder.ButtonRow('footer', {
542
+ children: () => {
543
+ builder.Button('cancel', {
544
+ label: 'Back',
545
+ onClick: toggleExpand // Return to basic view
546
+ });
547
+
548
+ builder.Button('apply', {
549
+ label: 'Generate',
550
+ color: 'accent',
551
+ onClick: async () => {
552
+ await generate({
553
+ prompt: promptState.value
554
+ });
555
+ toggleExpand(); // Close expanded view after generation
556
+ }
557
+ });
558
+ }
559
+ });
560
+ }
561
+ }
562
+ ```
563
+
564
+ ### Quick Action Context
565
+
566
+ The `quickActionContext` parameter gives you access to:
567
+
568
+ - **blockIds**: Array of currently selected block IDs
569
+ - **closeMenu**: Function to close the quick action menu
570
+ - **toggleExpand**: Function to toggle between basic and expanded views
571
+ - **generate**: Function to trigger generation with input parameters
572
+ - **handleGenerationError**: Function to handle and display generation errors
573
+
574
+ ### Key Use Cases
575
+
576
+ 1. **One-Click Actions**: Simple transformations with predefined parameters
577
+ 2. **Context-Aware Generation**: Using properties of selected blocks as inputs
578
+ 3. **Multi-Step Workflows**: Expanded UIs for complex generation tasks
579
+ 4. **Block Manipulation**: Applying AI-generated content to existing blocks
580
+ 5. **Visual Selection**: Displaying visual options that apply different styles
581
+
582
+ ### Quick Action vs Panel: When to Use Each
583
+
584
+ **Use Quick Actions when:**
585
+
586
+ - The operation is context-dependent on selected blocks
587
+ - The operation is commonly used and benefits from quick access
588
+ - The input requirements are simple or can be preset
589
+ - The action works directly with content already on the canvas
590
+
591
+ **Use Panels when:**
592
+
593
+ - The operation requires complex input forms
594
+ - The generation is independent of canvas selections
595
+ - Users need to browse a history of generated assets
596
+ - The operation creates entirely new content rather than modifying existing content
597
+
598
+ ## Using Your Provider
599
+
600
+ 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.
601
+
602
+ ### Initializing Your Provider
603
+
604
+ The most basic way is to use the `initProvider` function to register your provider with CreativeEditor SDK:
605
+
606
+ ```typescript
607
+ import { initProvider } from '@imgly/plugin-ai-generation-web';
608
+
609
+ // Create your provider
610
+ const myProvider = createMyProvider({
611
+ proxyUrl: 'https://your-api-proxy.example.com'
612
+ });
613
+
614
+ // Initialize the provider with CreativeEditor SDK
615
+ function setupMyProvider(cesdk) {
616
+ const result = initProvider(
617
+ myProvider,
618
+ {
619
+ engine: cesdk.engine,
620
+ cesdk
621
+ },
622
+ {
623
+ debug: false, // Enable/disable debug logging
624
+ dryRun: false // Enable/disable dry run mode (no actual API calls)
625
+ }
626
+ );
627
+
628
+ return result;
629
+ }
630
+ ```
631
+
632
+ 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).
633
+
634
+ Alternatively, the `initProvider` function returns an object with `renderBuilderFunctions` which contains render functions that can be used to create custom UI.
635
+
636
+ ### Panel IDs and Registration
637
+
638
+ When a provider is initialized, it automatically registers panels with specific IDs. These panel IDs follow a consistent pattern:
639
+
640
+ ```
641
+ ly.img.ai/{provider-id}
642
+ ```
643
+
644
+ For example:
645
+
646
+ - A provider with ID `my-image-provider` registers a panel with ID `ly.img.ai/my-image-provider`
647
+ - A provider with ID `fal-ai/recraft-v3` registers a panel with ID `ly.img.ai/fal-ai/recraft-v3`
648
+
649
+ You can programmatically get a panel ID using the `getPanelId` function:
650
+
651
+ ```typescript
652
+ import { getPanelId } from '@imgly/plugin-ai-generation-web';
653
+
654
+ // Get panel ID for a provider
655
+ const panelId = getPanelId('my-image-provider'); // returns "ly.img.ai/my-image-provider"
656
+
657
+ // Open the panel
658
+ cesdk.ui.openPanel(panelId);
659
+ ```
660
+
661
+ For quick actions in the canvas menu, the following format is used:
662
+
663
+ ```
664
+ ly.img.ai.{kind}.canvasMenu
665
+ ```
666
+
667
+ For example:
668
+
669
+ - Image quick actions: `ly.img.ai.image.canvasMenu`
670
+ - Video quick actions: `ly.img.ai.video.canvasMenu`
671
+ - Audio quick actions: `ly.img.ai.audio.canvasMenu`
672
+ - Text quick actions: `ly.img.ai.text.canvasMenu`
673
+
674
+ ### Using with Existing AI Generation Plugins
675
+
676
+ 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.
677
+
678
+ - `@imgly/plugin-ai-image-generation-web`: For image generation
679
+ - `@imgly/plugin-ai-video-generation-web`: For video generation
680
+ - `@imgly/plugin-ai-audio-generation-web`: For audio generation
681
+ - `@imgly/plugin-ai-text-generation-web`: For text generation
682
+
683
+ You can use these packages with different AI provider implementations:
684
+
685
+ ```typescript
686
+ import CreativeEditorSDK from '@cesdk/cesdk-js';
687
+
688
+ // Import plugin packages
689
+ import ImageGeneration from '@imgly/plugin-ai-image-generation-web';
690
+ import FalAiImage from '@imgly/plugin-ai-image-generation-web/fal-ai';
691
+ import VideoGeneration from '@imgly/plugin-ai-video-generation-web';
692
+ import FalAiVideo from '@imgly/plugin-ai-video-generation-web/fal-ai';
693
+ import AudioGeneration from '@imgly/plugin-ai-audio-generation-web';
694
+ import Elevenlabs from '@imgly/plugin-ai-audio-generation-web/elevenlabs';
695
+ import TextGeneration from '@imgly/plugin-ai-text-generation-web';
696
+ import Anthropic from '@imgly/plugin-ai-text-generation-web/anthropic';
697
+
698
+ // Initialize CreativeEditor SDK
699
+ CreativeEditorSDK.create(domElement, {
700
+ license: 'your-license-key'
701
+ // Other configuration options...
702
+ }).then(async (cesdk) => {
703
+ // Add default asset sources
704
+ await cesdk.addDefaultAssetSources();
705
+
706
+ // Text generation with Anthropic
707
+ cesdk.addPlugin(
708
+ TextGeneration({
709
+ provider: Anthropic.AnthropicProvider({
710
+ proxyUrl: 'https://your-anthropic-proxy.example.com'
711
+ })
712
+ })
713
+ );
714
+
715
+ // Image generation with Fal.ai models
716
+ cesdk.addPlugin(
717
+ ImageGeneration({
718
+ text2image: FalAiImage.RecraftV3({
719
+ proxyUrl: 'https://your-falai-proxy.example.com'
720
+ }),
721
+ image2image: FalAiImage.GeminiFlashEdit({
722
+ proxyUrl: 'https://your-falai-proxy.example.com'
723
+ })
724
+ })
725
+ );
726
+
727
+ // Video generation
728
+ cesdk.addPlugin(
729
+ VideoGeneration({
730
+ text2video: FalAiVideo.MinimaxVideo01Live({
731
+ proxyUrl: 'https://your-falai-proxy.example.com'
732
+ }),
733
+ image2video: FalAiVideo.MinimaxVideo01LiveImageToVideo({
734
+ proxyUrl: 'https://your-falai-proxy.example.com'
735
+ })
736
+ })
737
+ );
738
+
739
+ // Audio generation
740
+ cesdk.addPlugin(
741
+ AudioGeneration({
742
+ text2speech: Elevenlabs.ElevenMultilingualV2({
743
+ proxyUrl: 'https://your-elevenlabs-proxy.example.com'
744
+ }),
745
+ text2sound: Elevenlabs.ElevenSoundEffects({
746
+ proxyUrl: 'https://your-elevenlabs-proxy.example.com'
747
+ })
748
+ })
749
+ );
750
+
751
+ // Add the quick action menu to the canvas menu
752
+ cesdk.ui.setCanvasMenuOrder([
753
+ 'ly.img.ai.text.canvasMenu',
754
+ 'ly.img.ai.image.canvasMenu',
755
+ ...cesdk.ui.getCanvasMenuOrder()
756
+ ]);
757
+ });
758
+ ```
759
+
760
+ ## Advanced Features
761
+
762
+ ### Middleware
763
+
764
+ The package includes a middleware system to augment the generation flow:
765
+
766
+ ```typescript
767
+ // NOTE:: This middleware will not protect against calling the server directly as
768
+ // many times as you want. It is only meant to be used for rate-limiting the UI before it
769
+ // hits the server.
770
+ // Always secure your API endpoints with authentication and authorization or server-side
771
+ // rate-limiting.
772
+ import { rateLimitMiddleware } from '@imgly/plugin-ai-generation-web';
773
+
774
+ // Create a rate limiting middleware
775
+ const rateLimit = rateLimitMiddleware({
776
+ maxRequests: 10,
777
+ timeWindowMs: 60000, // 1 minute
778
+ onRateLimitExceeded: (input, options, info) => {
779
+ console.log(
780
+ `Rate limit exceeded: ${info.currentCount}/${info.maxRequests}`
781
+ );
782
+ return false; // Reject request
783
+ }
784
+ });
785
+
786
+ // Apply middleware to your provider
787
+ const provider = {
788
+ // ...provider config
789
+ output: {
790
+ middleware: [rateLimit]
791
+ // ...other output config
792
+ }
793
+ };
794
+ ```
795
+
796
+ ## TypeScript Support
797
+
798
+ This package is fully typed with TypeScript, providing excellent IntelliSense support during development.