vanilla-agent 1.3.0 → 1.4.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/README.md CHANGED
@@ -129,6 +129,18 @@ chat.stopVoiceRecognition()
129
129
 
130
130
  All hook methods return `boolean` indicating success (`true`) or failure (`false`). They will automatically open the widget if it's currently closed (when launcher is enabled).
131
131
 
132
+ #### Clear chat
133
+
134
+ ```ts
135
+ const chat = initAgentWidget({
136
+ target: '#launcher-root',
137
+ config: { /* ... */ }
138
+ })
139
+
140
+ // Clear all messages programmatically
141
+ chat.clearChat()
142
+ ```
143
+
132
144
  #### Accessing from window
133
145
 
134
146
  To access the controller globally (e.g., from browser console or external scripts), use the `windowKey` option:
@@ -184,6 +196,32 @@ const chat = initAgentWidget({ /* ... */ })
184
196
  window.chatController = chat
185
197
  ```
186
198
 
199
+ ### Events
200
+
201
+ The widget dispatches custom events that you can listen to for integration with your application:
202
+
203
+ #### `vanilla-agent:clear-chat`
204
+
205
+ Dispatched when the user clicks the "Clear chat" button or when `chat.clearChat()` is called programmatically.
206
+
207
+ ```ts
208
+ window.addEventListener("vanilla-agent:clear-chat", (event) => {
209
+ console.log("Chat cleared at:", event.detail.timestamp);
210
+ // Clear your localStorage, reset state, etc.
211
+ });
212
+ ```
213
+
214
+ **Event detail:**
215
+ - `timestamp`: ISO timestamp string of when the chat was cleared
216
+
217
+ **Use cases:**
218
+ - Clear localStorage chat history
219
+ - Reset application state
220
+ - Track analytics events
221
+ - Sync with backend
222
+
223
+ **Note:** The widget automatically clears the `"vanilla-agent-chat-history"` localStorage key by default when chat is cleared. If you set `clearChatHistoryStorageKey` in the config, it will also clear that additional key. You can still listen to this event for additional custom behavior.
224
+
187
225
  ### Travrse adapter
188
226
 
189
227
  This package ships with a Travrse adapter by default. The proxy handles all flow configuration, keeping the client lightweight and flexible.
@@ -228,7 +266,9 @@ The easiest way is to use the automatic installer script. It handles loading CSS
228
266
  theme: {
229
267
  accent: '#2563eb',
230
268
  surface: '#ffffff'
231
- }
269
+ },
270
+ // Optional: configure stream parser for JSON/XML responses
271
+ // streamParser: () => window.AgentWidget.createJsonStreamParser()
232
272
  }
233
273
  };
234
274
  </script>
@@ -286,7 +326,9 @@ For more control, manually load CSS and JavaScript:
286
326
  theme: {
287
327
  accent: '#111827',
288
328
  surface: '#f5f5f5'
289
- }
329
+ },
330
+ // Optional: configure stream parser for JSON/XML responses
331
+ streamParser: window.AgentWidget.createJsonStreamParser // or createXmlParser, createPlainTextParser
290
332
  }
291
333
  });
292
334
 
@@ -308,7 +350,14 @@ Replace `VERSION` with `latest` for auto-updates, or a specific version like `0.
308
350
  - `index.global.js` - Widget JavaScript (IIFE format)
309
351
  - `install.global.js` - Automatic installer script
310
352
 
311
- The script build exposes a `window.AgentWidget` global with `initAgentWidget()` and other exports.
353
+ The script build exposes a `window.AgentWidget` global with `initAgentWidget()` and other exports, including parser functions:
354
+
355
+ - `window.AgentWidget.initAgentWidget()` - Initialize the widget
356
+ - `window.AgentWidget.createPlainTextParser()` - Plain text parser (default)
357
+ - `window.AgentWidget.createJsonStreamParser()` - JSON parser using schema-stream
358
+ - `window.AgentWidget.createXmlParser()` - XML parser
359
+ - `window.AgentWidget.markdownPostprocessor()` - Markdown postprocessor
360
+ - `window.AgentWidget.directivePostprocessor()` - Directive postprocessor
312
361
 
313
362
  ### Using default configuration
314
363
 
@@ -356,12 +405,179 @@ This ensures all configuration values are set to sensible defaults while allowin
356
405
  | `initialMessages` | `AgentWidgetMessage[]` | Seed the conversation transcript. |
357
406
  | `suggestionChips` | `string[]` | Render quick reply buttons above the composer. |
358
407
  | `postprocessMessage` | `(ctx) => string` | Transform message text before it renders (return HTML). Combine with `markdownPostprocessor` for rich output. |
408
+ | `streamParser` | `() => AgentWidgetStreamParser` | Custom stream parser for detecting formats and extracting text from streaming responses. Handles JSON, XML, or custom formats. See [Stream Parser Configuration](#stream-parser-configuration) below. |
409
+ | `clearChatHistoryStorageKey` | `string` | Additional localStorage key to clear when the clear chat button is clicked. The widget automatically clears `"vanilla-agent-chat-history"` by default. Use this option to clear additional keys (e.g., if you're using a custom storage key). |
359
410
  | `formEndpoint` | `string` | Endpoint used by built-in directives (defaults to `/form`). |
360
411
  | `launcherWidth` | `string` | CSS width applied to the floating launcher panel (e.g. `320px`, `90vw`). Defaults to `min(400px, calc(100vw - 24px))`. |
361
412
  | `debug` | `boolean` | Emits verbose logs to `console`. |
362
413
 
363
414
  All options are safe to mutate via `initAgentWidget(...).update(newConfig)`.
364
415
 
416
+ ### Stream Parser Configuration
417
+
418
+ The widget can parse structured responses (JSON, XML, etc.) that stream in chunk by chunk, extracting the `text` field for display. By default, it uses a schema-stream based JSON parser. You can provide a custom parser to handle different formats, structures, or parsing strategies.
419
+
420
+ **Key benefits of the unified stream parser:**
421
+ - **Format detection**: Automatically detects if content matches your parser's format
422
+ - **Extensible**: Handle JSON, XML, or any custom structured format
423
+ - **Incremental parsing**: Extract text as it streams in, not just when complete
424
+
425
+ **Using built-in parsers with ESM/Modules:**
426
+
427
+ ```javascript
428
+ import { initAgentWidget, createPlainTextParser, createJsonStreamParser, createXmlParser } from 'vanilla-agent';
429
+
430
+ const controller = initAgentWidget({
431
+ target: '#chat-root',
432
+ config: {
433
+ apiUrl: '/api/chat/dispatch',
434
+ streamParser: createJsonStreamParser // Use JSON parser
435
+ // Or: createXmlParser for XML, createPlainTextParser for plain text (default)
436
+ }
437
+ });
438
+ ```
439
+
440
+ **Using built-in parsers with CDN Script Tags:**
441
+
442
+ ```html
443
+ <script src="https://cdn.jsdelivr.net/npm/vanilla-agent@latest/dist/index.global.js"></script>
444
+ <script>
445
+ window.AgentWidget.initAgentWidget({
446
+ target: '#chat-root',
447
+ config: {
448
+ apiUrl: '/api/chat/dispatch',
449
+ streamParser: window.AgentWidget.createJsonStreamParser // JSON parser
450
+ // Or: window.AgentWidget.createXmlParser for XML
451
+ // Or: window.AgentWidget.createPlainTextParser for plain text (default)
452
+ }
453
+ });
454
+ </script>
455
+ ```
456
+
457
+ **Using with automatic installer script:**
458
+
459
+ ```html
460
+ <script>
461
+ window.siteAgentConfig = {
462
+ target: 'body',
463
+ config: {
464
+ apiUrl: '/api/chat/dispatch',
465
+ // Note: streamParser must be set after the script loads, or use a function
466
+ streamParser: function() {
467
+ return window.AgentWidget.createJsonStreamParser();
468
+ }
469
+ }
470
+ };
471
+ </script>
472
+ <script src="https://cdn.jsdelivr.net/npm/vanilla-agent@latest/dist/install.global.js"></script>
473
+ ```
474
+
475
+ Alternatively, you can set it after the script loads:
476
+
477
+ ```html
478
+ <script>
479
+ window.siteAgentConfig = {
480
+ target: 'body',
481
+ config: {
482
+ apiUrl: '/api/chat/dispatch'
483
+ }
484
+ };
485
+ </script>
486
+ <script src="https://cdn.jsdelivr.net/npm/vanilla-agent@latest/dist/install.global.js"></script>
487
+ <script>
488
+ // Set parser after AgentWidget is loaded
489
+ if (window.siteAgentConfig && window.AgentWidget) {
490
+ window.siteAgentConfig.config.streamParser = window.AgentWidget.createJsonStreamParser;
491
+ }
492
+ </script>
493
+ ```
494
+
495
+ **Custom JSON parser example:**
496
+
497
+ ```javascript
498
+ const jsonParser = () => {
499
+ let extractedText = null;
500
+
501
+ return {
502
+ // Extract text field from JSON as it streams in
503
+ // Return null if not JSON or text not available yet
504
+ processChunk(accumulatedContent) {
505
+ const trimmed = accumulatedContent.trim();
506
+ // Return null if not JSON format
507
+ if (!trimmed.startsWith('{') && !trimmed.startsWith('[')) {
508
+ return null;
509
+ }
510
+
511
+ const match = accumulatedContent.match(/"text"\s*:\s*"([^"]*(?:\\.[^"]*)*)"/);
512
+ if (match) {
513
+ extractedText = match[1].replace(/\\"/g, '"').replace(/\\n/g, '\n');
514
+ return extractedText;
515
+ }
516
+ return null;
517
+ },
518
+
519
+ getExtractedText() {
520
+ return extractedText;
521
+ }
522
+ };
523
+ };
524
+
525
+ const controller = initAgentWidget({
526
+ target: '#chat-root',
527
+ config: {
528
+ apiUrl: '/api/chat/dispatch',
529
+ streamParser: jsonParser
530
+ }
531
+ });
532
+ ```
533
+
534
+ **Custom XML parser example:**
535
+
536
+ ```javascript
537
+ const xmlParser = () => {
538
+ let extractedText = null;
539
+
540
+ return {
541
+ processChunk(accumulatedContent) {
542
+ // Return null if not XML format
543
+ if (!accumulatedContent.trim().startsWith('<')) {
544
+ return null;
545
+ }
546
+
547
+ // Extract text from <text>...</text> tags
548
+ const match = accumulatedContent.match(/<text[^>]*>([\s\S]*?)<\/text>/);
549
+ if (match) {
550
+ extractedText = match[1];
551
+ return extractedText;
552
+ }
553
+ return null;
554
+ },
555
+
556
+ getExtractedText() {
557
+ return extractedText;
558
+ }
559
+ };
560
+ };
561
+ ```
562
+
563
+ **Parser interface:**
564
+
565
+ ```typescript
566
+ interface AgentWidgetStreamParser {
567
+ // Process a chunk and return extracted text (if available)
568
+ // Return null if the content doesn't match this parser's format or text is not yet available
569
+ processChunk(accumulatedContent: string): Promise<string | null> | string | null;
570
+
571
+ // Get the currently extracted text (may be partial)
572
+ getExtractedText(): string | null;
573
+
574
+ // Optional cleanup when parsing is complete
575
+ close?(): Promise<void> | void;
576
+ }
577
+ ```
578
+
579
+ The parser's `processChunk` method is called for each chunk. If the content matches your parser's format, return the extracted text. If it doesn't match (or text isn't available yet), return `null` and the content will be treated as plain text. This allows you to display the text value as it streams in without showing raw structured characters.
580
+
365
581
  ### Optional proxy server
366
582
 
367
583
  The proxy server handles flow configuration and forwards requests to Travrse. You can configure it in three ways: