@quilltap/plugin-types 1.0.2 → 1.1.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.
@@ -0,0 +1,834 @@
1
+ import { ReactNode } from 'react';
2
+ import { LLMProvider, ImageGenProvider, ToolFormatOptions, ToolCallRequest } from './llm/index.js';
3
+
4
+ /**
5
+ * Provider Plugin Interface types for Quilltap plugin development
6
+ *
7
+ * @module @quilltap/plugin-types/plugins/provider
8
+ */
9
+
10
+ /**
11
+ * Provider metadata for UI display and identification
12
+ */
13
+ interface ProviderMetadata {
14
+ /** Internal identifier for the provider (e.g., 'OPENAI', 'ANTHROPIC') */
15
+ providerName: string;
16
+ /** Human-readable display name for UI (e.g., 'OpenAI', 'Anthropic') */
17
+ displayName: string;
18
+ /** Short description of the provider */
19
+ description: string;
20
+ /** Short abbreviation for icon display (e.g., 'OAI', 'ANT') */
21
+ abbreviation: string;
22
+ /** Tailwind CSS color classes for UI styling */
23
+ colors: {
24
+ /** Background color class (e.g., 'bg-green-100') */
25
+ bg: string;
26
+ /** Text color class (e.g., 'text-green-800') */
27
+ text: string;
28
+ /** Icon color class (e.g., 'text-green-600') */
29
+ icon: string;
30
+ };
31
+ }
32
+ /**
33
+ * Configuration requirements for the provider
34
+ */
35
+ interface ProviderConfigRequirements {
36
+ /** Whether this provider requires an API key */
37
+ requiresApiKey: boolean;
38
+ /** Whether this provider requires a custom base URL */
39
+ requiresBaseUrl: boolean;
40
+ /** Label text for API key input field */
41
+ apiKeyLabel?: string;
42
+ /** Label text for base URL input field */
43
+ baseUrlLabel?: string;
44
+ /** Placeholder text for base URL input */
45
+ baseUrlPlaceholder?: string;
46
+ /** Default value for base URL */
47
+ baseUrlDefault?: string;
48
+ /** Deprecated: use baseUrlDefault instead */
49
+ defaultBaseUrl?: string;
50
+ }
51
+ /**
52
+ * Provider capability flags
53
+ */
54
+ interface ProviderCapabilities {
55
+ /** Whether the provider supports chat completions */
56
+ chat: boolean;
57
+ /** Whether the provider supports image generation */
58
+ imageGeneration: boolean;
59
+ /** Whether the provider supports text embeddings */
60
+ embeddings: boolean;
61
+ /** Whether the provider supports web search functionality */
62
+ webSearch: boolean;
63
+ }
64
+ /**
65
+ * Attachment/file support configuration
66
+ */
67
+ interface AttachmentSupport {
68
+ /** Whether this provider supports file attachments */
69
+ supportsAttachments: boolean;
70
+ /** Array of MIME types supported for attachments */
71
+ supportedMimeTypes: string[];
72
+ /** Human-readable description of attachment support */
73
+ description: string;
74
+ /** Additional notes about attachment support or limitations */
75
+ notes?: string;
76
+ /** Maximum file size in bytes */
77
+ maxFileSize?: number;
78
+ /** Maximum number of files per request */
79
+ maxFiles?: number;
80
+ }
81
+ /**
82
+ * Information about a specific model
83
+ */
84
+ interface ModelInfo {
85
+ /** Unique identifier for the model */
86
+ id: string;
87
+ /** Human-readable name of the model */
88
+ name: string;
89
+ /** Context window size (tokens) */
90
+ contextWindow?: number;
91
+ /** Maximum output tokens for this model */
92
+ maxOutputTokens?: number;
93
+ /** Whether this model supports image attachments */
94
+ supportsImages?: boolean;
95
+ /** Whether this model supports tool/function calling */
96
+ supportsTools?: boolean;
97
+ /** Description of the model */
98
+ description?: string;
99
+ /** Pricing information */
100
+ pricing?: {
101
+ /** Price per 1M input tokens */
102
+ input: number;
103
+ /** Price per 1M output tokens */
104
+ output: number;
105
+ };
106
+ }
107
+ /**
108
+ * Information about an embedding model
109
+ */
110
+ interface EmbeddingModelInfo {
111
+ /** Unique identifier for the embedding model */
112
+ id: string;
113
+ /** Human-readable name of the model */
114
+ name: string;
115
+ /** Dimensions of the embedding vector output */
116
+ dimensions?: number;
117
+ /** Description of the model's characteristics */
118
+ description?: string;
119
+ }
120
+ /**
121
+ * Information about an image generation model
122
+ */
123
+ interface ImageGenerationModelInfo {
124
+ /** Unique identifier for the model */
125
+ id: string;
126
+ /** Human-readable name of the model */
127
+ name: string;
128
+ /** Supported aspect ratios (e.g., ['1:1', '16:9']) */
129
+ supportedAspectRatios?: string[];
130
+ /** Supported image sizes (e.g., ['1024x1024', '512x512']) */
131
+ supportedSizes?: string[];
132
+ /** Description of the model */
133
+ description?: string;
134
+ }
135
+ /**
136
+ * Constraints for image generation
137
+ */
138
+ interface ImageProviderConstraints {
139
+ /** Maximum bytes allowed for image generation prompt */
140
+ maxPromptBytes?: number;
141
+ /** Warning message about prompt constraints */
142
+ promptConstraintWarning?: string;
143
+ /** Maximum images per request */
144
+ maxImagesPerRequest?: number;
145
+ /** Supported aspect ratios */
146
+ supportedAspectRatios?: string[];
147
+ /** Supported image sizes */
148
+ supportedSizes?: string[];
149
+ }
150
+ /**
151
+ * Icon component props
152
+ */
153
+ interface IconProps {
154
+ /** CSS class for styling */
155
+ className?: string;
156
+ }
157
+ /**
158
+ * Message format support for multi-character chats
159
+ * Defines how the provider handles the 'name' field in messages
160
+ */
161
+ interface MessageFormatSupport {
162
+ /** Whether the provider supports a name field on messages */
163
+ supportsNameField: boolean;
164
+ /** Which roles support the name field */
165
+ supportedRoles: ('user' | 'assistant')[];
166
+ /** Maximum length for name field (if limited) */
167
+ maxNameLength?: number;
168
+ }
169
+ /**
170
+ * Cheap model configuration for background tasks
171
+ * Used for memory extraction, summarization, titling, etc.
172
+ */
173
+ interface CheapModelConfig {
174
+ /** The default cheap model for this provider */
175
+ defaultModel: string;
176
+ /** List of recommended cheap models */
177
+ recommendedModels: string[];
178
+ }
179
+ /**
180
+ * Tool format type for this provider
181
+ * Determines how tools are formatted for API calls
182
+ */
183
+ type ToolFormatType = 'openai' | 'anthropic' | 'google';
184
+ /**
185
+ * Main LLM Provider Plugin Interface
186
+ *
187
+ * Plugins implementing this interface can be dynamically loaded
188
+ * by Quilltap to provide LLM functionality from various providers.
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * import type { LLMProviderPlugin } from '@quilltap/plugin-types';
193
+ *
194
+ * export const plugin: LLMProviderPlugin = {
195
+ * metadata: {
196
+ * providerName: 'MY_PROVIDER',
197
+ * displayName: 'My Provider',
198
+ * description: 'Custom LLM provider',
199
+ * abbreviation: 'MYP',
200
+ * colors: { bg: 'bg-blue-100', text: 'text-blue-800', icon: 'text-blue-600' },
201
+ * },
202
+ * config: {
203
+ * requiresApiKey: true,
204
+ * requiresBaseUrl: false,
205
+ * apiKeyLabel: 'API Key',
206
+ * },
207
+ * capabilities: {
208
+ * chat: true,
209
+ * imageGeneration: false,
210
+ * embeddings: false,
211
+ * webSearch: false,
212
+ * },
213
+ * attachmentSupport: {
214
+ * supportsAttachments: false,
215
+ * supportedMimeTypes: [],
216
+ * description: 'No file attachments supported',
217
+ * },
218
+ * createProvider: () => new MyProvider(),
219
+ * getAvailableModels: async (apiKey) => [...],
220
+ * validateApiKey: async (apiKey) => {...},
221
+ * renderIcon: ({ className }) => <MyIcon className={className} />,
222
+ * };
223
+ * ```
224
+ */
225
+ interface LLMProviderPlugin {
226
+ /** Provider metadata for UI display and identification */
227
+ metadata: ProviderMetadata;
228
+ /** Configuration requirements for this provider */
229
+ config: ProviderConfigRequirements;
230
+ /** Supported capabilities for this provider */
231
+ capabilities: ProviderCapabilities;
232
+ /** File attachment support information */
233
+ attachmentSupport: AttachmentSupport;
234
+ /**
235
+ * Factory method to create an LLMProvider instance
236
+ * @param baseUrl Optional base URL for the provider
237
+ */
238
+ createProvider: (baseUrl?: string) => LLMProvider;
239
+ /**
240
+ * Factory method to create an ImageGenProvider instance (optional)
241
+ * Only required if capabilities.imageGeneration is true
242
+ * @param baseUrl Optional base URL for the provider
243
+ */
244
+ createImageProvider?: (baseUrl?: string) => ImageGenProvider;
245
+ /**
246
+ * Factory method to create an embedding provider (optional)
247
+ * Only required if capabilities.embeddings is true
248
+ * @param baseUrl Optional base URL for the provider
249
+ */
250
+ createEmbeddingProvider?: (baseUrl?: string) => unknown;
251
+ /**
252
+ * Get list of available models for this provider
253
+ * @param apiKey API key for authentication
254
+ * @param baseUrl Optional base URL
255
+ */
256
+ getAvailableModels: (apiKey: string, baseUrl?: string) => Promise<string[]>;
257
+ /**
258
+ * Get static model information without API calls
259
+ */
260
+ getModelInfo?: () => ModelInfo[];
261
+ /**
262
+ * Get embedding models supported by this provider
263
+ */
264
+ getEmbeddingModels?: () => EmbeddingModelInfo[];
265
+ /**
266
+ * Get image generation models supported by this provider
267
+ */
268
+ getImageGenerationModels?: () => ImageGenerationModelInfo[];
269
+ /**
270
+ * Validate an API key for this provider
271
+ * @param apiKey API key to validate
272
+ * @param baseUrl Optional base URL
273
+ */
274
+ validateApiKey: (apiKey: string, baseUrl?: string) => Promise<boolean>;
275
+ /**
276
+ * Render the provider icon as a React component
277
+ * @param props Icon component props
278
+ */
279
+ renderIcon: (props: IconProps) => ReactNode;
280
+ /**
281
+ * Convert universal tool format to provider-specific format (optional)
282
+ * @param tool Tools in OpenAI format or generic objects
283
+ * @param options Formatting options
284
+ */
285
+ formatTools?: (tool: any, options?: ToolFormatOptions) => any;
286
+ /**
287
+ * Parse provider-specific tool calls from response (optional)
288
+ * @param response Raw API response
289
+ */
290
+ parseToolCalls?: (response: any) => ToolCallRequest[];
291
+ /**
292
+ * Get image provider constraints (optional)
293
+ * Only applicable for providers with imageGeneration capability
294
+ */
295
+ getImageProviderConstraints?: () => ImageProviderConstraints;
296
+ /**
297
+ * Message format support for multi-character contexts (optional)
298
+ * If not provided, defaults to no name field support
299
+ */
300
+ messageFormat?: MessageFormatSupport;
301
+ /**
302
+ * Token estimation multiplier (optional)
303
+ * Characters per token for this provider's tokenizer
304
+ * @default 3.5
305
+ */
306
+ charsPerToken?: number;
307
+ /**
308
+ * Tool format type for this provider (optional)
309
+ * Used for quick format detection without calling formatTools()
310
+ * @default 'openai'
311
+ */
312
+ toolFormat?: ToolFormatType;
313
+ /**
314
+ * Cheap model configuration for background tasks (optional)
315
+ * Used for memory extraction, summarization, titling, etc.
316
+ */
317
+ cheapModels?: CheapModelConfig;
318
+ /**
319
+ * Default context window when model is unknown (optional)
320
+ * Falls back to 8192 if not specified
321
+ */
322
+ defaultContextWindow?: number;
323
+ }
324
+ /**
325
+ * Standard export type for provider plugins
326
+ */
327
+ interface ProviderPluginExport {
328
+ /** The provider plugin instance */
329
+ plugin: LLMProviderPlugin;
330
+ }
331
+
332
+ /**
333
+ * Plugin Manifest types for Quilltap plugin development
334
+ *
335
+ * @module @quilltap/plugin-types/plugins/manifest
336
+ */
337
+ /**
338
+ * Plugin capability types
339
+ */
340
+ type PluginCapability = 'LLM_PROVIDER' | 'AUTH_PROVIDER' | 'STORAGE_BACKEND' | 'THEME' | 'UTILITY';
341
+ /**
342
+ * Plugin category
343
+ */
344
+ type PluginCategory = 'PROVIDER' | 'AUTH' | 'STORAGE' | 'UI' | 'UTILITY';
345
+ /**
346
+ * Plugin status
347
+ */
348
+ type PluginStatus = 'STABLE' | 'BETA' | 'EXPERIMENTAL' | 'DEPRECATED';
349
+ /**
350
+ * Author information
351
+ */
352
+ interface PluginAuthor {
353
+ /** Author name */
354
+ name: string;
355
+ /** Author email */
356
+ email?: string;
357
+ /** Author website or profile URL */
358
+ url?: string;
359
+ }
360
+ /**
361
+ * Compatibility requirements
362
+ */
363
+ interface PluginCompatibility {
364
+ /** Minimum Quilltap version (semver range) */
365
+ quilltapVersion: string;
366
+ /** Minimum Node.js version (semver range) */
367
+ nodeVersion?: string;
368
+ }
369
+ /**
370
+ * Provider-specific configuration (for LLM_PROVIDER plugins)
371
+ */
372
+ interface ProviderConfig {
373
+ /** Internal provider name */
374
+ providerName: string;
375
+ /** Human-readable display name */
376
+ displayName: string;
377
+ /** Provider description */
378
+ description: string;
379
+ /** Short abbreviation */
380
+ abbreviation: string;
381
+ /** UI color configuration */
382
+ colors: {
383
+ bg: string;
384
+ text: string;
385
+ icon: string;
386
+ };
387
+ /** Whether the provider requires an API key */
388
+ requiresApiKey: boolean;
389
+ /** Whether the provider requires a base URL */
390
+ requiresBaseUrl: boolean;
391
+ /** Label for API key input */
392
+ apiKeyLabel?: string;
393
+ /** Provider capabilities */
394
+ capabilities: {
395
+ chat: boolean;
396
+ imageGeneration: boolean;
397
+ embeddings: boolean;
398
+ webSearch: boolean;
399
+ };
400
+ /** Attachment support configuration */
401
+ attachmentSupport: {
402
+ supported: boolean;
403
+ mimeTypes: string[];
404
+ description: string;
405
+ };
406
+ }
407
+ /**
408
+ * Required permissions for the plugin
409
+ */
410
+ interface PluginPermissions {
411
+ /** Network domains the plugin may access */
412
+ network?: string[];
413
+ /** Whether the plugin accesses user data */
414
+ userData?: boolean;
415
+ /** Whether the plugin accesses the database */
416
+ database?: boolean;
417
+ /** Whether the plugin accesses the file system */
418
+ fileSystem?: boolean;
419
+ }
420
+ /**
421
+ * Plugin manifest schema
422
+ *
423
+ * This is the structure of the quilltap-manifest.json file
424
+ * that every Quilltap plugin must include.
425
+ */
426
+ interface PluginManifest {
427
+ /** JSON schema reference */
428
+ $schema?: string;
429
+ /** Package name (must start with qtap-plugin-) */
430
+ name: string;
431
+ /** Human-readable title */
432
+ title: string;
433
+ /** Plugin description */
434
+ description: string;
435
+ /** Semantic version */
436
+ version: string;
437
+ /** Author information */
438
+ author: PluginAuthor;
439
+ /** License identifier (SPDX) */
440
+ license: string;
441
+ /** Compatibility requirements */
442
+ compatibility: PluginCompatibility;
443
+ /** Plugin capabilities */
444
+ capabilities: PluginCapability[];
445
+ /** Plugin category */
446
+ category: PluginCategory;
447
+ /** Main entry point (relative path) */
448
+ main: string;
449
+ /** Whether TypeScript source is available */
450
+ typescript?: boolean;
451
+ /** Frontend framework used */
452
+ frontend?: 'REACT' | 'NONE';
453
+ /** Styling approach used */
454
+ styling?: 'TAILWIND' | 'CSS' | 'NONE';
455
+ /** Whether to enable by default when installed */
456
+ enabledByDefault?: boolean;
457
+ /** Plugin status */
458
+ status: PluginStatus;
459
+ /** Search keywords */
460
+ keywords?: string[];
461
+ /** Provider-specific configuration (for LLM_PROVIDER plugins) */
462
+ providerConfig?: ProviderConfig;
463
+ /** Required permissions */
464
+ permissions?: PluginPermissions;
465
+ /** Repository URL */
466
+ repository?: string | {
467
+ type: string;
468
+ url: string;
469
+ directory?: string;
470
+ };
471
+ /** Homepage URL */
472
+ homepage?: string;
473
+ /** Bug tracker URL */
474
+ bugs?: string | {
475
+ url: string;
476
+ email?: string;
477
+ };
478
+ }
479
+ /**
480
+ * Installed plugin metadata
481
+ * Extended manifest with installation-specific information
482
+ */
483
+ interface InstalledPluginInfo extends PluginManifest {
484
+ /** Whether the plugin is currently enabled */
485
+ enabled: boolean;
486
+ /** Installation timestamp */
487
+ installedAt?: string;
488
+ /** Last update timestamp */
489
+ updatedAt?: string;
490
+ /** Installation scope */
491
+ scope?: 'site' | 'user';
492
+ /** Path to installed plugin */
493
+ installPath?: string;
494
+ }
495
+
496
+ /**
497
+ * Theme Plugin Interface types for Quilltap plugin development
498
+ *
499
+ * @module @quilltap/plugin-types/plugins/theme
500
+ */
501
+ /**
502
+ * Color palette for a single color mode (light or dark)
503
+ *
504
+ * Colors can be specified as:
505
+ * - HSL values: "222.2 84% 4.9%" (without hsl() wrapper)
506
+ * - Full HSL: "hsl(222.2 84% 4.9%)"
507
+ * - Hex: "#1a1a2e"
508
+ * - Other valid CSS color values: rgb(), oklch(), etc.
509
+ */
510
+ interface ColorPalette {
511
+ /** Main background color */
512
+ background: string;
513
+ /** Main text color */
514
+ foreground: string;
515
+ /** Primary brand/action color */
516
+ primary: string;
517
+ /** Text on primary color */
518
+ primaryForeground: string;
519
+ /** Secondary background color */
520
+ secondary: string;
521
+ /** Text on secondary color */
522
+ secondaryForeground: string;
523
+ /** Muted background for less prominent elements */
524
+ muted: string;
525
+ /** Muted text color */
526
+ mutedForeground: string;
527
+ /** Accent color for highlights */
528
+ accent: string;
529
+ /** Text on accent color */
530
+ accentForeground: string;
531
+ /** Error/destructive action color */
532
+ destructive: string;
533
+ /** Text on destructive color */
534
+ destructiveForeground: string;
535
+ /** Card background color */
536
+ card: string;
537
+ /** Card text color */
538
+ cardForeground: string;
539
+ /** Popover/dropdown background */
540
+ popover: string;
541
+ /** Popover text color */
542
+ popoverForeground: string;
543
+ /** Default border color */
544
+ border: string;
545
+ /** Input field border color */
546
+ input: string;
547
+ /** Focus ring color */
548
+ ring: string;
549
+ /** Success state color */
550
+ success?: string;
551
+ /** Text on success color */
552
+ successForeground?: string;
553
+ /** Warning state color */
554
+ warning?: string;
555
+ /** Text on warning color */
556
+ warningForeground?: string;
557
+ /** Info state color */
558
+ info?: string;
559
+ /** Text on info color */
560
+ infoForeground?: string;
561
+ /** User message bubble background */
562
+ chatUser?: string;
563
+ /** User message bubble text */
564
+ chatUserForeground?: string;
565
+ }
566
+ /**
567
+ * Typography token configuration
568
+ */
569
+ interface Typography {
570
+ /** Sans-serif font stack (default: "Inter, system-ui, sans-serif") */
571
+ fontSans?: string;
572
+ /** Serif font stack (default: "Georgia, serif") */
573
+ fontSerif?: string;
574
+ /** Monospace font stack (default: "ui-monospace, SFMono-Regular, monospace") */
575
+ fontMono?: string;
576
+ /** Extra small text - 12px (default: "0.75rem") */
577
+ fontSizeXs?: string;
578
+ /** Small text - 14px (default: "0.875rem") */
579
+ fontSizeSm?: string;
580
+ /** Base text size - 16px (default: "1rem") */
581
+ fontSizeBase?: string;
582
+ /** Large text - 18px (default: "1.125rem") */
583
+ fontSizeLg?: string;
584
+ /** Extra large text - 20px (default: "1.25rem") */
585
+ fontSizeXl?: string;
586
+ /** 2XL text - 24px (default: "1.5rem") */
587
+ fontSize2xl?: string;
588
+ /** 3XL text - 30px (default: "1.875rem") */
589
+ fontSize3xl?: string;
590
+ /** 4XL text - 36px (default: "2.25rem") */
591
+ fontSize4xl?: string;
592
+ /** Tight line height (default: "1.25") */
593
+ lineHeightTight?: string;
594
+ /** Normal line height (default: "1.5") */
595
+ lineHeightNormal?: string;
596
+ /** Relaxed line height (default: "1.75") */
597
+ lineHeightRelaxed?: string;
598
+ /** Normal font weight (default: "400") */
599
+ fontWeightNormal?: string;
600
+ /** Medium font weight (default: "500") */
601
+ fontWeightMedium?: string;
602
+ /** Semibold font weight (default: "600") */
603
+ fontWeightSemibold?: string;
604
+ /** Bold font weight (default: "700") */
605
+ fontWeightBold?: string;
606
+ /** Tight letter spacing (default: "-0.025em") */
607
+ letterSpacingTight?: string;
608
+ /** Normal letter spacing (default: "0") */
609
+ letterSpacingNormal?: string;
610
+ /** Wide letter spacing (default: "0.025em") */
611
+ letterSpacingWide?: string;
612
+ }
613
+ /**
614
+ * Spacing and layout token configuration
615
+ */
616
+ interface Spacing {
617
+ /** Small border radius (default: "calc(0.5rem - 4px)") */
618
+ radiusSm?: string;
619
+ /** Medium border radius (default: "calc(0.5rem - 2px)") */
620
+ radiusMd?: string;
621
+ /** Large border radius (default: "0.5rem") */
622
+ radiusLg?: string;
623
+ /** Extra large border radius (default: "0.75rem") */
624
+ radiusXl?: string;
625
+ /** Full/pill border radius (default: "9999px") */
626
+ radiusFull?: string;
627
+ /** 4px spacing (default: "0.25rem") */
628
+ spacing1?: string;
629
+ /** 8px spacing (default: "0.5rem") */
630
+ spacing2?: string;
631
+ /** 12px spacing (default: "0.75rem") */
632
+ spacing3?: string;
633
+ /** 16px spacing (default: "1rem") */
634
+ spacing4?: string;
635
+ /** 20px spacing (default: "1.25rem") */
636
+ spacing5?: string;
637
+ /** 24px spacing (default: "1.5rem") */
638
+ spacing6?: string;
639
+ /** 32px spacing (default: "2rem") */
640
+ spacing8?: string;
641
+ /** 40px spacing (default: "2.5rem") */
642
+ spacing10?: string;
643
+ /** 48px spacing (default: "3rem") */
644
+ spacing12?: string;
645
+ /** 64px spacing (default: "4rem") */
646
+ spacing16?: string;
647
+ }
648
+ /**
649
+ * Visual effects token configuration
650
+ */
651
+ interface Effects {
652
+ /** Small shadow (default: "0 1px 2px 0 rgb(0 0 0 / 0.05)") */
653
+ shadowSm?: string;
654
+ /** Medium shadow (default: "0 4px 6px -1px rgb(0 0 0 / 0.1)") */
655
+ shadowMd?: string;
656
+ /** Large shadow (default: "0 10px 15px -3px rgb(0 0 0 / 0.1)") */
657
+ shadowLg?: string;
658
+ /** Extra large shadow (default: "0 20px 25px -5px rgb(0 0 0 / 0.1)") */
659
+ shadowXl?: string;
660
+ /** Fast transition duration (default: "150ms") */
661
+ transitionFast?: string;
662
+ /** Normal transition duration (default: "200ms") */
663
+ transitionNormal?: string;
664
+ /** Slow transition duration (default: "300ms") */
665
+ transitionSlow?: string;
666
+ /** Default easing function (default: "cubic-bezier(0.4, 0, 0.2, 1)") */
667
+ transitionEasing?: string;
668
+ /** Focus ring width (default: "2px") */
669
+ focusRingWidth?: string;
670
+ /** Focus ring offset (default: "2px") */
671
+ focusRingOffset?: string;
672
+ }
673
+ /**
674
+ * Complete theme tokens structure
675
+ *
676
+ * Contains all customizable values for a theme:
677
+ * - colors: Required light and dark mode color palettes
678
+ * - typography: Optional font customization
679
+ * - spacing: Optional spacing/radius customization
680
+ * - effects: Optional shadows/transitions customization
681
+ */
682
+ interface ThemeTokens {
683
+ /** Light and dark mode color palettes (required) */
684
+ colors: {
685
+ /** Light mode color palette */
686
+ light: ColorPalette;
687
+ /** Dark mode color palette */
688
+ dark: ColorPalette;
689
+ };
690
+ /** Typography customization (optional) */
691
+ typography?: Typography;
692
+ /** Spacing and radius customization (optional) */
693
+ spacing?: Spacing;
694
+ /** Shadow and transition customization (optional) */
695
+ effects?: Effects;
696
+ }
697
+ /**
698
+ * Custom font definition for themes that include custom fonts
699
+ */
700
+ interface FontDefinition {
701
+ /** Font family name */
702
+ family: string;
703
+ /** Font source URL or relative path */
704
+ src: string;
705
+ /** Font weight (e.g., "400", "700", "400 700") */
706
+ weight?: string;
707
+ /** Font style (e.g., "normal", "italic") */
708
+ style?: string;
709
+ /** Font display strategy */
710
+ display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
711
+ }
712
+ /**
713
+ * Loaded font with binary data (for self-contained themes)
714
+ */
715
+ interface EmbeddedFont {
716
+ /** Font family name */
717
+ family: string;
718
+ /** Font weight */
719
+ weight: string;
720
+ /** Font style */
721
+ style?: string;
722
+ /** Base64-encoded font data or data URL */
723
+ data: string;
724
+ /** MIME type of the font */
725
+ mimeType?: string;
726
+ }
727
+ /**
728
+ * Theme plugin metadata for UI display and identification
729
+ */
730
+ interface ThemeMetadata {
731
+ /** Unique theme identifier (lowercase, hyphens allowed) */
732
+ themeId: string;
733
+ /** Human-readable display name */
734
+ displayName: string;
735
+ /** Theme description */
736
+ description?: string;
737
+ /** Theme author */
738
+ author?: string | {
739
+ name: string;
740
+ email?: string;
741
+ url?: string;
742
+ };
743
+ /** Whether this theme provides dark mode support */
744
+ supportsDarkMode: boolean;
745
+ /** Theme tags for categorization */
746
+ tags?: string[];
747
+ /** Base64-encoded preview image or path */
748
+ previewImage?: string;
749
+ }
750
+ /**
751
+ * Main Theme Plugin Interface
752
+ *
753
+ * Plugins implementing this interface can be dynamically loaded
754
+ * by Quilltap to provide custom theming.
755
+ *
756
+ * Self-contained themes export all data directly in the plugin object,
757
+ * with no file system dependencies after module load.
758
+ *
759
+ * @example
760
+ * ```typescript
761
+ * import type { ThemePlugin } from '@quilltap/plugin-types';
762
+ *
763
+ * export const plugin: ThemePlugin = {
764
+ * metadata: {
765
+ * themeId: 'my-theme',
766
+ * displayName: 'My Custom Theme',
767
+ * description: 'A beautiful custom theme',
768
+ * supportsDarkMode: true,
769
+ * tags: ['dark', 'minimal'],
770
+ * },
771
+ * tokens: {
772
+ * colors: {
773
+ * light: {
774
+ * background: 'hsl(0 0% 100%)',
775
+ * foreground: 'hsl(222.2 84% 4.9%)',
776
+ * // ... all required colors
777
+ * },
778
+ * dark: {
779
+ * background: 'hsl(222.2 84% 4.9%)',
780
+ * foreground: 'hsl(210 40% 98%)',
781
+ * // ... all required colors
782
+ * },
783
+ * },
784
+ * typography: {
785
+ * fontSans: '"Custom Font", system-ui, sans-serif',
786
+ * },
787
+ * },
788
+ * cssOverrides: `
789
+ * .qt-button-primary {
790
+ * border-radius: 9999px;
791
+ * }
792
+ * `,
793
+ * fonts: [
794
+ * { family: 'Custom Font', weight: '400', data: 'base64...' },
795
+ * ],
796
+ * };
797
+ * ```
798
+ */
799
+ interface ThemePlugin {
800
+ /** Theme metadata for UI display and identification */
801
+ metadata: ThemeMetadata;
802
+ /** Theme design tokens (colors, typography, spacing, effects) */
803
+ tokens: ThemeTokens;
804
+ /**
805
+ * Optional CSS overrides for component-level customization (Tier 3)
806
+ * This CSS is injected when the theme is active
807
+ */
808
+ cssOverrides?: string;
809
+ /**
810
+ * Optional embedded fonts
811
+ * Base64-encoded font data for fully self-contained themes
812
+ */
813
+ fonts?: EmbeddedFont[];
814
+ /**
815
+ * Optional method for dynamic token generation
816
+ * Called when color mode changes, allows computed theme values
817
+ * @param mode Current color mode ('light' | 'dark')
818
+ */
819
+ getTokensForMode?: (mode: 'light' | 'dark') => ThemeTokens;
820
+ /**
821
+ * Optional initialization function
822
+ * Called when the theme is loaded
823
+ */
824
+ initialize?: () => void | Promise<void>;
825
+ }
826
+ /**
827
+ * Standard export type for theme plugins
828
+ */
829
+ interface ThemePluginExport {
830
+ /** The theme plugin instance */
831
+ plugin: ThemePlugin;
832
+ }
833
+
834
+ export type { AttachmentSupport as A, CheapModelConfig as C, EmbeddingModelInfo as E, FontDefinition as F, ImageGenerationModelInfo as I, LLMProviderPlugin as L, ModelInfo as M, ProviderMetadata as P, Spacing as S, ToolFormatType as T, ProviderConfigRequirements as a, ProviderCapabilities as b, ImageProviderConstraints as c, IconProps as d, ProviderPluginExport as e, MessageFormatSupport as f, PluginCapability as g, PluginCategory as h, PluginStatus as i, PluginAuthor as j, PluginCompatibility as k, ProviderConfig as l, PluginPermissions as m, PluginManifest as n, InstalledPluginInfo as o, ColorPalette as p, Typography as q, Effects as r, ThemeTokens as s, EmbeddedFont as t, ThemeMetadata as u, ThemePlugin as v, ThemePluginExport as w };