@makemore/agent-frontend 1.1.0 â 1.3.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 +83 -1
- package/dist/chat-widget-markdown.js +110 -0
- package/dist/chat-widget.css +186 -0
- package/dist/chat-widget.js +104 -22
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -61,6 +61,28 @@ Then include in your HTML:
|
|
|
61
61
|
<script src="https://cdn.jsdelivr.net/npm/@makemore/agent-frontend/dist/chat-widget.js"></script>
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
### Optional: Enhanced Markdown Support
|
|
65
|
+
|
|
66
|
+
For full-featured markdown rendering (tables, code blocks with syntax highlighting, etc.), include the optional markdown addon:
|
|
67
|
+
|
|
68
|
+
```html
|
|
69
|
+
<!-- Core widget -->
|
|
70
|
+
<link rel="stylesheet" href="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget.css">
|
|
71
|
+
<script src="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget.js"></script>
|
|
72
|
+
|
|
73
|
+
<!-- Optional: Enhanced markdown with marked.js -->
|
|
74
|
+
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
75
|
+
<script src="https://unpkg.com/@makemore/agent-frontend/dist/chat-widget-markdown.js"></script>
|
|
76
|
+
|
|
77
|
+
<!-- Optional: Syntax highlighting for code blocks -->
|
|
78
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11/styles/github-dark.min.css">
|
|
79
|
+
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11/lib/core.min.js"></script>
|
|
80
|
+
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11/lib/languages/javascript.min.js"></script>
|
|
81
|
+
<script src="https://cdn.jsdelivr.net/npm/highlight.js@11/lib/languages/python.min.js"></script>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
The widget automatically detects and uses the enhanced markdown parser if available. Without it, a basic markdown parser is used.
|
|
85
|
+
|
|
64
86
|
## Quick Start
|
|
65
87
|
|
|
66
88
|
### Initialize the widget
|
|
@@ -115,6 +137,29 @@ Then include in your HTML:
|
|
|
115
137
|
| `conversationIdKey` | string | `'chat_widget_conversation_id'` | localStorage key for conversation ID |
|
|
116
138
|
| `sessionTokenKey` | string | `'chat_widget_session_token'` | localStorage key for session token |
|
|
117
139
|
| `apiPaths` | object | See below | API endpoint paths (customizable for different backends) |
|
|
140
|
+
| `autoRunMode` | string | `'automatic'` | Demo flow mode: `'automatic'`, `'confirm'`, or `'manual'` |
|
|
141
|
+
| `autoRunDelay` | number | `1000` | Delay in milliseconds before auto-generating next message (automatic mode) |
|
|
142
|
+
|
|
143
|
+
### Demo Flow Control
|
|
144
|
+
|
|
145
|
+
The widget supports three modes for demo flows:
|
|
146
|
+
|
|
147
|
+
- **Automatic** (`autoRunMode: 'automatic'`): Continuously generates customer responses with a configurable delay
|
|
148
|
+
- **Confirm Next** (`autoRunMode: 'confirm'`): Pauses after each assistant response and waits for user to click "Continue"
|
|
149
|
+
- **Manual** (`autoRunMode: 'manual'`): Stops auto-generation; user must manually type responses
|
|
150
|
+
|
|
151
|
+
These settings can be changed in real-time via the demo controls dropdown (visible when a demo is running).
|
|
152
|
+
|
|
153
|
+
```javascript
|
|
154
|
+
ChatWidget.init({
|
|
155
|
+
autoRunMode: 'confirm', // Start in confirm mode
|
|
156
|
+
autoRunDelay: 2000, // 2 second delay in automatic mode
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Change mode programmatically
|
|
160
|
+
ChatWidget.setAutoRunMode('automatic');
|
|
161
|
+
ChatWidget.setAutoRunDelay(500); // 0.5 second delay
|
|
162
|
+
```
|
|
118
163
|
|
|
119
164
|
### API Paths Configuration
|
|
120
165
|
|
|
@@ -191,9 +236,18 @@ ChatWidget.clearMessages();
|
|
|
191
236
|
// Start a demo flow
|
|
192
237
|
ChatWidget.startDemoFlow('quote');
|
|
193
238
|
|
|
194
|
-
// Stop
|
|
239
|
+
// Stop demo flow
|
|
195
240
|
ChatWidget.stopAutoRun();
|
|
196
241
|
|
|
242
|
+
// Continue demo flow (when in confirm mode and paused)
|
|
243
|
+
ChatWidget.continueAutoRun();
|
|
244
|
+
|
|
245
|
+
// Change demo flow mode
|
|
246
|
+
ChatWidget.setAutoRunMode('automatic'); // 'automatic', 'confirm', or 'manual'
|
|
247
|
+
|
|
248
|
+
// Change auto-run delay (in milliseconds)
|
|
249
|
+
ChatWidget.setAutoRunDelay(2000);
|
|
250
|
+
|
|
197
251
|
// Remove the widget from the page
|
|
198
252
|
ChatWidget.destroy();
|
|
199
253
|
|
|
@@ -204,6 +258,34 @@ const state = ChatWidget.getState();
|
|
|
204
258
|
const config = ChatWidget.getConfig();
|
|
205
259
|
```
|
|
206
260
|
|
|
261
|
+
## Markdown Support
|
|
262
|
+
|
|
263
|
+
The widget includes built-in markdown rendering for assistant messages:
|
|
264
|
+
|
|
265
|
+
### Basic Markdown (Built-in)
|
|
266
|
+
|
|
267
|
+
The widget includes a lightweight markdown parser that supports:
|
|
268
|
+
- **Bold** (`**text**` or `__text__`)
|
|
269
|
+
- *Italic* (`*text*` or `_text_`)
|
|
270
|
+
- `Inline code` (`` `code` ``)
|
|
271
|
+
- [Links](url) (`[text](url)`)
|
|
272
|
+
- Lists (`- item` or `* item`)
|
|
273
|
+
- Line breaks
|
|
274
|
+
|
|
275
|
+
### Enhanced Markdown (Optional)
|
|
276
|
+
|
|
277
|
+
Include `chat-widget-markdown.js` for full-featured markdown:
|
|
278
|
+
- **Tables** - Full GFM table support
|
|
279
|
+
- **Code blocks** - Multi-line code with syntax highlighting
|
|
280
|
+
- **Blockquotes** - `> quoted text`
|
|
281
|
+
- **Headings** - `# H1` through `###### H6`
|
|
282
|
+
- **Horizontal rules** - `---` or `***`
|
|
283
|
+
- **Task lists** - `- [ ] todo` and `- [x] done`
|
|
284
|
+
- **Strikethrough** - `~~text~~`
|
|
285
|
+
|
|
286
|
+
**Supported languages for syntax highlighting:**
|
|
287
|
+
Add highlight.js language modules as needed (JavaScript, Python, TypeScript, Go, Rust, etc.)
|
|
288
|
+
|
|
207
289
|
## Backend Requirements
|
|
208
290
|
|
|
209
291
|
The widget expects a backend API with the following endpoints:
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat Widget - Enhanced Markdown Support
|
|
3
|
+
*
|
|
4
|
+
* This optional addon replaces the basic markdown parser with marked.js
|
|
5
|
+
* for full-featured markdown rendering including tables, code blocks with
|
|
6
|
+
* syntax highlighting, and more.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* 1. Include marked.js (and optionally highlight.js for syntax highlighting)
|
|
10
|
+
* 2. Include this file AFTER chat-widget.js
|
|
11
|
+
* 3. Initialize the widget normally
|
|
12
|
+
*
|
|
13
|
+
* Example:
|
|
14
|
+
* <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
15
|
+
* <script src="https://cdn.jsdelivr.net/npm/highlight.js@11/lib/core.min.js"></script>
|
|
16
|
+
* <script src="https://cdn.jsdelivr.net/npm/highlight.js@11/lib/languages/javascript.min.js"></script>
|
|
17
|
+
* <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/highlight.js@11/styles/github-dark.min.css">
|
|
18
|
+
* <script src="chat-widget.js"></script>
|
|
19
|
+
* <script src="chat-widget-markdown.js"></script>
|
|
20
|
+
*/
|
|
21
|
+
(function(global) {
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
// Check if ChatWidget is available
|
|
25
|
+
if (!global.ChatWidget) {
|
|
26
|
+
console.error('[ChatWidget Markdown] ChatWidget must be loaded before chat-widget-markdown.js');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Check if marked is available
|
|
31
|
+
if (typeof marked === 'undefined') {
|
|
32
|
+
console.warn('[ChatWidget Markdown] marked.js not found. Install with: npm install marked or include from CDN');
|
|
33
|
+
console.warn('[ChatWidget Markdown] Falling back to basic markdown parser');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log('[ChatWidget Markdown] Enhanced markdown support enabled');
|
|
38
|
+
|
|
39
|
+
// Configure marked
|
|
40
|
+
const markedOptions = {
|
|
41
|
+
breaks: true,
|
|
42
|
+
gfm: true,
|
|
43
|
+
headerIds: false,
|
|
44
|
+
mangle: false,
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
// Configure syntax highlighting if highlight.js is available
|
|
48
|
+
if (typeof hljs !== 'undefined') {
|
|
49
|
+
console.log('[ChatWidget Markdown] Syntax highlighting enabled');
|
|
50
|
+
markedOptions.highlight = function(code, lang) {
|
|
51
|
+
if (lang && hljs.getLanguage(lang)) {
|
|
52
|
+
try {
|
|
53
|
+
return hljs.highlight(code, { language: lang }).value;
|
|
54
|
+
} catch (err) {
|
|
55
|
+
console.error('[ChatWidget Markdown] Highlight error:', err);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return code;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
marked.setOptions(markedOptions);
|
|
63
|
+
|
|
64
|
+
// Enhanced markdown parser using marked.js
|
|
65
|
+
function enhancedParseMarkdown(text) {
|
|
66
|
+
if (!text) return '';
|
|
67
|
+
|
|
68
|
+
try {
|
|
69
|
+
// Parse markdown with marked
|
|
70
|
+
let html = marked.parse(text);
|
|
71
|
+
|
|
72
|
+
// Sanitize links to open in new tab
|
|
73
|
+
html = html.replace(/<a href=/g, '<a target="_blank" rel="noopener noreferrer" href=');
|
|
74
|
+
|
|
75
|
+
return html;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
console.error('[ChatWidget Markdown] Parse error:', err);
|
|
78
|
+
// Fallback to escaped text
|
|
79
|
+
const div = document.createElement('div');
|
|
80
|
+
div.textContent = text;
|
|
81
|
+
return div.innerHTML.replace(/\n/g, '<br>');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Store reference to original init
|
|
86
|
+
const originalInit = global.ChatWidget.init;
|
|
87
|
+
|
|
88
|
+
// Override init to inject enhanced markdown parser
|
|
89
|
+
global.ChatWidget.init = function(userConfig = {}) {
|
|
90
|
+
// Call original init
|
|
91
|
+
originalInit.call(this, userConfig);
|
|
92
|
+
|
|
93
|
+
// Inject enhanced markdown parser
|
|
94
|
+
// We need to override the internal parseMarkdown function
|
|
95
|
+
// This is done by monkey-patching the render cycle
|
|
96
|
+
console.log('[ChatWidget Markdown] Markdown parser enhanced with marked.js');
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Expose the enhanced parser for internal use
|
|
100
|
+
// The widget will need to check for this and use it if available
|
|
101
|
+
global.ChatWidget._enhancedMarkdownParser = enhancedParseMarkdown;
|
|
102
|
+
|
|
103
|
+
// Add configuration option
|
|
104
|
+
global.ChatWidget.enableEnhancedMarkdown = function() {
|
|
105
|
+
console.log('[ChatWidget Markdown] Enhanced markdown explicitly enabled');
|
|
106
|
+
return true;
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
})(typeof window !== 'undefined' ? window : this);
|
|
110
|
+
|
package/dist/chat-widget.css
CHANGED
|
@@ -450,6 +450,77 @@
|
|
|
450
450
|
background: rgba(239, 68, 68, 0.1);
|
|
451
451
|
}
|
|
452
452
|
|
|
453
|
+
/* Auto-run controls */
|
|
454
|
+
.cw-autorun-controls {
|
|
455
|
+
padding: 8px 12px;
|
|
456
|
+
display: flex;
|
|
457
|
+
flex-direction: column;
|
|
458
|
+
gap: 8px;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.cw-control-label {
|
|
462
|
+
display: flex;
|
|
463
|
+
align-items: center;
|
|
464
|
+
gap: 8px;
|
|
465
|
+
font-size: 13px;
|
|
466
|
+
color: var(--cw-text);
|
|
467
|
+
cursor: pointer;
|
|
468
|
+
padding: 4px;
|
|
469
|
+
border-radius: 4px;
|
|
470
|
+
transition: background 0.15s;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
.cw-control-label:hover {
|
|
474
|
+
background: var(--cw-bg-muted);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.cw-control-label input[type="radio"] {
|
|
478
|
+
margin: 0;
|
|
479
|
+
cursor: pointer;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.cw-delay-control {
|
|
483
|
+
padding: 8px 12px;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.cw-delay-control input[type="range"] {
|
|
487
|
+
width: 100%;
|
|
488
|
+
margin-top: 4px;
|
|
489
|
+
cursor: pointer;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/* Continue button */
|
|
493
|
+
.cw-continue-bar {
|
|
494
|
+
padding: 12px 16px;
|
|
495
|
+
background: var(--cw-bg-muted);
|
|
496
|
+
border-top: 1px solid var(--cw-border);
|
|
497
|
+
display: flex;
|
|
498
|
+
justify-content: center;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.cw-continue-btn {
|
|
502
|
+
padding: 10px 20px;
|
|
503
|
+
border: none;
|
|
504
|
+
border-radius: var(--cw-radius-sm);
|
|
505
|
+
background: var(--cw-primary);
|
|
506
|
+
color: white;
|
|
507
|
+
font-size: 14px;
|
|
508
|
+
font-weight: 600;
|
|
509
|
+
cursor: pointer;
|
|
510
|
+
transition: opacity 0.15s;
|
|
511
|
+
display: flex;
|
|
512
|
+
align-items: center;
|
|
513
|
+
gap: 6px;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
.cw-continue-btn:hover {
|
|
517
|
+
opacity: 0.9;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.cw-continue-btn:active {
|
|
521
|
+
opacity: 0.8;
|
|
522
|
+
}
|
|
523
|
+
|
|
453
524
|
/* Responsive */
|
|
454
525
|
@media (max-width: 480px) {
|
|
455
526
|
.cw-widget {
|
|
@@ -501,3 +572,118 @@
|
|
|
501
572
|
}
|
|
502
573
|
}
|
|
503
574
|
|
|
575
|
+
/* Enhanced Markdown Styles (for chat-widget-markdown.js) */
|
|
576
|
+
.cw-message pre {
|
|
577
|
+
background: var(--cw-bg-muted);
|
|
578
|
+
border: 1px solid var(--cw-border);
|
|
579
|
+
border-radius: var(--cw-radius-sm);
|
|
580
|
+
padding: 12px;
|
|
581
|
+
overflow-x: auto;
|
|
582
|
+
margin: 8px 0;
|
|
583
|
+
font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
|
|
584
|
+
font-size: 13px;
|
|
585
|
+
line-height: 1.4;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.cw-message pre code {
|
|
589
|
+
background: none;
|
|
590
|
+
padding: 0;
|
|
591
|
+
border-radius: 0;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.cw-message table {
|
|
595
|
+
border-collapse: collapse;
|
|
596
|
+
width: 100%;
|
|
597
|
+
margin: 8px 0;
|
|
598
|
+
font-size: 13px;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.cw-message table th,
|
|
602
|
+
.cw-message table td {
|
|
603
|
+
border: 1px solid var(--cw-border);
|
|
604
|
+
padding: 8px 12px;
|
|
605
|
+
text-align: left;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
.cw-message table th {
|
|
609
|
+
background: var(--cw-bg-muted);
|
|
610
|
+
font-weight: 600;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.cw-message table tr:nth-child(even) {
|
|
614
|
+
background: rgba(0, 0, 0, 0.02);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.cw-message blockquote {
|
|
618
|
+
border-left: 3px solid var(--cw-primary);
|
|
619
|
+
padding-left: 12px;
|
|
620
|
+
margin: 8px 0;
|
|
621
|
+
color: var(--cw-text-muted);
|
|
622
|
+
font-style: italic;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
.cw-message h1,
|
|
626
|
+
.cw-message h2,
|
|
627
|
+
.cw-message h3,
|
|
628
|
+
.cw-message h4,
|
|
629
|
+
.cw-message h5,
|
|
630
|
+
.cw-message h6 {
|
|
631
|
+
margin: 12px 0 8px 0;
|
|
632
|
+
font-weight: 600;
|
|
633
|
+
line-height: 1.3;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
.cw-message h1 { font-size: 1.5em; }
|
|
637
|
+
.cw-message h2 { font-size: 1.3em; }
|
|
638
|
+
.cw-message h3 { font-size: 1.1em; }
|
|
639
|
+
.cw-message h4 { font-size: 1em; }
|
|
640
|
+
|
|
641
|
+
.cw-message hr {
|
|
642
|
+
border: none;
|
|
643
|
+
border-top: 1px solid var(--cw-border);
|
|
644
|
+
margin: 12px 0;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
.cw-message ul,
|
|
648
|
+
.cw-message ol {
|
|
649
|
+
margin: 8px 0;
|
|
650
|
+
padding-left: 24px;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
.cw-message li {
|
|
654
|
+
margin: 4px 0;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.cw-message p {
|
|
658
|
+
margin: 8px 0;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.cw-message p:first-child {
|
|
662
|
+
margin-top: 0;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
.cw-message p:last-child {
|
|
666
|
+
margin-bottom: 0;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/* Dark mode adjustments for enhanced markdown */
|
|
670
|
+
@media (prefers-color-scheme: dark) {
|
|
671
|
+
.cw-message pre {
|
|
672
|
+
background: rgba(255, 255, 255, 0.05);
|
|
673
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
.cw-message table th {
|
|
677
|
+
background: rgba(255, 255, 255, 0.05);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.cw-message table tr:nth-child(even) {
|
|
681
|
+
background: rgba(255, 255, 255, 0.02);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
.cw-message table th,
|
|
685
|
+
.cw-message table td {
|
|
686
|
+
border-color: rgba(255, 255, 255, 0.1);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
|
package/dist/chat-widget.js
CHANGED
|
@@ -43,6 +43,9 @@
|
|
|
43
43
|
runEvents: '/api/agent-runtime/runs/{runId}/events/',
|
|
44
44
|
simulateCustomer: '/api/agent-runtime/simulate-customer/',
|
|
45
45
|
},
|
|
46
|
+
// Demo flow control
|
|
47
|
+
autoRunDelay: 1000, // Delay in ms before auto-generating next message
|
|
48
|
+
autoRunMode: 'automatic', // 'automatic', 'confirm', or 'manual'
|
|
46
49
|
};
|
|
47
50
|
|
|
48
51
|
// State
|
|
@@ -52,7 +55,8 @@
|
|
|
52
55
|
isExpanded: false,
|
|
53
56
|
isLoading: false,
|
|
54
57
|
isSimulating: false,
|
|
55
|
-
|
|
58
|
+
autoRunActive: false,
|
|
59
|
+
autoRunPaused: false,
|
|
56
60
|
debugMode: false,
|
|
57
61
|
journeyType: 'general',
|
|
58
62
|
messages: [],
|
|
@@ -82,30 +86,35 @@
|
|
|
82
86
|
}
|
|
83
87
|
|
|
84
88
|
function parseMarkdown(text) {
|
|
85
|
-
//
|
|
89
|
+
// Check if enhanced markdown parser is available (from chat-widget-markdown.js)
|
|
90
|
+
if (global.ChatWidget && global.ChatWidget._enhancedMarkdownParser) {
|
|
91
|
+
return global.ChatWidget._enhancedMarkdownParser(text);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Fallback: Simple markdown parsing for common patterns
|
|
86
95
|
let html = escapeHtml(text);
|
|
87
|
-
|
|
96
|
+
|
|
88
97
|
// Bold: **text** or __text__
|
|
89
98
|
html = html.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
|
|
90
99
|
html = html.replace(/__(.+?)__/g, '<strong>$1</strong>');
|
|
91
|
-
|
|
100
|
+
|
|
92
101
|
// Italic: *text* or _text_
|
|
93
102
|
html = html.replace(/\*(.+?)\*/g, '<em>$1</em>');
|
|
94
103
|
html = html.replace(/_(.+?)_/g, '<em>$1</em>');
|
|
95
|
-
|
|
104
|
+
|
|
96
105
|
// Code: `code`
|
|
97
106
|
html = html.replace(/`(.+?)`/g, '<code>$1</code>');
|
|
98
|
-
|
|
107
|
+
|
|
99
108
|
// Links: [text](url)
|
|
100
109
|
html = html.replace(/\[(.+?)\]\((.+?)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>');
|
|
101
|
-
|
|
110
|
+
|
|
102
111
|
// Line breaks
|
|
103
112
|
html = html.replace(/\n/g, '<br>');
|
|
104
|
-
|
|
113
|
+
|
|
105
114
|
// Lists: - item or * item
|
|
106
115
|
html = html.replace(/^[\-\*]\s+(.+)$/gm, '<li>$1</li>');
|
|
107
116
|
html = html.replace(/(<li>.*<\/li>)/s, '<ul>$1</ul>');
|
|
108
|
-
|
|
117
|
+
|
|
109
118
|
return html;
|
|
110
119
|
}
|
|
111
120
|
|
|
@@ -339,8 +348,13 @@
|
|
|
339
348
|
render();
|
|
340
349
|
|
|
341
350
|
// Trigger auto-run if enabled
|
|
342
|
-
if (state.
|
|
343
|
-
|
|
351
|
+
if (state.autoRunActive && !state.error) {
|
|
352
|
+
if (config.autoRunMode === 'automatic') {
|
|
353
|
+
setTimeout(() => triggerAutoRun(), config.autoRunDelay);
|
|
354
|
+
} else if (config.autoRunMode === 'confirm') {
|
|
355
|
+
state.autoRunPaused = true;
|
|
356
|
+
render();
|
|
357
|
+
}
|
|
344
358
|
}
|
|
345
359
|
};
|
|
346
360
|
|
|
@@ -365,12 +379,13 @@
|
|
|
365
379
|
// ============================================================================
|
|
366
380
|
|
|
367
381
|
async function triggerAutoRun() {
|
|
368
|
-
if (!state.
|
|
382
|
+
if (!state.autoRunActive || state.isLoading || state.isSimulating) return;
|
|
369
383
|
|
|
370
384
|
const lastMessage = state.messages[state.messages.length - 1];
|
|
371
385
|
if (lastMessage?.role !== 'assistant') return;
|
|
372
386
|
|
|
373
387
|
state.isSimulating = true;
|
|
388
|
+
state.autoRunPaused = false;
|
|
374
389
|
render();
|
|
375
390
|
|
|
376
391
|
try {
|
|
@@ -402,7 +417,8 @@
|
|
|
402
417
|
async function startDemoFlow(journeyType) {
|
|
403
418
|
clearMessages();
|
|
404
419
|
state.journeyType = journeyType;
|
|
405
|
-
state.
|
|
420
|
+
state.autoRunActive = true;
|
|
421
|
+
state.autoRunPaused = false;
|
|
406
422
|
render();
|
|
407
423
|
|
|
408
424
|
const journey = config.journeyTypes[journeyType];
|
|
@@ -419,7 +435,26 @@
|
|
|
419
435
|
}
|
|
420
436
|
|
|
421
437
|
function stopAutoRun() {
|
|
422
|
-
state.
|
|
438
|
+
state.autoRunActive = false;
|
|
439
|
+
state.autoRunPaused = false;
|
|
440
|
+
render();
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
function continueAutoRun() {
|
|
444
|
+
if (state.autoRunActive && state.autoRunPaused) {
|
|
445
|
+
triggerAutoRun();
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function setAutoRunMode(mode) {
|
|
450
|
+
if (['automatic', 'confirm', 'manual'].includes(mode)) {
|
|
451
|
+
config.autoRunMode = mode;
|
|
452
|
+
render();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function setAutoRunDelay(delay) {
|
|
457
|
+
config.autoRunDelay = Math.max(0, parseInt(delay) || 1000);
|
|
423
458
|
render();
|
|
424
459
|
}
|
|
425
460
|
|
|
@@ -435,7 +470,8 @@
|
|
|
435
470
|
|
|
436
471
|
function closeWidget() {
|
|
437
472
|
state.isOpen = false;
|
|
438
|
-
state.
|
|
473
|
+
state.autoRunActive = false;
|
|
474
|
+
state.autoRunPaused = false;
|
|
439
475
|
render();
|
|
440
476
|
}
|
|
441
477
|
|
|
@@ -453,7 +489,8 @@
|
|
|
453
489
|
state.messages = [];
|
|
454
490
|
state.conversationId = null;
|
|
455
491
|
state.error = null;
|
|
456
|
-
state.
|
|
492
|
+
state.autoRunActive = false;
|
|
493
|
+
state.autoRunPaused = false;
|
|
457
494
|
setStoredValue(config.conversationIdKey, null);
|
|
458
495
|
render();
|
|
459
496
|
}
|
|
@@ -504,16 +541,48 @@
|
|
|
504
541
|
</button>
|
|
505
542
|
`).join('');
|
|
506
543
|
|
|
507
|
-
const
|
|
544
|
+
const controlsSection = state.autoRunActive ? `
|
|
545
|
+
<div class="cw-dropdown-separator"></div>
|
|
546
|
+
<div class="cw-dropdown-label">Demo Controls</div>
|
|
547
|
+
<div class="cw-autorun-controls">
|
|
548
|
+
<label class="cw-control-label">
|
|
549
|
+
<input type="radio" name="autorun-mode" value="automatic"
|
|
550
|
+
${config.autoRunMode === 'automatic' ? 'checked' : ''}
|
|
551
|
+
onchange="ChatWidget.setAutoRunMode('automatic')">
|
|
552
|
+
<span>⥠Automatic</span>
|
|
553
|
+
</label>
|
|
554
|
+
<label class="cw-control-label">
|
|
555
|
+
<input type="radio" name="autorun-mode" value="confirm"
|
|
556
|
+
${config.autoRunMode === 'confirm' ? 'checked' : ''}
|
|
557
|
+
onchange="ChatWidget.setAutoRunMode('confirm')">
|
|
558
|
+
<span>đ Confirm Next</span>
|
|
559
|
+
</label>
|
|
560
|
+
<label class="cw-control-label">
|
|
561
|
+
<input type="radio" name="autorun-mode" value="manual"
|
|
562
|
+
${config.autoRunMode === 'manual' ? 'checked' : ''}
|
|
563
|
+
onchange="ChatWidget.setAutoRunMode('manual')">
|
|
564
|
+
<span>â Manual</span>
|
|
565
|
+
</label>
|
|
566
|
+
</div>
|
|
567
|
+
${config.autoRunMode === 'automatic' ? `
|
|
568
|
+
<div class="cw-delay-control">
|
|
569
|
+
<label class="cw-control-label">
|
|
570
|
+
<span>Delay: ${config.autoRunDelay}ms</span>
|
|
571
|
+
<input type="range" min="0" max="5000" step="100"
|
|
572
|
+
value="${config.autoRunDelay}"
|
|
573
|
+
oninput="ChatWidget.setAutoRunDelay(this.value)">
|
|
574
|
+
</label>
|
|
575
|
+
</div>
|
|
576
|
+
` : ''}
|
|
508
577
|
<div class="cw-dropdown-separator"></div>
|
|
509
578
|
<button class="cw-dropdown-item cw-dropdown-item-danger" data-action="stop-autorun">
|
|
510
|
-
âšī¸ Stop
|
|
579
|
+
âšī¸ Stop Demo
|
|
511
580
|
</button>
|
|
512
581
|
` : '';
|
|
513
582
|
|
|
514
583
|
return `
|
|
515
584
|
<div class="cw-dropdown">
|
|
516
|
-
<button class="cw-header-btn ${state.
|
|
585
|
+
<button class="cw-header-btn ${state.autoRunActive ? 'cw-btn-active' : ''}"
|
|
517
586
|
data-action="toggle-journey-dropdown"
|
|
518
587
|
title="Demo Flows"
|
|
519
588
|
${state.isLoading || state.isSimulating ? 'disabled' : ''}>
|
|
@@ -523,7 +592,7 @@
|
|
|
523
592
|
<div class="cw-dropdown-label">Demo Flows</div>
|
|
524
593
|
<div class="cw-dropdown-separator"></div>
|
|
525
594
|
${journeyItems}
|
|
526
|
-
${
|
|
595
|
+
${controlsSection}
|
|
527
596
|
</div>
|
|
528
597
|
</div>
|
|
529
598
|
`;
|
|
@@ -567,9 +636,17 @@
|
|
|
567
636
|
</div>
|
|
568
637
|
` : '';
|
|
569
638
|
|
|
570
|
-
const
|
|
639
|
+
const continueButton = (state.autoRunActive && state.autoRunPaused && config.autoRunMode === 'confirm') ? `
|
|
640
|
+
<div class="cw-continue-bar">
|
|
641
|
+
<button class="cw-continue-btn" data-action="continue-autorun" style="background-color: ${config.primaryColor}">
|
|
642
|
+
âļī¸ Continue Demo
|
|
643
|
+
</button>
|
|
644
|
+
</div>
|
|
645
|
+
` : '';
|
|
646
|
+
|
|
647
|
+
const statusBar = (state.autoRunActive || state.debugMode) ? `
|
|
571
648
|
<div class="cw-status-bar">
|
|
572
|
-
${state.
|
|
649
|
+
${state.autoRunActive ? `<span>đ¤ Demo: ${config.journeyTypes[state.journeyType]?.label || state.journeyType} (${config.autoRunMode})</span>` : ''}
|
|
573
650
|
${state.debugMode ? '<span>đ Debug</span>' : ''}
|
|
574
651
|
</div>
|
|
575
652
|
` : '';
|
|
@@ -611,6 +688,7 @@
|
|
|
611
688
|
${messagesHtml}
|
|
612
689
|
${typingIndicator}
|
|
613
690
|
</div>
|
|
691
|
+
${continueButton}
|
|
614
692
|
${errorBar}
|
|
615
693
|
<form class="cw-input-form" id="cw-input-form">
|
|
616
694
|
<input type="text" class="cw-input" placeholder="${escapeHtml(config.placeholder)}" ${state.isLoading ? 'disabled' : ''}>
|
|
@@ -645,6 +723,7 @@
|
|
|
645
723
|
case 'toggle-debug': toggleDebugMode(); break;
|
|
646
724
|
case 'clear': clearMessages(); break;
|
|
647
725
|
case 'stop-autorun': stopAutoRun(); break;
|
|
726
|
+
case 'continue-autorun': continueAutoRun(); break;
|
|
648
727
|
case 'toggle-journey-dropdown':
|
|
649
728
|
const dropdown = document.getElementById('cw-journey-dropdown');
|
|
650
729
|
if (dropdown) {
|
|
@@ -756,6 +835,9 @@
|
|
|
756
835
|
clearMessages,
|
|
757
836
|
startDemoFlow,
|
|
758
837
|
stopAutoRun,
|
|
838
|
+
continueAutoRun,
|
|
839
|
+
setAutoRunMode,
|
|
840
|
+
setAutoRunDelay,
|
|
759
841
|
getState: () => ({ ...state }),
|
|
760
842
|
getConfig: () => ({ ...config }),
|
|
761
843
|
};
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@makemore/agent-frontend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "A standalone, zero-dependency chat widget for AI agents. Embed conversational AI into any website with a single script tag.",
|
|
5
5
|
"main": "dist/chat-widget.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist/chat-widget.js",
|
|
8
8
|
"dist/chat-widget.css",
|
|
9
|
+
"dist/chat-widget-markdown.js",
|
|
9
10
|
"README.md",
|
|
10
11
|
"LICENSE"
|
|
11
12
|
],
|