vanilla-agent 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.ts CHANGED
@@ -156,6 +156,24 @@ export type AgentWidgetTheme = {
156
156
  radiusLg?: string;
157
157
  launcherRadius?: string;
158
158
  buttonRadius?: string;
159
+ /**
160
+ * Border style for the chat panel container.
161
+ * @example "1px solid #e5e7eb" | "none"
162
+ * @default "1px solid var(--tvw-cw-border)"
163
+ */
164
+ panelBorder?: string;
165
+ /**
166
+ * Box shadow for the chat panel container.
167
+ * @example "0 25px 50px -12px rgba(0,0,0,0.25)" | "none"
168
+ * @default "0 25px 50px -12px rgba(0,0,0,0.25)"
169
+ */
170
+ panelShadow?: string;
171
+ /**
172
+ * Border radius for the chat panel container.
173
+ * @example "16px" | "0"
174
+ * @default "16px"
175
+ */
176
+ panelBorderRadius?: string;
159
177
  };
160
178
 
161
179
  export type AgentWidgetLauncherConfig = {
@@ -170,6 +188,35 @@ export type AgentWidgetLauncherConfig = {
170
188
  position?: "bottom-right" | "bottom-left" | "top-right" | "top-left";
171
189
  autoExpand?: boolean;
172
190
  width?: string;
191
+ /**
192
+ * When true, the widget panel will fill the full height of its container.
193
+ * Useful for sidebar layouts where the chat should take up the entire viewport height.
194
+ * The widget will use flex layout to ensure header stays at top, messages scroll in middle,
195
+ * and composer stays fixed at bottom.
196
+ *
197
+ * @default false
198
+ */
199
+ fullHeight?: boolean;
200
+ /**
201
+ * When true, the widget panel will be positioned as a sidebar flush with the viewport edges.
202
+ * The panel will have:
203
+ * - No border-radius (square corners)
204
+ * - No margins (flush with top, left/right, and bottom edges)
205
+ * - Full viewport height
206
+ * - Subtle shadow on the edge facing the content
207
+ * - No border between footer and messages
208
+ *
209
+ * Use with `position` to control which side ('bottom-left' for left sidebar, 'bottom-right' for right sidebar).
210
+ * Automatically enables fullHeight when true.
211
+ *
212
+ * @default false
213
+ */
214
+ sidebarMode?: boolean;
215
+ /**
216
+ * Width of the sidebar panel when sidebarMode is true.
217
+ * @default "420px"
218
+ */
219
+ sidebarWidth?: string;
173
220
  callToActionIconText?: string;
174
221
  callToActionIconName?: string;
175
222
  callToActionIconColor?: string;
@@ -214,6 +261,7 @@ export type AgentWidgetSendButtonConfig = {
214
261
 
215
262
  export type AgentWidgetClearChatConfig = {
216
263
  enabled?: boolean;
264
+ placement?: "inline" | "top-right";
217
265
  iconName?: string;
218
266
  iconColor?: string;
219
267
  backgroundColor?: string;
@@ -339,10 +387,240 @@ export interface AgentWidgetStreamParser {
339
387
  }
340
388
 
341
389
 
390
+ /**
391
+ * Component renderer function signature for custom components
392
+ */
393
+ export type AgentWidgetComponentRenderer = (
394
+ props: Record<string, unknown>,
395
+ context: {
396
+ message: AgentWidgetMessage;
397
+ config: AgentWidgetConfig;
398
+ updateProps: (newProps: Record<string, unknown>) => void;
399
+ }
400
+ ) => HTMLElement;
401
+
402
+ /**
403
+ * Result from custom SSE event parser
404
+ */
405
+ export type AgentWidgetSSEEventResult = {
406
+ /** Text content to display */
407
+ text?: string;
408
+ /** Whether the stream is complete */
409
+ done?: boolean;
410
+ /** Error message if an error occurred */
411
+ error?: string;
412
+ } | null;
413
+
414
+ /**
415
+ * Custom SSE event parser function
416
+ * Allows transforming non-standard SSE event formats to vanilla-agent's expected format
417
+ */
418
+ export type AgentWidgetSSEEventParser = (
419
+ eventData: unknown
420
+ ) => AgentWidgetSSEEventResult | Promise<AgentWidgetSSEEventResult>;
421
+
422
+ /**
423
+ * Custom fetch function for full control over API requests
424
+ * Use this for custom authentication, request transformation, etc.
425
+ */
426
+ export type AgentWidgetCustomFetch = (
427
+ url: string,
428
+ init: RequestInit,
429
+ payload: AgentWidgetRequestPayload
430
+ ) => Promise<Response>;
431
+
432
+ /**
433
+ * Dynamic headers function - called before each request
434
+ */
435
+ export type AgentWidgetHeadersFunction = () => Record<string, string> | Promise<Record<string, string>>;
436
+
437
+ // ============================================================================
438
+ // Layout Configuration Types
439
+ // ============================================================================
440
+
441
+ /**
442
+ * Context provided to header render functions
443
+ */
444
+ export type HeaderRenderContext = {
445
+ config: AgentWidgetConfig;
446
+ onClose?: () => void;
447
+ onClearChat?: () => void;
448
+ };
449
+
450
+ /**
451
+ * Context provided to message render functions
452
+ */
453
+ export type MessageRenderContext = {
454
+ message: AgentWidgetMessage;
455
+ config: AgentWidgetConfig;
456
+ streaming: boolean;
457
+ };
458
+
459
+ /**
460
+ * Context provided to slot render functions
461
+ */
462
+ export type SlotRenderContext = {
463
+ config: AgentWidgetConfig;
464
+ defaultContent: () => HTMLElement | null;
465
+ };
466
+
467
+ /**
468
+ * Header layout configuration
469
+ * Allows customization of the header section appearance and behavior
470
+ */
471
+ export type AgentWidgetHeaderLayoutConfig = {
472
+ /**
473
+ * Layout preset: "default" | "minimal" | "expanded"
474
+ * - default: Standard layout with icon, title, subtitle, and buttons
475
+ * - minimal: Simplified layout with just title and close button
476
+ * - expanded: Full branding area with additional content space
477
+ */
478
+ layout?: "default" | "minimal" | "expanded";
479
+ /** Show/hide the header icon */
480
+ showIcon?: boolean;
481
+ /** Show/hide the title */
482
+ showTitle?: boolean;
483
+ /** Show/hide the subtitle */
484
+ showSubtitle?: boolean;
485
+ /** Show/hide the close button */
486
+ showCloseButton?: boolean;
487
+ /** Show/hide the clear chat button */
488
+ showClearChat?: boolean;
489
+ /**
490
+ * Custom renderer for complete header override
491
+ * When provided, replaces the entire header with custom content
492
+ */
493
+ render?: (context: HeaderRenderContext) => HTMLElement;
494
+ };
495
+
496
+ /**
497
+ * Avatar configuration for message bubbles
498
+ */
499
+ export type AgentWidgetAvatarConfig = {
500
+ /** Whether to show avatars */
501
+ show?: boolean;
502
+ /** Position of avatar relative to message bubble */
503
+ position?: "left" | "right";
504
+ /** URL or emoji for user avatar */
505
+ userAvatar?: string;
506
+ /** URL or emoji for assistant avatar */
507
+ assistantAvatar?: string;
508
+ };
509
+
510
+ /**
511
+ * Timestamp configuration for message bubbles
512
+ */
513
+ export type AgentWidgetTimestampConfig = {
514
+ /** Whether to show timestamps */
515
+ show?: boolean;
516
+ /** Position of timestamp relative to message */
517
+ position?: "inline" | "below";
518
+ /** Custom formatter for timestamp display */
519
+ format?: (date: Date) => string;
520
+ };
521
+
522
+ /**
523
+ * Message layout configuration
524
+ * Allows customization of how chat messages are displayed
525
+ */
526
+ export type AgentWidgetMessageLayoutConfig = {
527
+ /**
528
+ * Layout preset: "bubble" | "flat" | "minimal"
529
+ * - bubble: Standard chat bubble appearance (default)
530
+ * - flat: Flat messages without bubble styling
531
+ * - minimal: Minimal styling with reduced padding/borders
532
+ */
533
+ layout?: "bubble" | "flat" | "minimal";
534
+ /** Avatar configuration */
535
+ avatar?: AgentWidgetAvatarConfig;
536
+ /** Timestamp configuration */
537
+ timestamp?: AgentWidgetTimestampConfig;
538
+ /** Group consecutive messages from the same role */
539
+ groupConsecutive?: boolean;
540
+ /**
541
+ * Custom renderer for user messages
542
+ * When provided, replaces the default user message rendering
543
+ */
544
+ renderUserMessage?: (context: MessageRenderContext) => HTMLElement;
545
+ /**
546
+ * Custom renderer for assistant messages
547
+ * When provided, replaces the default assistant message rendering
548
+ */
549
+ renderAssistantMessage?: (context: MessageRenderContext) => HTMLElement;
550
+ };
551
+
552
+ /**
553
+ * Available layout slots for content injection
554
+ */
555
+ export type WidgetLayoutSlot =
556
+ | "header-left"
557
+ | "header-center"
558
+ | "header-right"
559
+ | "body-top"
560
+ | "messages"
561
+ | "body-bottom"
562
+ | "footer-top"
563
+ | "composer"
564
+ | "footer-bottom";
565
+
566
+ /**
567
+ * Slot renderer function signature
568
+ * Returns HTMLElement to render in the slot, or null to use default content
569
+ */
570
+ export type SlotRenderer = (context: SlotRenderContext) => HTMLElement | null;
571
+
572
+ /**
573
+ * Main layout configuration
574
+ * Provides comprehensive control over widget layout and appearance
575
+ *
576
+ * @example
577
+ * ```typescript
578
+ * config: {
579
+ * layout: {
580
+ * header: { layout: "minimal" },
581
+ * messages: {
582
+ * avatar: { show: true, assistantAvatar: "/bot.png" },
583
+ * timestamp: { show: true, position: "below" }
584
+ * },
585
+ * slots: {
586
+ * "footer-top": () => {
587
+ * const el = document.createElement("div");
588
+ * el.textContent = "Powered by AI";
589
+ * return el;
590
+ * }
591
+ * }
592
+ * }
593
+ * }
594
+ * ```
595
+ */
596
+ export type AgentWidgetLayoutConfig = {
597
+ /** Header layout configuration */
598
+ header?: AgentWidgetHeaderLayoutConfig;
599
+ /** Message layout configuration */
600
+ messages?: AgentWidgetMessageLayoutConfig;
601
+ /** Slot renderers for custom content injection */
602
+ slots?: Partial<Record<WidgetLayoutSlot, SlotRenderer>>;
603
+ };
604
+
342
605
  export type AgentWidgetConfig = {
343
606
  apiUrl?: string;
344
607
  flowId?: string;
608
+ /**
609
+ * Static headers to include with each request.
610
+ * For dynamic headers (e.g., auth tokens), use `getHeaders` instead.
611
+ */
345
612
  headers?: Record<string, string>;
613
+ /**
614
+ * Dynamic headers function - called before each request.
615
+ * Useful for adding auth tokens that may change.
616
+ * @example
617
+ * ```typescript
618
+ * getHeaders: async () => ({
619
+ * 'Authorization': `Bearer ${await getAuthToken()}`
620
+ * })
621
+ * ```
622
+ */
623
+ getHeaders?: AgentWidgetHeadersFunction;
346
624
  copy?: {
347
625
  welcomeTitle?: string;
348
626
  welcomeSubtitle?: string;
@@ -374,6 +652,32 @@ export type AgentWidgetConfig = {
374
652
  actionParsers?: AgentWidgetActionParser[];
375
653
  actionHandlers?: AgentWidgetActionHandler[];
376
654
  storageAdapter?: AgentWidgetStorageAdapter;
655
+ /**
656
+ * Registry of custom components that can be rendered from JSON directives.
657
+ * Components are registered by name and can be invoked via JSON responses
658
+ * with the format: `{"component": "ComponentName", "props": {...}}`
659
+ *
660
+ * @example
661
+ * ```typescript
662
+ * config: {
663
+ * components: {
664
+ * ProductCard: (props, context) => {
665
+ * const card = document.createElement("div");
666
+ * card.innerHTML = `<h3>${props.title}</h3><p>$${props.price}</p>`;
667
+ * return card;
668
+ * }
669
+ * }
670
+ * }
671
+ * ```
672
+ */
673
+ components?: Record<string, AgentWidgetComponentRenderer>;
674
+ /**
675
+ * Enable component streaming. When true, component props will be updated
676
+ * incrementally as they stream in from the JSON response.
677
+ *
678
+ * @default true
679
+ */
680
+ enableComponentStreaming?: boolean;
377
681
  /**
378
682
  * Custom stream parser for extracting text from streaming structured responses.
379
683
  * Handles incremental parsing of JSON, XML, or other formats.
@@ -430,6 +734,83 @@ export type AgentWidgetConfig = {
430
734
  * ```
431
735
  */
432
736
  parserType?: "plain" | "json" | "regex-json" | "xml";
737
+ /**
738
+ * Custom fetch function for full control over API requests.
739
+ * Use this for custom authentication, request/response transformation, etc.
740
+ *
741
+ * When provided, this function is called instead of the default fetch.
742
+ * You receive the URL, RequestInit, and the payload that would be sent.
743
+ *
744
+ * @example
745
+ * ```typescript
746
+ * config: {
747
+ * customFetch: async (url, init, payload) => {
748
+ * // Transform request for your API format
749
+ * const myPayload = {
750
+ * flow: { id: 'my-flow-id' },
751
+ * messages: payload.messages,
752
+ * options: { stream_response: true }
753
+ * };
754
+ *
755
+ * // Add auth header
756
+ * const token = await getAuthToken();
757
+ *
758
+ * return fetch('/my-api/dispatch', {
759
+ * method: 'POST',
760
+ * headers: {
761
+ * 'Content-Type': 'application/json',
762
+ * 'Authorization': `Bearer ${token}`
763
+ * },
764
+ * body: JSON.stringify(myPayload),
765
+ * signal: init.signal
766
+ * });
767
+ * }
768
+ * }
769
+ * ```
770
+ */
771
+ customFetch?: AgentWidgetCustomFetch;
772
+ /**
773
+ * Custom SSE event parser for non-standard streaming response formats.
774
+ *
775
+ * Use this when your API returns SSE events in a different format than expected.
776
+ * Return `{ text }` for text chunks, `{ done: true }` for completion,
777
+ * `{ error }` for errors, or `null` to ignore the event.
778
+ *
779
+ * @example
780
+ * ```typescript
781
+ * // For Travrse API format
782
+ * config: {
783
+ * parseSSEEvent: (data) => {
784
+ * if (data.type === 'step_chunk' && data.chunk) {
785
+ * return { text: data.chunk };
786
+ * }
787
+ * if (data.type === 'flow_complete') {
788
+ * return { done: true };
789
+ * }
790
+ * if (data.type === 'step_error') {
791
+ * return { error: data.error };
792
+ * }
793
+ * return null; // Ignore other events
794
+ * }
795
+ * }
796
+ * ```
797
+ */
798
+ parseSSEEvent?: AgentWidgetSSEEventParser;
799
+ /**
800
+ * Layout configuration for customizing widget appearance and structure.
801
+ * Provides control over header, messages, and content slots.
802
+ *
803
+ * @example
804
+ * ```typescript
805
+ * config: {
806
+ * layout: {
807
+ * header: { layout: "minimal" },
808
+ * messages: { avatar: { show: true } }
809
+ * }
810
+ * }
811
+ * ```
812
+ */
813
+ layout?: AgentWidgetLayoutConfig;
433
814
  };
434
815
 
435
816
  export type AgentWidgetMessageRole = "user" | "assistant" | "system";