@kroonen-ai/librebot-widget 1.1.0 → 1.1.1

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 ADDED
@@ -0,0 +1,155 @@
1
+ # Libre Bot Widget
2
+
3
+ AI-powered documentation assistant widget for your website. Part of [Libre Bot](https://librebot.io) - the RAG-powered chatbot SaaS.
4
+
5
+ ## Installation
6
+
7
+ ### CDN (Recommended)
8
+
9
+ ```html
10
+ <script src="https://cdn.jsdelivr.net/npm/@kroonen-ai/librebot-widget@latest/dist/librebot.js"></script>
11
+ <script>
12
+ LibreBot.init({
13
+ apiKey: 'YOUR_API_KEY'
14
+ });
15
+ </script>
16
+ ```
17
+
18
+ ### npm
19
+
20
+ ```bash
21
+ npm install @kroonen-ai/librebot-widget
22
+ ```
23
+
24
+ ```javascript
25
+ import { LibreBotWidget } from '@kroonen-ai/librebot-widget';
26
+
27
+ new LibreBotWidget({
28
+ apiKey: 'YOUR_API_KEY'
29
+ });
30
+ ```
31
+
32
+ ## Configuration
33
+
34
+ All configuration options are optional except `apiKey`. Settings configured in your [Libre Bot dashboard](https://librebot.io/dashboard) are automatically loaded.
35
+
36
+ ```javascript
37
+ LibreBot.init({
38
+ apiKey: 'YOUR_API_KEY', // Required
39
+ apiUrl: 'https://librebot.io/api', // API endpoint (default)
40
+ position: 'bottom-right', // 'bottom-right' | 'bottom-left'
41
+ theme: 'dark', // 'dark' | 'light' | 'auto'
42
+ primaryColor: '#14b8a6', // Hex color for branding
43
+ title: 'Libre Bot', // Widget header title
44
+ subtitle: 'AI Documentation Assistant',
45
+ placeholder: 'Ask a question...', // Input placeholder
46
+ welcomeMessage: 'Hi! How can I help?',
47
+ streaming: true, // Enable streaming responses
48
+ whiteLabel: false, // Remove "Powered by Libre Bot"
49
+ autoLoadConfig: true // Fetch settings from server
50
+ });
51
+ ```
52
+
53
+ ## Features
54
+
55
+ ### Markdown Support
56
+
57
+ The widget renders full markdown formatting in AI responses:
58
+
59
+ - **Code blocks** with syntax language labels
60
+ ````
61
+ ```javascript
62
+ console.log('Hello');
63
+ ```
64
+ ````
65
+ - **Inline code** with backticks: `code`
66
+ - **Headers** (h2, h3, h4)
67
+ - **Bold** (`**text**`), *italic* (`*text*`), and ***bold+italic*** (`***text***`)
68
+ - **Links** `[text](url)` - opens in new tab
69
+ - **Unordered lists** (`-` or `*`)
70
+ - **Ordered lists** (`1.` `2.` `3.`)
71
+ - **Blockquotes** (`> text`)
72
+ - **Horizontal rules** (`---`)
73
+
74
+ ### Themes
75
+
76
+ - **Dark mode** - Default dark theme
77
+ - **Light mode** - Clean light theme
78
+ - **Auto** - Follows system preference
79
+
80
+ ### White-Label
81
+
82
+ Remove "Powered by Libre Bot" branding with the `whiteLabel: true` option (requires Pro plan or higher).
83
+
84
+ ### Streaming Responses
85
+
86
+ Real-time streaming of AI responses for better UX. Enabled by default.
87
+
88
+ ### RAG-Powered
89
+
90
+ Responses are augmented with your uploaded documentation. Source citations are included when relevant documents are found.
91
+
92
+ ## Methods
93
+
94
+ ```javascript
95
+ const widget = LibreBot.init({ apiKey: 'YOUR_API_KEY' });
96
+
97
+ // Open the chat modal
98
+ widget.open();
99
+
100
+ // Close the chat modal
101
+ widget.close();
102
+
103
+ // Toggle open/close
104
+ widget.toggle();
105
+
106
+ // Remove widget from DOM
107
+ widget.destroy();
108
+ ```
109
+
110
+ ## Styling
111
+
112
+ The widget uses CSS custom properties scoped to `.librebot-widget`. Override these to customize:
113
+
114
+ ```css
115
+ .librebot-widget {
116
+ --lb-primary: #14b8a6;
117
+ --lb-bg: #0f0f0f;
118
+ --lb-bg-secondary: #1a1a1a;
119
+ --lb-text: #ffffff;
120
+ --lb-text-secondary: #9ca3af;
121
+ --lb-border: #2a2a2a;
122
+ }
123
+ ```
124
+
125
+ ## Browser Support
126
+
127
+ - Chrome 80+
128
+ - Firefox 75+
129
+ - Safari 13+
130
+ - Edge 80+
131
+
132
+ ## Changelog
133
+
134
+ ### 1.1.0
135
+ - Full markdown formatting support
136
+ - Code blocks with language labels
137
+ - Headers, lists, blockquotes
138
+ - Links opening in new tabs
139
+ - XSS protection via HTML escaping
140
+ - Improved light/dark theme styling
141
+
142
+ ### 1.0.3
143
+ - Widget customization support
144
+ - White-label mode
145
+ - Auto-load config from server
146
+ - Theme options (dark, light, auto)
147
+
148
+ ### 1.0.0
149
+ - Initial release
150
+ - Streaming responses
151
+ - Basic markdown (bold, inline code)
152
+
153
+ ## License
154
+
155
+ MIT - Kroonen AI, Inc.
@@ -685,8 +685,9 @@ class LibreBotWidget {
685
685
  .replace(/'/g, '&#039;');
686
686
  };
687
687
  // First, extract code blocks to protect them from other formatting
688
+ // Regex handles optional space/newline after ``` and optional language identifier
688
689
  const codeBlocks = [];
689
- let processed = content.replace(/```(\w*)\n?([\s\S]*?)```/g, (_, lang, code) => {
690
+ let processed = content.replace(/```\s*(\w*)\s*\n?([\s\S]*?)```/g, (_, lang, code) => {
690
691
  const escaped = escapeHtml(code.trim());
691
692
  const langClass = lang ? ` data-language="${escapeHtml(lang)}"` : '';
692
693
  codeBlocks.push(`<pre class="librebot-code-block"${langClass}><code>${escaped}</code></pre>`);
@@ -1 +1 @@
1
- {"version":3,"file":"librebot.esm.js","sources":["../src/styles.ts","../src/icons.ts","../src/widget.ts"],"sourcesContent":["export const getStyles = (primaryColor: string = '#14b8a6') => `\n .librebot-widget {\n --lb-primary: ${primaryColor};\n --lb-primary-hover: color-mix(in srgb, ${primaryColor} 85%, white);\n --lb-bg: #0f0f0f;\n --lb-bg-secondary: #1a1a1a;\n --lb-text: #ffffff;\n --lb-text-secondary: #9ca3af;\n --lb-border: #2a2a2a;\n font-family: 'Roboto Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .librebot-widget.light {\n --lb-bg: #ffffff;\n --lb-bg-secondary: #f5f5f5;\n --lb-text: #1a1a1a;\n --lb-text-secondary: #666666;\n --lb-border: #e0e0e0;\n }\n\n .librebot-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--lb-primary);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n z-index: 999998;\n }\n\n .librebot-fab:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n }\n\n .librebot-fab svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-fab.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-modal {\n position: fixed;\n bottom: 90px;\n right: 20px;\n width: 380px;\n max-width: calc(100vw - 40px);\n height: 520px;\n max-height: calc(100vh - 120px);\n background: var(--lb-bg);\n border: 1px solid var(--lb-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 999999;\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n }\n\n .librebot-modal.open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .librebot-modal.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-header {\n padding: 16px;\n border-bottom: 1px solid var(--lb-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .librebot-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .librebot-avatar {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: var(--lb-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-avatar svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-title {\n font-weight: 600;\n color: var(--lb-text);\n margin: 0;\n font-size: 16px;\n }\n\n .librebot-subtitle {\n font-size: 12px;\n color: var(--lb-text-secondary);\n margin: 0;\n }\n\n .librebot-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--lb-text-secondary);\n transition: background 0.2s;\n }\n\n .librebot-close:hover {\n background: var(--lb-bg-secondary);\n }\n\n .librebot-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .librebot-message {\n max-width: 85%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .librebot-message.user {\n align-self: flex-end;\n background: var(--lb-primary);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .librebot-message.assistant {\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n border-bottom-left-radius: 4px;\n }\n\n /* Inline code */\n .librebot-inline-code {\n background: rgba(0, 0, 0, 0.3);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n color: #f0f0f0;\n }\n\n .librebot-widget.light .librebot-inline-code {\n background: rgba(0, 0, 0, 0.08);\n color: #1a1a1a;\n }\n\n /* Code blocks */\n .librebot-code-block {\n background: #0d1117;\n padding: 12px 14px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 10px 0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n }\n\n .librebot-widget.light .librebot-code-block {\n background: #f6f8fa;\n border-color: rgba(0, 0, 0, 0.1);\n }\n\n .librebot-code-block code {\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #e6edf3;\n background: none;\n padding: 0;\n white-space: pre;\n display: block;\n }\n\n .librebot-widget.light .librebot-code-block code {\n color: #24292f;\n }\n\n .librebot-code-block[data-language]::before {\n content: attr(data-language);\n position: absolute;\n top: 6px;\n right: 10px;\n font-size: 10px;\n color: rgba(255, 255, 255, 0.4);\n text-transform: uppercase;\n font-family: 'Roboto Mono', monospace;\n }\n\n .librebot-widget.light .librebot-code-block[data-language]::before {\n color: rgba(0, 0, 0, 0.3);\n }\n\n /* Headers */\n .librebot-h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 12px 0 8px 0;\n color: var(--lb-text);\n }\n\n .librebot-h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 10px 0 6px 0;\n color: var(--lb-text);\n }\n\n .librebot-h4 {\n font-size: 13px;\n font-weight: 600;\n margin: 8px 0 4px 0;\n color: var(--lb-text);\n }\n\n /* Lists */\n .librebot-ul, .librebot-ol {\n margin: 8px 0;\n padding-left: 20px;\n }\n\n .librebot-ul {\n list-style-type: disc;\n }\n\n .librebot-ol {\n list-style-type: decimal;\n }\n\n .librebot-li, .librebot-li-ordered {\n margin: 4px 0;\n padding-left: 4px;\n line-height: 1.5;\n }\n\n /* Links */\n .librebot-link {\n color: var(--lb-primary);\n text-decoration: none;\n border-bottom: 1px solid transparent;\n transition: border-color 0.2s;\n }\n\n .librebot-link:hover {\n border-bottom-color: var(--lb-primary);\n }\n\n /* Blockquotes */\n .librebot-blockquote {\n border-left: 3px solid var(--lb-primary);\n margin: 8px 0;\n padding: 4px 12px;\n color: var(--lb-text-secondary);\n font-style: italic;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 0 6px 6px 0;\n }\n\n .librebot-widget.light .librebot-blockquote {\n background: rgba(0, 0, 0, 0.04);\n }\n\n /* Horizontal rule */\n .librebot-hr {\n border: none;\n border-top: 1px solid var(--lb-border);\n margin: 12px 0;\n }\n\n /* Strong and emphasis */\n .librebot-message strong {\n font-weight: 600;\n }\n\n .librebot-message em {\n font-style: italic;\n }\n\n /* Legacy support for old code elements */\n .librebot-message code:not(.librebot-inline-code) {\n background: rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 13px;\n }\n\n .librebot-message pre:not(.librebot-code-block) {\n background: rgba(0, 0, 0, 0.3);\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 8px 0;\n }\n\n .librebot-message pre:not(.librebot-code-block) code {\n background: none;\n padding: 0;\n }\n\n .librebot-typing {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .librebot-typing span {\n width: 8px;\n height: 8px;\n background: var(--lb-text-secondary);\n border-radius: 50%;\n animation: librebot-bounce 1.4s infinite ease-in-out;\n }\n\n .librebot-typing span:nth-child(1) { animation-delay: 0s; }\n .librebot-typing span:nth-child(2) { animation-delay: 0.2s; }\n .librebot-typing span:nth-child(3) { animation-delay: 0.4s; }\n\n @keyframes librebot-bounce {\n 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }\n 40% { transform: scale(1); opacity: 1; }\n }\n\n .librebot-input-area {\n padding: 12px 16px;\n border-top: 1px solid var(--lb-border);\n display: flex;\n gap: 8px;\n }\n\n .librebot-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--lb-border);\n border-radius: 24px;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .librebot-input:focus {\n border-color: var(--lb-primary);\n }\n\n .librebot-input::placeholder {\n color: var(--lb-text-secondary);\n }\n\n .librebot-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: var(--lb-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .librebot-send:hover {\n background: var(--lb-primary-hover);\n }\n\n .librebot-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .librebot-send svg {\n width: 18px;\n height: 18px;\n fill: white;\n }\n\n .librebot-welcome {\n text-align: center;\n padding: 20px;\n color: var(--lb-text-secondary);\n }\n\n .librebot-welcome-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n background: var(--lb-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-welcome-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .librebot-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--lb-text-secondary);\n border-top: 1px solid var(--lb-border);\n }\n\n .librebot-powered a {\n color: var(--lb-primary);\n text-decoration: none;\n }\n\n .librebot-powered a:hover {\n text-decoration: underline;\n }\n`;\n","export const chatIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path></svg>`;\n\nexport const closeIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg>`;\n\nexport const sendIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line><polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon></svg>`;\n\nexport const botIcon = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>`;\n","import { LibreBotConfig, Message, ChatResponse } from './types';\nimport { getStyles } from './styles';\nimport { chatIcon, closeIcon, sendIcon } from './icons';\n\nexport class LibreBotWidget {\n private config!: Required<LibreBotConfig>;\n private container: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private messagesContainer: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private isOpen = false;\n private messages: Message[] = [];\n private isLoading = false;\n\n private defaultConfig: Omit<Required<LibreBotConfig>, 'apiKey'> = {\n apiUrl: 'https://librebot.io/api',\n position: 'bottom-right',\n theme: 'dark',\n primaryColor: '#14b8a6',\n title: 'Libre Bot',\n subtitle: 'AI Documentation Assistant',\n placeholder: 'Ask a question...',\n welcomeMessage: 'Hi! I can help you find answers in the documentation. What would you like to know?',\n streaming: true,\n whiteLabel: false,\n autoLoadConfig: true,\n };\n\n constructor(config: LibreBotConfig) {\n if (!config.apiKey) {\n console.error('LibreBot: API key is required');\n return;\n }\n\n this.config = { ...this.defaultConfig, ...config } as Required<LibreBotConfig>;\n\n // Auto-load config from server if enabled and no custom settings provided\n if (this.config.autoLoadConfig) {\n this.loadRemoteConfig().then(() => this.init());\n } else {\n this.init();\n }\n }\n\n private async loadRemoteConfig(): Promise<void> {\n try {\n const response = await fetch(`${this.config.apiUrl}/widget-config?key=${this.config.apiKey}`);\n if (response.ok) {\n const remoteConfig = await response.json();\n // Merge remote config with local config (local overrides remote)\n this.config = {\n ...this.defaultConfig,\n ...remoteConfig,\n ...this.getProvidedConfig(),\n apiKey: this.config.apiKey,\n apiUrl: this.config.apiUrl,\n autoLoadConfig: this.config.autoLoadConfig,\n } as Required<LibreBotConfig>;\n }\n } catch (error) {\n console.warn('LibreBot: Could not load remote config, using defaults', error);\n }\n }\n\n private getProvidedConfig(): Partial<LibreBotConfig> {\n // Return only the config options that were explicitly provided (not default values)\n const provided: Partial<LibreBotConfig> = {};\n const userConfig = this.config;\n const defaults = this.defaultConfig;\n\n if (userConfig.position !== defaults.position) provided.position = userConfig.position;\n if (userConfig.theme !== defaults.theme) provided.theme = userConfig.theme;\n if (userConfig.primaryColor !== defaults.primaryColor) provided.primaryColor = userConfig.primaryColor;\n if (userConfig.title !== defaults.title) provided.title = userConfig.title;\n if (userConfig.subtitle !== defaults.subtitle) provided.subtitle = userConfig.subtitle;\n if (userConfig.placeholder !== defaults.placeholder) provided.placeholder = userConfig.placeholder;\n if (userConfig.welcomeMessage !== defaults.welcomeMessage) provided.welcomeMessage = userConfig.welcomeMessage;\n if (userConfig.streaming !== defaults.streaming) provided.streaming = userConfig.streaming;\n if (userConfig.whiteLabel !== defaults.whiteLabel) provided.whiteLabel = userConfig.whiteLabel;\n\n return provided;\n }\n\n private init(): void {\n // Inject styles\n this.injectStyles();\n\n // Create widget container\n this.createWidget();\n\n // Add welcome message\n if (this.config.welcomeMessage) {\n this.addMessage('assistant', this.config.welcomeMessage);\n }\n }\n\n private injectStyles(): void {\n const styleId = 'librebot-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = getStyles(this.config.primaryColor);\n document.head.appendChild(style);\n }\n\n private createWidget(): void {\n // Create container\n this.container = document.createElement('div');\n this.container.className = `librebot-widget ${this.config.theme === 'light' ? 'light' : ''}`;\n\n // Create FAB button\n const fab = document.createElement('button');\n fab.className = `librebot-fab ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n fab.innerHTML = chatIcon;\n fab.onclick = () => this.toggle();\n\n // Create modal\n this.modal = document.createElement('div');\n this.modal.className = `librebot-modal ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n this.modal.innerHTML = this.getModalHTML();\n\n // Add to container\n this.container.appendChild(fab);\n this.container.appendChild(this.modal);\n document.body.appendChild(this.container);\n\n // Get references\n this.messagesContainer = this.modal.querySelector('.librebot-messages');\n this.input = this.modal.querySelector('.librebot-input');\n\n // Add event listeners\n const closeBtn = this.modal.querySelector('.librebot-close');\n closeBtn?.addEventListener('click', () => this.close());\n\n const sendBtn = this.modal.querySelector('.librebot-send');\n sendBtn?.addEventListener('click', () => this.sendMessage());\n\n this.input?.addEventListener('keypress', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.sendMessage();\n }\n });\n\n // Auto theme detection\n if (this.config.theme === 'auto') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: light)');\n this.updateTheme(mediaQuery.matches);\n mediaQuery.addEventListener('change', (e) => this.updateTheme(e.matches));\n }\n }\n\n private getModalHTML(): string {\n const poweredByHtml = this.config.whiteLabel\n ? ''\n : `<div class=\"librebot-powered\">\n Powered by <a href=\"https://librebot.io\" target=\"_blank\">Libre Bot</a>\n </div>`;\n\n return `\n <div class=\"librebot-header\">\n <div class=\"librebot-header-content\">\n <div class=\"librebot-avatar\">${chatIcon}</div>\n <div>\n <h3 class=\"librebot-title\">${this.config.title}</h3>\n <p class=\"librebot-subtitle\">${this.config.subtitle}</p>\n </div>\n </div>\n <button class=\"librebot-close\">${closeIcon}</button>\n </div>\n <div class=\"librebot-messages\"></div>\n <div class=\"librebot-input-area\">\n <input type=\"text\" class=\"librebot-input\" placeholder=\"${this.config.placeholder}\" />\n <button class=\"librebot-send\">${sendIcon}</button>\n </div>\n ${poweredByHtml}\n `;\n }\n\n private updateTheme(isLight: boolean): void {\n if (isLight) {\n this.container?.classList.add('light');\n } else {\n this.container?.classList.remove('light');\n }\n }\n\n public toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n public open(): void {\n this.isOpen = true;\n this.modal?.classList.add('open');\n this.input?.focus();\n }\n\n public close(): void {\n this.isOpen = false;\n this.modal?.classList.remove('open');\n }\n\n private addMessage(role: 'user' | 'assistant', content: string): void {\n const message: Message = {\n id: `msg-${Date.now()}`,\n role,\n content,\n timestamp: new Date(),\n };\n\n this.messages.push(message);\n this.renderMessage(message);\n }\n\n private renderMessage(message: Message): void {\n if (!this.messagesContainer) return;\n\n const el = document.createElement('div');\n el.className = `librebot-message ${message.role}`;\n el.innerHTML = this.formatMessage(message.content);\n\n this.messagesContainer.appendChild(el);\n this.scrollToBottom();\n }\n\n private formatMessage(content: string): string {\n // Escape HTML to prevent XSS\n const escapeHtml = (text: string): string => {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n };\n\n // First, extract code blocks to protect them from other formatting\n const codeBlocks: string[] = [];\n let processed = content.replace(/```(\\w*)\\n?([\\s\\S]*?)```/g, (_, lang, code) => {\n const escaped = escapeHtml(code.trim());\n const langClass = lang ? ` data-language=\"${escapeHtml(lang)}\"` : '';\n codeBlocks.push(`<pre class=\"librebot-code-block\"${langClass}><code>${escaped}</code></pre>`);\n return `%%CODEBLOCK${codeBlocks.length - 1}%%`;\n });\n\n // Extract inline code\n const inlineCodes: string[] = [];\n processed = processed.replace(/`([^`]+)`/g, (_, code) => {\n inlineCodes.push(`<code class=\"librebot-inline-code\">${escapeHtml(code)}</code>`);\n return `%%INLINECODE${inlineCodes.length - 1}%%`;\n });\n\n // Now escape remaining HTML\n processed = escapeHtml(processed);\n\n // Headers (## and ###)\n processed = processed.replace(/^### (.+)$/gm, '<h4 class=\"librebot-h4\">$1</h4>');\n processed = processed.replace(/^## (.+)$/gm, '<h3 class=\"librebot-h3\">$1</h3>');\n processed = processed.replace(/^# (.+)$/gm, '<h2 class=\"librebot-h2\">$1</h2>');\n\n // Bold and italic\n processed = processed.replace(/\\*\\*\\*([^*]+)\\*\\*\\*/g, '<strong><em>$1</em></strong>');\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n processed = processed.replace(/_([^_]+)_/g, '<em>$1</em>');\n\n // Links [text](url)\n processed = processed.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"librebot-link\">$1</a>');\n\n // Unordered lists\n processed = processed.replace(/^[\\*\\-] (.+)$/gm, '<li class=\"librebot-li\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ul class=\"librebot-ul\">${match}</ul>`;\n });\n\n // Ordered lists\n processed = processed.replace(/^\\d+\\. (.+)$/gm, '<li class=\"librebot-li-ordered\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li-ordered\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ol class=\"librebot-ol\">${match}</ol>`;\n });\n\n // Horizontal rule\n processed = processed.replace(/^---$/gm, '<hr class=\"librebot-hr\">');\n\n // Blockquotes\n processed = processed.replace(/^&gt; (.+)$/gm, '<blockquote class=\"librebot-blockquote\">$1</blockquote>');\n\n // Convert newlines to <br> (but not inside lists/blockquotes)\n processed = processed.replace(/\\n/g, '<br>');\n\n // Clean up extra <br> after block elements\n processed = processed.replace(/<\\/(pre|ul|ol|blockquote|h[2-4])><br>/g, '</$1>');\n processed = processed.replace(/<br><(pre|ul|ol|blockquote|h[2-4])/g, '<$1');\n\n // Restore code blocks\n codeBlocks.forEach((block, i) => {\n processed = processed.replace(`%%CODEBLOCK${i}%%`, block);\n });\n\n // Restore inline code\n inlineCodes.forEach((code, i) => {\n processed = processed.replace(`%%INLINECODE${i}%%`, code);\n });\n\n return processed;\n }\n\n private showTyping(): HTMLDivElement {\n const typing = document.createElement('div');\n typing.className = 'librebot-typing';\n typing.innerHTML = '<span></span><span></span><span></span>';\n this.messagesContainer?.appendChild(typing);\n this.scrollToBottom();\n return typing;\n }\n\n private scrollToBottom(): void {\n if (this.messagesContainer) {\n this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;\n }\n }\n\n private async sendMessage(): Promise<void> {\n if (!this.input || this.isLoading) return;\n\n const content = this.input.value.trim();\n if (!content) return;\n\n // Add user message\n this.addMessage('user', content);\n this.input.value = '';\n\n // Show typing indicator\n this.isLoading = true;\n const typing = this.showTyping();\n\n try {\n if (this.config.streaming) {\n await this.callStreamingAPI(content, typing);\n } else {\n const response = await this.callAPI(content);\n typing.remove();\n\n if (response.error) {\n this.addMessage('assistant', `Sorry, I encountered an error: ${response.error}`);\n } else {\n this.addMessage('assistant', response.response);\n }\n }\n } catch (error) {\n typing.remove();\n this.addMessage('assistant', 'Sorry, I had trouble connecting. Please try again.');\n console.error('LibreBot error:', error);\n } finally {\n this.isLoading = false;\n }\n }\n\n private async callStreamingAPI(message: string, typing: HTMLDivElement): Promise<void> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n stream: true,\n }),\n });\n\n if (!response.ok) {\n typing.remove();\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n this.addMessage('assistant', `Sorry, I encountered an error: ${error.error || 'Request failed'}`);\n return;\n }\n\n // Remove typing indicator and create streaming message element\n typing.remove();\n const messageEl = document.createElement('div');\n messageEl.className = 'librebot-message assistant';\n this.messagesContainer?.appendChild(messageEl);\n\n const reader = response.body?.getReader();\n if (!reader) {\n this.addMessage('assistant', 'Sorry, streaming is not supported.');\n return;\n }\n\n const decoder = new TextDecoder();\n let fullContent = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n const lines = chunk.split('\\n').filter((line) => line.trim() !== '');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) {\n fullContent += parsed.content;\n messageEl.innerHTML = this.formatMessage(fullContent);\n this.scrollToBottom();\n }\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n } catch (error) {\n console.error('Stream reading error:', error);\n }\n\n // Add to messages array\n this.messages.push({\n id: `msg-${Date.now()}`,\n role: 'assistant',\n content: fullContent,\n timestamp: new Date(),\n });\n }\n\n private async callAPI(message: string): Promise<ChatResponse> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n return { response: '', error: error.error || 'Request failed' };\n }\n\n return response.json();\n }\n\n private getConversationContext(): Array<{ role: string; content: string }> {\n // Get last 10 messages for context\n return this.messages.slice(-10).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n }\n\n public destroy(): void {\n this.container?.remove();\n document.getElementById('librebot-styles')?.remove();\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"librebot.esm.js","sources":["../src/styles.ts","../src/icons.ts","../src/widget.ts"],"sourcesContent":["export const getStyles = (primaryColor: string = '#14b8a6') => `\n .librebot-widget {\n --lb-primary: ${primaryColor};\n --lb-primary-hover: color-mix(in srgb, ${primaryColor} 85%, white);\n --lb-bg: #0f0f0f;\n --lb-bg-secondary: #1a1a1a;\n --lb-text: #ffffff;\n --lb-text-secondary: #9ca3af;\n --lb-border: #2a2a2a;\n font-family: 'Roboto Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .librebot-widget.light {\n --lb-bg: #ffffff;\n --lb-bg-secondary: #f5f5f5;\n --lb-text: #1a1a1a;\n --lb-text-secondary: #666666;\n --lb-border: #e0e0e0;\n }\n\n .librebot-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--lb-primary);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n z-index: 999998;\n }\n\n .librebot-fab:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n }\n\n .librebot-fab svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-fab.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-modal {\n position: fixed;\n bottom: 90px;\n right: 20px;\n width: 380px;\n max-width: calc(100vw - 40px);\n height: 520px;\n max-height: calc(100vh - 120px);\n background: var(--lb-bg);\n border: 1px solid var(--lb-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 999999;\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n }\n\n .librebot-modal.open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .librebot-modal.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-header {\n padding: 16px;\n border-bottom: 1px solid var(--lb-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .librebot-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .librebot-avatar {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: var(--lb-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-avatar svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-title {\n font-weight: 600;\n color: var(--lb-text);\n margin: 0;\n font-size: 16px;\n }\n\n .librebot-subtitle {\n font-size: 12px;\n color: var(--lb-text-secondary);\n margin: 0;\n }\n\n .librebot-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--lb-text-secondary);\n transition: background 0.2s;\n }\n\n .librebot-close:hover {\n background: var(--lb-bg-secondary);\n }\n\n .librebot-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .librebot-message {\n max-width: 85%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .librebot-message.user {\n align-self: flex-end;\n background: var(--lb-primary);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .librebot-message.assistant {\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n border-bottom-left-radius: 4px;\n }\n\n /* Inline code */\n .librebot-inline-code {\n background: rgba(0, 0, 0, 0.3);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n color: #f0f0f0;\n }\n\n .librebot-widget.light .librebot-inline-code {\n background: rgba(0, 0, 0, 0.08);\n color: #1a1a1a;\n }\n\n /* Code blocks */\n .librebot-code-block {\n background: #0d1117;\n padding: 12px 14px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 10px 0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n }\n\n .librebot-widget.light .librebot-code-block {\n background: #f6f8fa;\n border-color: rgba(0, 0, 0, 0.1);\n }\n\n .librebot-code-block code {\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #e6edf3;\n background: none;\n padding: 0;\n white-space: pre;\n display: block;\n }\n\n .librebot-widget.light .librebot-code-block code {\n color: #24292f;\n }\n\n .librebot-code-block[data-language]::before {\n content: attr(data-language);\n position: absolute;\n top: 6px;\n right: 10px;\n font-size: 10px;\n color: rgba(255, 255, 255, 0.4);\n text-transform: uppercase;\n font-family: 'Roboto Mono', monospace;\n }\n\n .librebot-widget.light .librebot-code-block[data-language]::before {\n color: rgba(0, 0, 0, 0.3);\n }\n\n /* Headers */\n .librebot-h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 12px 0 8px 0;\n color: var(--lb-text);\n }\n\n .librebot-h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 10px 0 6px 0;\n color: var(--lb-text);\n }\n\n .librebot-h4 {\n font-size: 13px;\n font-weight: 600;\n margin: 8px 0 4px 0;\n color: var(--lb-text);\n }\n\n /* Lists */\n .librebot-ul, .librebot-ol {\n margin: 8px 0;\n padding-left: 20px;\n }\n\n .librebot-ul {\n list-style-type: disc;\n }\n\n .librebot-ol {\n list-style-type: decimal;\n }\n\n .librebot-li, .librebot-li-ordered {\n margin: 4px 0;\n padding-left: 4px;\n line-height: 1.5;\n }\n\n /* Links */\n .librebot-link {\n color: var(--lb-primary);\n text-decoration: none;\n border-bottom: 1px solid transparent;\n transition: border-color 0.2s;\n }\n\n .librebot-link:hover {\n border-bottom-color: var(--lb-primary);\n }\n\n /* Blockquotes */\n .librebot-blockquote {\n border-left: 3px solid var(--lb-primary);\n margin: 8px 0;\n padding: 4px 12px;\n color: var(--lb-text-secondary);\n font-style: italic;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 0 6px 6px 0;\n }\n\n .librebot-widget.light .librebot-blockquote {\n background: rgba(0, 0, 0, 0.04);\n }\n\n /* Horizontal rule */\n .librebot-hr {\n border: none;\n border-top: 1px solid var(--lb-border);\n margin: 12px 0;\n }\n\n /* Strong and emphasis */\n .librebot-message strong {\n font-weight: 600;\n }\n\n .librebot-message em {\n font-style: italic;\n }\n\n /* Legacy support for old code elements */\n .librebot-message code:not(.librebot-inline-code) {\n background: rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 13px;\n }\n\n .librebot-message pre:not(.librebot-code-block) {\n background: rgba(0, 0, 0, 0.3);\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 8px 0;\n }\n\n .librebot-message pre:not(.librebot-code-block) code {\n background: none;\n padding: 0;\n }\n\n .librebot-typing {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .librebot-typing span {\n width: 8px;\n height: 8px;\n background: var(--lb-text-secondary);\n border-radius: 50%;\n animation: librebot-bounce 1.4s infinite ease-in-out;\n }\n\n .librebot-typing span:nth-child(1) { animation-delay: 0s; }\n .librebot-typing span:nth-child(2) { animation-delay: 0.2s; }\n .librebot-typing span:nth-child(3) { animation-delay: 0.4s; }\n\n @keyframes librebot-bounce {\n 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }\n 40% { transform: scale(1); opacity: 1; }\n }\n\n .librebot-input-area {\n padding: 12px 16px;\n border-top: 1px solid var(--lb-border);\n display: flex;\n gap: 8px;\n }\n\n .librebot-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--lb-border);\n border-radius: 24px;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .librebot-input:focus {\n border-color: var(--lb-primary);\n }\n\n .librebot-input::placeholder {\n color: var(--lb-text-secondary);\n }\n\n .librebot-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: var(--lb-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .librebot-send:hover {\n background: var(--lb-primary-hover);\n }\n\n .librebot-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .librebot-send svg {\n width: 18px;\n height: 18px;\n fill: white;\n }\n\n .librebot-welcome {\n text-align: center;\n padding: 20px;\n color: var(--lb-text-secondary);\n }\n\n .librebot-welcome-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n background: var(--lb-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-welcome-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .librebot-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--lb-text-secondary);\n border-top: 1px solid var(--lb-border);\n }\n\n .librebot-powered a {\n color: var(--lb-primary);\n text-decoration: none;\n }\n\n .librebot-powered a:hover {\n text-decoration: underline;\n }\n`;\n","export const chatIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path></svg>`;\n\nexport const closeIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg>`;\n\nexport const sendIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line><polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon></svg>`;\n\nexport const botIcon = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>`;\n","import { LibreBotConfig, Message, ChatResponse } from './types';\nimport { getStyles } from './styles';\nimport { chatIcon, closeIcon, sendIcon } from './icons';\n\nexport class LibreBotWidget {\n private config!: Required<LibreBotConfig>;\n private container: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private messagesContainer: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private isOpen = false;\n private messages: Message[] = [];\n private isLoading = false;\n\n private defaultConfig: Omit<Required<LibreBotConfig>, 'apiKey'> = {\n apiUrl: 'https://librebot.io/api',\n position: 'bottom-right',\n theme: 'dark',\n primaryColor: '#14b8a6',\n title: 'Libre Bot',\n subtitle: 'AI Documentation Assistant',\n placeholder: 'Ask a question...',\n welcomeMessage: 'Hi! I can help you find answers in the documentation. What would you like to know?',\n streaming: true,\n whiteLabel: false,\n autoLoadConfig: true,\n };\n\n constructor(config: LibreBotConfig) {\n if (!config.apiKey) {\n console.error('LibreBot: API key is required');\n return;\n }\n\n this.config = { ...this.defaultConfig, ...config } as Required<LibreBotConfig>;\n\n // Auto-load config from server if enabled and no custom settings provided\n if (this.config.autoLoadConfig) {\n this.loadRemoteConfig().then(() => this.init());\n } else {\n this.init();\n }\n }\n\n private async loadRemoteConfig(): Promise<void> {\n try {\n const response = await fetch(`${this.config.apiUrl}/widget-config?key=${this.config.apiKey}`);\n if (response.ok) {\n const remoteConfig = await response.json();\n // Merge remote config with local config (local overrides remote)\n this.config = {\n ...this.defaultConfig,\n ...remoteConfig,\n ...this.getProvidedConfig(),\n apiKey: this.config.apiKey,\n apiUrl: this.config.apiUrl,\n autoLoadConfig: this.config.autoLoadConfig,\n } as Required<LibreBotConfig>;\n }\n } catch (error) {\n console.warn('LibreBot: Could not load remote config, using defaults', error);\n }\n }\n\n private getProvidedConfig(): Partial<LibreBotConfig> {\n // Return only the config options that were explicitly provided (not default values)\n const provided: Partial<LibreBotConfig> = {};\n const userConfig = this.config;\n const defaults = this.defaultConfig;\n\n if (userConfig.position !== defaults.position) provided.position = userConfig.position;\n if (userConfig.theme !== defaults.theme) provided.theme = userConfig.theme;\n if (userConfig.primaryColor !== defaults.primaryColor) provided.primaryColor = userConfig.primaryColor;\n if (userConfig.title !== defaults.title) provided.title = userConfig.title;\n if (userConfig.subtitle !== defaults.subtitle) provided.subtitle = userConfig.subtitle;\n if (userConfig.placeholder !== defaults.placeholder) provided.placeholder = userConfig.placeholder;\n if (userConfig.welcomeMessage !== defaults.welcomeMessage) provided.welcomeMessage = userConfig.welcomeMessage;\n if (userConfig.streaming !== defaults.streaming) provided.streaming = userConfig.streaming;\n if (userConfig.whiteLabel !== defaults.whiteLabel) provided.whiteLabel = userConfig.whiteLabel;\n\n return provided;\n }\n\n private init(): void {\n // Inject styles\n this.injectStyles();\n\n // Create widget container\n this.createWidget();\n\n // Add welcome message\n if (this.config.welcomeMessage) {\n this.addMessage('assistant', this.config.welcomeMessage);\n }\n }\n\n private injectStyles(): void {\n const styleId = 'librebot-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = getStyles(this.config.primaryColor);\n document.head.appendChild(style);\n }\n\n private createWidget(): void {\n // Create container\n this.container = document.createElement('div');\n this.container.className = `librebot-widget ${this.config.theme === 'light' ? 'light' : ''}`;\n\n // Create FAB button\n const fab = document.createElement('button');\n fab.className = `librebot-fab ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n fab.innerHTML = chatIcon;\n fab.onclick = () => this.toggle();\n\n // Create modal\n this.modal = document.createElement('div');\n this.modal.className = `librebot-modal ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n this.modal.innerHTML = this.getModalHTML();\n\n // Add to container\n this.container.appendChild(fab);\n this.container.appendChild(this.modal);\n document.body.appendChild(this.container);\n\n // Get references\n this.messagesContainer = this.modal.querySelector('.librebot-messages');\n this.input = this.modal.querySelector('.librebot-input');\n\n // Add event listeners\n const closeBtn = this.modal.querySelector('.librebot-close');\n closeBtn?.addEventListener('click', () => this.close());\n\n const sendBtn = this.modal.querySelector('.librebot-send');\n sendBtn?.addEventListener('click', () => this.sendMessage());\n\n this.input?.addEventListener('keypress', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.sendMessage();\n }\n });\n\n // Auto theme detection\n if (this.config.theme === 'auto') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: light)');\n this.updateTheme(mediaQuery.matches);\n mediaQuery.addEventListener('change', (e) => this.updateTheme(e.matches));\n }\n }\n\n private getModalHTML(): string {\n const poweredByHtml = this.config.whiteLabel\n ? ''\n : `<div class=\"librebot-powered\">\n Powered by <a href=\"https://librebot.io\" target=\"_blank\">Libre Bot</a>\n </div>`;\n\n return `\n <div class=\"librebot-header\">\n <div class=\"librebot-header-content\">\n <div class=\"librebot-avatar\">${chatIcon}</div>\n <div>\n <h3 class=\"librebot-title\">${this.config.title}</h3>\n <p class=\"librebot-subtitle\">${this.config.subtitle}</p>\n </div>\n </div>\n <button class=\"librebot-close\">${closeIcon}</button>\n </div>\n <div class=\"librebot-messages\"></div>\n <div class=\"librebot-input-area\">\n <input type=\"text\" class=\"librebot-input\" placeholder=\"${this.config.placeholder}\" />\n <button class=\"librebot-send\">${sendIcon}</button>\n </div>\n ${poweredByHtml}\n `;\n }\n\n private updateTheme(isLight: boolean): void {\n if (isLight) {\n this.container?.classList.add('light');\n } else {\n this.container?.classList.remove('light');\n }\n }\n\n public toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n public open(): void {\n this.isOpen = true;\n this.modal?.classList.add('open');\n this.input?.focus();\n }\n\n public close(): void {\n this.isOpen = false;\n this.modal?.classList.remove('open');\n }\n\n private addMessage(role: 'user' | 'assistant', content: string): void {\n const message: Message = {\n id: `msg-${Date.now()}`,\n role,\n content,\n timestamp: new Date(),\n };\n\n this.messages.push(message);\n this.renderMessage(message);\n }\n\n private renderMessage(message: Message): void {\n if (!this.messagesContainer) return;\n\n const el = document.createElement('div');\n el.className = `librebot-message ${message.role}`;\n el.innerHTML = this.formatMessage(message.content);\n\n this.messagesContainer.appendChild(el);\n this.scrollToBottom();\n }\n\n private formatMessage(content: string): string {\n // Escape HTML to prevent XSS\n const escapeHtml = (text: string): string => {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n };\n\n // First, extract code blocks to protect them from other formatting\n // Regex handles optional space/newline after ``` and optional language identifier\n const codeBlocks: string[] = [];\n let processed = content.replace(/```\\s*(\\w*)\\s*\\n?([\\s\\S]*?)```/g, (_, lang, code) => {\n const escaped = escapeHtml(code.trim());\n const langClass = lang ? ` data-language=\"${escapeHtml(lang)}\"` : '';\n codeBlocks.push(`<pre class=\"librebot-code-block\"${langClass}><code>${escaped}</code></pre>`);\n return `%%CODEBLOCK${codeBlocks.length - 1}%%`;\n });\n\n // Extract inline code\n const inlineCodes: string[] = [];\n processed = processed.replace(/`([^`]+)`/g, (_, code) => {\n inlineCodes.push(`<code class=\"librebot-inline-code\">${escapeHtml(code)}</code>`);\n return `%%INLINECODE${inlineCodes.length - 1}%%`;\n });\n\n // Now escape remaining HTML\n processed = escapeHtml(processed);\n\n // Headers (## and ###)\n processed = processed.replace(/^### (.+)$/gm, '<h4 class=\"librebot-h4\">$1</h4>');\n processed = processed.replace(/^## (.+)$/gm, '<h3 class=\"librebot-h3\">$1</h3>');\n processed = processed.replace(/^# (.+)$/gm, '<h2 class=\"librebot-h2\">$1</h2>');\n\n // Bold and italic\n processed = processed.replace(/\\*\\*\\*([^*]+)\\*\\*\\*/g, '<strong><em>$1</em></strong>');\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n processed = processed.replace(/_([^_]+)_/g, '<em>$1</em>');\n\n // Links [text](url)\n processed = processed.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"librebot-link\">$1</a>');\n\n // Unordered lists\n processed = processed.replace(/^[\\*\\-] (.+)$/gm, '<li class=\"librebot-li\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ul class=\"librebot-ul\">${match}</ul>`;\n });\n\n // Ordered lists\n processed = processed.replace(/^\\d+\\. (.+)$/gm, '<li class=\"librebot-li-ordered\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li-ordered\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ol class=\"librebot-ol\">${match}</ol>`;\n });\n\n // Horizontal rule\n processed = processed.replace(/^---$/gm, '<hr class=\"librebot-hr\">');\n\n // Blockquotes\n processed = processed.replace(/^&gt; (.+)$/gm, '<blockquote class=\"librebot-blockquote\">$1</blockquote>');\n\n // Convert newlines to <br> (but not inside lists/blockquotes)\n processed = processed.replace(/\\n/g, '<br>');\n\n // Clean up extra <br> after block elements\n processed = processed.replace(/<\\/(pre|ul|ol|blockquote|h[2-4])><br>/g, '</$1>');\n processed = processed.replace(/<br><(pre|ul|ol|blockquote|h[2-4])/g, '<$1');\n\n // Restore code blocks\n codeBlocks.forEach((block, i) => {\n processed = processed.replace(`%%CODEBLOCK${i}%%`, block);\n });\n\n // Restore inline code\n inlineCodes.forEach((code, i) => {\n processed = processed.replace(`%%INLINECODE${i}%%`, code);\n });\n\n return processed;\n }\n\n private showTyping(): HTMLDivElement {\n const typing = document.createElement('div');\n typing.className = 'librebot-typing';\n typing.innerHTML = '<span></span><span></span><span></span>';\n this.messagesContainer?.appendChild(typing);\n this.scrollToBottom();\n return typing;\n }\n\n private scrollToBottom(): void {\n if (this.messagesContainer) {\n this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;\n }\n }\n\n private async sendMessage(): Promise<void> {\n if (!this.input || this.isLoading) return;\n\n const content = this.input.value.trim();\n if (!content) return;\n\n // Add user message\n this.addMessage('user', content);\n this.input.value = '';\n\n // Show typing indicator\n this.isLoading = true;\n const typing = this.showTyping();\n\n try {\n if (this.config.streaming) {\n await this.callStreamingAPI(content, typing);\n } else {\n const response = await this.callAPI(content);\n typing.remove();\n\n if (response.error) {\n this.addMessage('assistant', `Sorry, I encountered an error: ${response.error}`);\n } else {\n this.addMessage('assistant', response.response);\n }\n }\n } catch (error) {\n typing.remove();\n this.addMessage('assistant', 'Sorry, I had trouble connecting. Please try again.');\n console.error('LibreBot error:', error);\n } finally {\n this.isLoading = false;\n }\n }\n\n private async callStreamingAPI(message: string, typing: HTMLDivElement): Promise<void> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n stream: true,\n }),\n });\n\n if (!response.ok) {\n typing.remove();\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n this.addMessage('assistant', `Sorry, I encountered an error: ${error.error || 'Request failed'}`);\n return;\n }\n\n // Remove typing indicator and create streaming message element\n typing.remove();\n const messageEl = document.createElement('div');\n messageEl.className = 'librebot-message assistant';\n this.messagesContainer?.appendChild(messageEl);\n\n const reader = response.body?.getReader();\n if (!reader) {\n this.addMessage('assistant', 'Sorry, streaming is not supported.');\n return;\n }\n\n const decoder = new TextDecoder();\n let fullContent = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n const lines = chunk.split('\\n').filter((line) => line.trim() !== '');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) {\n fullContent += parsed.content;\n messageEl.innerHTML = this.formatMessage(fullContent);\n this.scrollToBottom();\n }\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n } catch (error) {\n console.error('Stream reading error:', error);\n }\n\n // Add to messages array\n this.messages.push({\n id: `msg-${Date.now()}`,\n role: 'assistant',\n content: fullContent,\n timestamp: new Date(),\n });\n }\n\n private async callAPI(message: string): Promise<ChatResponse> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n return { response: '', error: error.error || 'Request failed' };\n }\n\n return response.json();\n }\n\n private getConversationContext(): Array<{ role: string; content: string }> {\n // Get last 10 messages for context\n return this.messages.slice(-10).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n }\n\n public destroy(): void {\n this.container?.remove();\n document.getElementById('librebot-styles')?.remove();\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/librebot.js CHANGED
@@ -1,2 +1,2 @@
1
- var LibreBot=function(e){"use strict";const n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>';class t{constructor(e){this.container=null,this.modal=null,this.messagesContainer=null,this.input=null,this.isOpen=!1,this.messages=[],this.isLoading=!1,this.defaultConfig={apiUrl:"https://librebot.io/api",position:"bottom-right",theme:"dark",primaryColor:"#14b8a6",title:"Libre Bot",subtitle:"AI Documentation Assistant",placeholder:"Ask a question...",welcomeMessage:"Hi! I can help you find answers in the documentation. What would you like to know?",streaming:!0,whiteLabel:!1,autoLoadConfig:!0},e.apiKey?(this.config={...this.defaultConfig,...e},this.config.autoLoadConfig?this.loadRemoteConfig().then(()=>this.init()):this.init()):console.error("LibreBot: API key is required")}async loadRemoteConfig(){try{const e=await fetch(`${this.config.apiUrl}/widget-config?key=${this.config.apiKey}`);if(e.ok){const n=await e.json();this.config={...this.defaultConfig,...n,...this.getProvidedConfig(),apiKey:this.config.apiKey,apiUrl:this.config.apiUrl,autoLoadConfig:this.config.autoLoadConfig}}}catch(e){console.warn("LibreBot: Could not load remote config, using defaults",e)}}getProvidedConfig(){const e={},n=this.config,t=this.defaultConfig;return n.position!==t.position&&(e.position=n.position),n.theme!==t.theme&&(e.theme=n.theme),n.primaryColor!==t.primaryColor&&(e.primaryColor=n.primaryColor),n.title!==t.title&&(e.title=n.title),n.subtitle!==t.subtitle&&(e.subtitle=n.subtitle),n.placeholder!==t.placeholder&&(e.placeholder=n.placeholder),n.welcomeMessage!==t.welcomeMessage&&(e.welcomeMessage=n.welcomeMessage),n.streaming!==t.streaming&&(e.streaming=n.streaming),n.whiteLabel!==t.whiteLabel&&(e.whiteLabel=n.whiteLabel),e}init(){this.injectStyles(),this.createWidget(),this.config.welcomeMessage&&this.addMessage("assistant",this.config.welcomeMessage)}injectStyles(){const e="librebot-styles";if(document.getElementById(e))return;const n=document.createElement("style");n.id=e,n.textContent=((e="#14b8a6")=>`\n .librebot-widget {\n --lb-primary: ${e};\n --lb-primary-hover: color-mix(in srgb, ${e} 85%, white);\n --lb-bg: #0f0f0f;\n --lb-bg-secondary: #1a1a1a;\n --lb-text: #ffffff;\n --lb-text-secondary: #9ca3af;\n --lb-border: #2a2a2a;\n font-family: 'Roboto Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .librebot-widget.light {\n --lb-bg: #ffffff;\n --lb-bg-secondary: #f5f5f5;\n --lb-text: #1a1a1a;\n --lb-text-secondary: #666666;\n --lb-border: #e0e0e0;\n }\n\n .librebot-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--lb-primary);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n z-index: 999998;\n }\n\n .librebot-fab:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n }\n\n .librebot-fab svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-fab.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-modal {\n position: fixed;\n bottom: 90px;\n right: 20px;\n width: 380px;\n max-width: calc(100vw - 40px);\n height: 520px;\n max-height: calc(100vh - 120px);\n background: var(--lb-bg);\n border: 1px solid var(--lb-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 999999;\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n }\n\n .librebot-modal.open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .librebot-modal.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-header {\n padding: 16px;\n border-bottom: 1px solid var(--lb-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .librebot-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .librebot-avatar {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: var(--lb-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-avatar svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-title {\n font-weight: 600;\n color: var(--lb-text);\n margin: 0;\n font-size: 16px;\n }\n\n .librebot-subtitle {\n font-size: 12px;\n color: var(--lb-text-secondary);\n margin: 0;\n }\n\n .librebot-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--lb-text-secondary);\n transition: background 0.2s;\n }\n\n .librebot-close:hover {\n background: var(--lb-bg-secondary);\n }\n\n .librebot-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .librebot-message {\n max-width: 85%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .librebot-message.user {\n align-self: flex-end;\n background: var(--lb-primary);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .librebot-message.assistant {\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n border-bottom-left-radius: 4px;\n }\n\n /* Inline code */\n .librebot-inline-code {\n background: rgba(0, 0, 0, 0.3);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n color: #f0f0f0;\n }\n\n .librebot-widget.light .librebot-inline-code {\n background: rgba(0, 0, 0, 0.08);\n color: #1a1a1a;\n }\n\n /* Code blocks */\n .librebot-code-block {\n background: #0d1117;\n padding: 12px 14px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 10px 0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n }\n\n .librebot-widget.light .librebot-code-block {\n background: #f6f8fa;\n border-color: rgba(0, 0, 0, 0.1);\n }\n\n .librebot-code-block code {\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #e6edf3;\n background: none;\n padding: 0;\n white-space: pre;\n display: block;\n }\n\n .librebot-widget.light .librebot-code-block code {\n color: #24292f;\n }\n\n .librebot-code-block[data-language]::before {\n content: attr(data-language);\n position: absolute;\n top: 6px;\n right: 10px;\n font-size: 10px;\n color: rgba(255, 255, 255, 0.4);\n text-transform: uppercase;\n font-family: 'Roboto Mono', monospace;\n }\n\n .librebot-widget.light .librebot-code-block[data-language]::before {\n color: rgba(0, 0, 0, 0.3);\n }\n\n /* Headers */\n .librebot-h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 12px 0 8px 0;\n color: var(--lb-text);\n }\n\n .librebot-h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 10px 0 6px 0;\n color: var(--lb-text);\n }\n\n .librebot-h4 {\n font-size: 13px;\n font-weight: 600;\n margin: 8px 0 4px 0;\n color: var(--lb-text);\n }\n\n /* Lists */\n .librebot-ul, .librebot-ol {\n margin: 8px 0;\n padding-left: 20px;\n }\n\n .librebot-ul {\n list-style-type: disc;\n }\n\n .librebot-ol {\n list-style-type: decimal;\n }\n\n .librebot-li, .librebot-li-ordered {\n margin: 4px 0;\n padding-left: 4px;\n line-height: 1.5;\n }\n\n /* Links */\n .librebot-link {\n color: var(--lb-primary);\n text-decoration: none;\n border-bottom: 1px solid transparent;\n transition: border-color 0.2s;\n }\n\n .librebot-link:hover {\n border-bottom-color: var(--lb-primary);\n }\n\n /* Blockquotes */\n .librebot-blockquote {\n border-left: 3px solid var(--lb-primary);\n margin: 8px 0;\n padding: 4px 12px;\n color: var(--lb-text-secondary);\n font-style: italic;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 0 6px 6px 0;\n }\n\n .librebot-widget.light .librebot-blockquote {\n background: rgba(0, 0, 0, 0.04);\n }\n\n /* Horizontal rule */\n .librebot-hr {\n border: none;\n border-top: 1px solid var(--lb-border);\n margin: 12px 0;\n }\n\n /* Strong and emphasis */\n .librebot-message strong {\n font-weight: 600;\n }\n\n .librebot-message em {\n font-style: italic;\n }\n\n /* Legacy support for old code elements */\n .librebot-message code:not(.librebot-inline-code) {\n background: rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 13px;\n }\n\n .librebot-message pre:not(.librebot-code-block) {\n background: rgba(0, 0, 0, 0.3);\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 8px 0;\n }\n\n .librebot-message pre:not(.librebot-code-block) code {\n background: none;\n padding: 0;\n }\n\n .librebot-typing {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .librebot-typing span {\n width: 8px;\n height: 8px;\n background: var(--lb-text-secondary);\n border-radius: 50%;\n animation: librebot-bounce 1.4s infinite ease-in-out;\n }\n\n .librebot-typing span:nth-child(1) { animation-delay: 0s; }\n .librebot-typing span:nth-child(2) { animation-delay: 0.2s; }\n .librebot-typing span:nth-child(3) { animation-delay: 0.4s; }\n\n @keyframes librebot-bounce {\n 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }\n 40% { transform: scale(1); opacity: 1; }\n }\n\n .librebot-input-area {\n padding: 12px 16px;\n border-top: 1px solid var(--lb-border);\n display: flex;\n gap: 8px;\n }\n\n .librebot-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--lb-border);\n border-radius: 24px;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .librebot-input:focus {\n border-color: var(--lb-primary);\n }\n\n .librebot-input::placeholder {\n color: var(--lb-text-secondary);\n }\n\n .librebot-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: var(--lb-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .librebot-send:hover {\n background: var(--lb-primary-hover);\n }\n\n .librebot-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .librebot-send svg {\n width: 18px;\n height: 18px;\n fill: white;\n }\n\n .librebot-welcome {\n text-align: center;\n padding: 20px;\n color: var(--lb-text-secondary);\n }\n\n .librebot-welcome-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n background: var(--lb-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-welcome-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .librebot-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--lb-text-secondary);\n border-top: 1px solid var(--lb-border);\n }\n\n .librebot-powered a {\n color: var(--lb-primary);\n text-decoration: none;\n }\n\n .librebot-powered a:hover {\n text-decoration: underline;\n }\n`)(this.config.primaryColor),document.head.appendChild(n)}createWidget(){this.container=document.createElement("div"),this.container.className="librebot-widget "+("light"===this.config.theme?"light":"");const e=document.createElement("button");e.className="librebot-fab "+("bottom-left"===this.config.position?"left":""),e.innerHTML=n,e.onclick=()=>this.toggle(),this.modal=document.createElement("div"),this.modal.className="librebot-modal "+("bottom-left"===this.config.position?"left":""),this.modal.innerHTML=this.getModalHTML(),this.container.appendChild(e),this.container.appendChild(this.modal),document.body.appendChild(this.container),this.messagesContainer=this.modal.querySelector(".librebot-messages"),this.input=this.modal.querySelector(".librebot-input");const t=this.modal.querySelector(".librebot-close");t?.addEventListener("click",()=>this.close());const o=this.modal.querySelector(".librebot-send");if(o?.addEventListener("click",()=>this.sendMessage()),this.input?.addEventListener("keypress",e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),this.sendMessage())}),"auto"===this.config.theme){const e=window.matchMedia("(prefers-color-scheme: light)");this.updateTheme(e.matches),e.addEventListener("change",e=>this.updateTheme(e.matches))}}getModalHTML(){const e=this.config.whiteLabel?"":'<div class="librebot-powered">\n Powered by <a href="https://librebot.io" target="_blank">Libre Bot</a>\n </div>';return`\n <div class="librebot-header">\n <div class="librebot-header-content">\n <div class="librebot-avatar">${n}</div>\n <div>\n <h3 class="librebot-title">${this.config.title}</h3>\n <p class="librebot-subtitle">${this.config.subtitle}</p>\n </div>\n </div>\n <button class="librebot-close"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>\n </div>\n <div class="librebot-messages"></div>\n <div class="librebot-input-area">\n <input type="text" class="librebot-input" placeholder="${this.config.placeholder}" />\n <button class="librebot-send"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg></button>\n </div>\n ${e}\n `}updateTheme(e){e?this.container?.classList.add("light"):this.container?.classList.remove("light")}toggle(){this.isOpen?this.close():this.open()}open(){this.isOpen=!0,this.modal?.classList.add("open"),this.input?.focus()}close(){this.isOpen=!1,this.modal?.classList.remove("open")}addMessage(e,n){const t={id:`msg-${Date.now()}`,role:e,content:n,timestamp:new Date};this.messages.push(t),this.renderMessage(t)}renderMessage(e){if(!this.messagesContainer)return;const n=document.createElement("div");n.className=`librebot-message ${e.role}`,n.innerHTML=this.formatMessage(e.content),this.messagesContainer.appendChild(n),this.scrollToBottom()}formatMessage(e){const n=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;"),t=[];let o=e.replace(/```(\w*)\n?([\s\S]*?)```/g,(e,o,i)=>{const r=n(i.trim()),a=o?` data-language="${n(o)}"`:"";return t.push(`<pre class="librebot-code-block"${a}><code>${r}</code></pre>`),`%%CODEBLOCK${t.length-1}%%`});const i=[];return o=o.replace(/`([^`]+)`/g,(e,t)=>(i.push(`<code class="librebot-inline-code">${n(t)}</code>`),`%%INLINECODE${i.length-1}%%`)),o=n(o),o=o.replace(/^### (.+)$/gm,'<h4 class="librebot-h4">$1</h4>'),o=o.replace(/^## (.+)$/gm,'<h3 class="librebot-h3">$1</h3>'),o=o.replace(/^# (.+)$/gm,'<h2 class="librebot-h2">$1</h2>'),o=o.replace(/\*\*\*([^*]+)\*\*\*/g,"<strong><em>$1</em></strong>"),o=o.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),o=o.replace(/\*([^*]+)\*/g,"<em>$1</em>"),o=o.replace(/_([^_]+)_/g,"<em>$1</em>"),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer" class="librebot-link">$1</a>'),o=o.replace(/^[\*\-] (.+)$/gm,'<li class="librebot-li">$1</li>'),o=o.replace(/(<li class="librebot-li">.*<\/li>\n?)+/g,e=>`<ul class="librebot-ul">${e}</ul>`),o=o.replace(/^\d+\. (.+)$/gm,'<li class="librebot-li-ordered">$1</li>'),o=o.replace(/(<li class="librebot-li-ordered">.*<\/li>\n?)+/g,e=>`<ol class="librebot-ol">${e}</ol>`),o=o.replace(/^---$/gm,'<hr class="librebot-hr">'),o=o.replace(/^&gt; (.+)$/gm,'<blockquote class="librebot-blockquote">$1</blockquote>'),o=o.replace(/\n/g,"<br>"),o=o.replace(/<\/(pre|ul|ol|blockquote|h[2-4])><br>/g,"</$1>"),o=o.replace(/<br><(pre|ul|ol|blockquote|h[2-4])/g,"<$1"),t.forEach((e,n)=>{o=o.replace(`%%CODEBLOCK${n}%%`,e)}),i.forEach((e,n)=>{o=o.replace(`%%INLINECODE${n}%%`,e)}),o}showTyping(){const e=document.createElement("div");return e.className="librebot-typing",e.innerHTML="<span></span><span></span><span></span>",this.messagesContainer?.appendChild(e),this.scrollToBottom(),e}scrollToBottom(){this.messagesContainer&&(this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight)}async sendMessage(){if(!this.input||this.isLoading)return;const e=this.input.value.trim();if(!e)return;this.addMessage("user",e),this.input.value="",this.isLoading=!0;const n=this.showTyping();try{if(this.config.streaming)await this.callStreamingAPI(e,n);else{const t=await this.callAPI(e);n.remove(),t.error?this.addMessage("assistant",`Sorry, I encountered an error: ${t.error}`):this.addMessage("assistant",t.response)}}catch(e){n.remove(),this.addMessage("assistant","Sorry, I had trouble connecting. Please try again."),console.error("LibreBot error:",e)}finally{this.isLoading=!1}}async callStreamingAPI(e,n){const t=await fetch(`${this.config.apiUrl}/chat`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({message:e,context:this.getConversationContext(),stream:!0})});if(!t.ok){n.remove();const e=await t.json().catch(()=>({error:"Request failed"}));return void this.addMessage("assistant",`Sorry, I encountered an error: ${e.error||"Request failed"}`)}n.remove();const o=document.createElement("div");o.className="librebot-message assistant",this.messagesContainer?.appendChild(o);const i=t.body?.getReader();if(!i)return void this.addMessage("assistant","Sorry, streaming is not supported.");const r=new TextDecoder;let a="";try{for(;;){const{done:e,value:n}=await i.read();if(e)break;const t=r.decode(n,{stream:!0}).split("\n").filter(e=>""!==e.trim());for(const e of t)if(e.startsWith("data: ")){const n=e.slice(6);if("[DONE]"===n)continue;try{const e=JSON.parse(n);e.content&&(a+=e.content,o.innerHTML=this.formatMessage(a),this.scrollToBottom())}catch{}}}}catch(e){console.error("Stream reading error:",e)}this.messages.push({id:`msg-${Date.now()}`,role:"assistant",content:a,timestamp:new Date})}async callAPI(e){const n=await fetch(`${this.config.apiUrl}/chat`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({message:e,context:this.getConversationContext()})});if(!n.ok){return{response:"",error:(await n.json().catch(()=>({error:"Request failed"}))).error||"Request failed"}}return n.json()}getConversationContext(){return this.messages.slice(-10).map(e=>({role:e.role,content:e.content}))}destroy(){this.container?.remove(),document.getElementById("librebot-styles")?.remove()}}return function(){const e=document.currentScript||document.querySelector('script[data-key][src*="librebot"]');if(!e)return void console.warn("LibreBot: Could not find script tag");const n={apiKey:e.dataset.key||e.dataset.apiKey||"",apiUrl:e.dataset.apiUrl||"https://api.librebot.io",position:e.dataset.position||"bottom-right",theme:e.dataset.theme||"dark",primaryColor:e.dataset.color||"#14b8a6",title:e.dataset.title||"Libre Bot",subtitle:e.dataset.subtitle||"AI Documentation Assistant",placeholder:e.dataset.placeholder||"Ask a question...",welcomeMessage:e.dataset.welcome||"Hi! I can help you find answers in the documentation. What would you like to know?",streaming:"false"!==e.dataset.streaming};n.apiKey?"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{window.LibreBot=new t(n)}):window.LibreBot=new t(n):console.error("LibreBot: Missing data-key attribute")}(),e.LibreBotWidget=t,e}({});
1
+ var LibreBot=function(e){"use strict";const n='<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>';class t{constructor(e){this.container=null,this.modal=null,this.messagesContainer=null,this.input=null,this.isOpen=!1,this.messages=[],this.isLoading=!1,this.defaultConfig={apiUrl:"https://librebot.io/api",position:"bottom-right",theme:"dark",primaryColor:"#14b8a6",title:"Libre Bot",subtitle:"AI Documentation Assistant",placeholder:"Ask a question...",welcomeMessage:"Hi! I can help you find answers in the documentation. What would you like to know?",streaming:!0,whiteLabel:!1,autoLoadConfig:!0},e.apiKey?(this.config={...this.defaultConfig,...e},this.config.autoLoadConfig?this.loadRemoteConfig().then(()=>this.init()):this.init()):console.error("LibreBot: API key is required")}async loadRemoteConfig(){try{const e=await fetch(`${this.config.apiUrl}/widget-config?key=${this.config.apiKey}`);if(e.ok){const n=await e.json();this.config={...this.defaultConfig,...n,...this.getProvidedConfig(),apiKey:this.config.apiKey,apiUrl:this.config.apiUrl,autoLoadConfig:this.config.autoLoadConfig}}}catch(e){console.warn("LibreBot: Could not load remote config, using defaults",e)}}getProvidedConfig(){const e={},n=this.config,t=this.defaultConfig;return n.position!==t.position&&(e.position=n.position),n.theme!==t.theme&&(e.theme=n.theme),n.primaryColor!==t.primaryColor&&(e.primaryColor=n.primaryColor),n.title!==t.title&&(e.title=n.title),n.subtitle!==t.subtitle&&(e.subtitle=n.subtitle),n.placeholder!==t.placeholder&&(e.placeholder=n.placeholder),n.welcomeMessage!==t.welcomeMessage&&(e.welcomeMessage=n.welcomeMessage),n.streaming!==t.streaming&&(e.streaming=n.streaming),n.whiteLabel!==t.whiteLabel&&(e.whiteLabel=n.whiteLabel),e}init(){this.injectStyles(),this.createWidget(),this.config.welcomeMessage&&this.addMessage("assistant",this.config.welcomeMessage)}injectStyles(){const e="librebot-styles";if(document.getElementById(e))return;const n=document.createElement("style");n.id=e,n.textContent=((e="#14b8a6")=>`\n .librebot-widget {\n --lb-primary: ${e};\n --lb-primary-hover: color-mix(in srgb, ${e} 85%, white);\n --lb-bg: #0f0f0f;\n --lb-bg-secondary: #1a1a1a;\n --lb-text: #ffffff;\n --lb-text-secondary: #9ca3af;\n --lb-border: #2a2a2a;\n font-family: 'Roboto Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .librebot-widget.light {\n --lb-bg: #ffffff;\n --lb-bg-secondary: #f5f5f5;\n --lb-text: #1a1a1a;\n --lb-text-secondary: #666666;\n --lb-border: #e0e0e0;\n }\n\n .librebot-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--lb-primary);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n z-index: 999998;\n }\n\n .librebot-fab:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n }\n\n .librebot-fab svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-fab.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-modal {\n position: fixed;\n bottom: 90px;\n right: 20px;\n width: 380px;\n max-width: calc(100vw - 40px);\n height: 520px;\n max-height: calc(100vh - 120px);\n background: var(--lb-bg);\n border: 1px solid var(--lb-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 999999;\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n }\n\n .librebot-modal.open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .librebot-modal.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-header {\n padding: 16px;\n border-bottom: 1px solid var(--lb-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .librebot-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .librebot-avatar {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: var(--lb-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-avatar svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-title {\n font-weight: 600;\n color: var(--lb-text);\n margin: 0;\n font-size: 16px;\n }\n\n .librebot-subtitle {\n font-size: 12px;\n color: var(--lb-text-secondary);\n margin: 0;\n }\n\n .librebot-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--lb-text-secondary);\n transition: background 0.2s;\n }\n\n .librebot-close:hover {\n background: var(--lb-bg-secondary);\n }\n\n .librebot-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .librebot-message {\n max-width: 85%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .librebot-message.user {\n align-self: flex-end;\n background: var(--lb-primary);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .librebot-message.assistant {\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n border-bottom-left-radius: 4px;\n }\n\n /* Inline code */\n .librebot-inline-code {\n background: rgba(0, 0, 0, 0.3);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n color: #f0f0f0;\n }\n\n .librebot-widget.light .librebot-inline-code {\n background: rgba(0, 0, 0, 0.08);\n color: #1a1a1a;\n }\n\n /* Code blocks */\n .librebot-code-block {\n background: #0d1117;\n padding: 12px 14px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 10px 0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n }\n\n .librebot-widget.light .librebot-code-block {\n background: #f6f8fa;\n border-color: rgba(0, 0, 0, 0.1);\n }\n\n .librebot-code-block code {\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #e6edf3;\n background: none;\n padding: 0;\n white-space: pre;\n display: block;\n }\n\n .librebot-widget.light .librebot-code-block code {\n color: #24292f;\n }\n\n .librebot-code-block[data-language]::before {\n content: attr(data-language);\n position: absolute;\n top: 6px;\n right: 10px;\n font-size: 10px;\n color: rgba(255, 255, 255, 0.4);\n text-transform: uppercase;\n font-family: 'Roboto Mono', monospace;\n }\n\n .librebot-widget.light .librebot-code-block[data-language]::before {\n color: rgba(0, 0, 0, 0.3);\n }\n\n /* Headers */\n .librebot-h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 12px 0 8px 0;\n color: var(--lb-text);\n }\n\n .librebot-h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 10px 0 6px 0;\n color: var(--lb-text);\n }\n\n .librebot-h4 {\n font-size: 13px;\n font-weight: 600;\n margin: 8px 0 4px 0;\n color: var(--lb-text);\n }\n\n /* Lists */\n .librebot-ul, .librebot-ol {\n margin: 8px 0;\n padding-left: 20px;\n }\n\n .librebot-ul {\n list-style-type: disc;\n }\n\n .librebot-ol {\n list-style-type: decimal;\n }\n\n .librebot-li, .librebot-li-ordered {\n margin: 4px 0;\n padding-left: 4px;\n line-height: 1.5;\n }\n\n /* Links */\n .librebot-link {\n color: var(--lb-primary);\n text-decoration: none;\n border-bottom: 1px solid transparent;\n transition: border-color 0.2s;\n }\n\n .librebot-link:hover {\n border-bottom-color: var(--lb-primary);\n }\n\n /* Blockquotes */\n .librebot-blockquote {\n border-left: 3px solid var(--lb-primary);\n margin: 8px 0;\n padding: 4px 12px;\n color: var(--lb-text-secondary);\n font-style: italic;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 0 6px 6px 0;\n }\n\n .librebot-widget.light .librebot-blockquote {\n background: rgba(0, 0, 0, 0.04);\n }\n\n /* Horizontal rule */\n .librebot-hr {\n border: none;\n border-top: 1px solid var(--lb-border);\n margin: 12px 0;\n }\n\n /* Strong and emphasis */\n .librebot-message strong {\n font-weight: 600;\n }\n\n .librebot-message em {\n font-style: italic;\n }\n\n /* Legacy support for old code elements */\n .librebot-message code:not(.librebot-inline-code) {\n background: rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 13px;\n }\n\n .librebot-message pre:not(.librebot-code-block) {\n background: rgba(0, 0, 0, 0.3);\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 8px 0;\n }\n\n .librebot-message pre:not(.librebot-code-block) code {\n background: none;\n padding: 0;\n }\n\n .librebot-typing {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .librebot-typing span {\n width: 8px;\n height: 8px;\n background: var(--lb-text-secondary);\n border-radius: 50%;\n animation: librebot-bounce 1.4s infinite ease-in-out;\n }\n\n .librebot-typing span:nth-child(1) { animation-delay: 0s; }\n .librebot-typing span:nth-child(2) { animation-delay: 0.2s; }\n .librebot-typing span:nth-child(3) { animation-delay: 0.4s; }\n\n @keyframes librebot-bounce {\n 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }\n 40% { transform: scale(1); opacity: 1; }\n }\n\n .librebot-input-area {\n padding: 12px 16px;\n border-top: 1px solid var(--lb-border);\n display: flex;\n gap: 8px;\n }\n\n .librebot-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--lb-border);\n border-radius: 24px;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .librebot-input:focus {\n border-color: var(--lb-primary);\n }\n\n .librebot-input::placeholder {\n color: var(--lb-text-secondary);\n }\n\n .librebot-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: var(--lb-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .librebot-send:hover {\n background: var(--lb-primary-hover);\n }\n\n .librebot-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .librebot-send svg {\n width: 18px;\n height: 18px;\n fill: white;\n }\n\n .librebot-welcome {\n text-align: center;\n padding: 20px;\n color: var(--lb-text-secondary);\n }\n\n .librebot-welcome-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n background: var(--lb-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-welcome-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .librebot-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--lb-text-secondary);\n border-top: 1px solid var(--lb-border);\n }\n\n .librebot-powered a {\n color: var(--lb-primary);\n text-decoration: none;\n }\n\n .librebot-powered a:hover {\n text-decoration: underline;\n }\n`)(this.config.primaryColor),document.head.appendChild(n)}createWidget(){this.container=document.createElement("div"),this.container.className="librebot-widget "+("light"===this.config.theme?"light":"");const e=document.createElement("button");e.className="librebot-fab "+("bottom-left"===this.config.position?"left":""),e.innerHTML=n,e.onclick=()=>this.toggle(),this.modal=document.createElement("div"),this.modal.className="librebot-modal "+("bottom-left"===this.config.position?"left":""),this.modal.innerHTML=this.getModalHTML(),this.container.appendChild(e),this.container.appendChild(this.modal),document.body.appendChild(this.container),this.messagesContainer=this.modal.querySelector(".librebot-messages"),this.input=this.modal.querySelector(".librebot-input");const t=this.modal.querySelector(".librebot-close");t?.addEventListener("click",()=>this.close());const o=this.modal.querySelector(".librebot-send");if(o?.addEventListener("click",()=>this.sendMessage()),this.input?.addEventListener("keypress",e=>{"Enter"!==e.key||e.shiftKey||(e.preventDefault(),this.sendMessage())}),"auto"===this.config.theme){const e=window.matchMedia("(prefers-color-scheme: light)");this.updateTheme(e.matches),e.addEventListener("change",e=>this.updateTheme(e.matches))}}getModalHTML(){const e=this.config.whiteLabel?"":'<div class="librebot-powered">\n Powered by <a href="https://librebot.io" target="_blank">Libre Bot</a>\n </div>';return`\n <div class="librebot-header">\n <div class="librebot-header-content">\n <div class="librebot-avatar">${n}</div>\n <div>\n <h3 class="librebot-title">${this.config.title}</h3>\n <p class="librebot-subtitle">${this.config.subtitle}</p>\n </div>\n </div>\n <button class="librebot-close"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></button>\n </div>\n <div class="librebot-messages"></div>\n <div class="librebot-input-area">\n <input type="text" class="librebot-input" placeholder="${this.config.placeholder}" />\n <button class="librebot-send"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg></button>\n </div>\n ${e}\n `}updateTheme(e){e?this.container?.classList.add("light"):this.container?.classList.remove("light")}toggle(){this.isOpen?this.close():this.open()}open(){this.isOpen=!0,this.modal?.classList.add("open"),this.input?.focus()}close(){this.isOpen=!1,this.modal?.classList.remove("open")}addMessage(e,n){const t={id:`msg-${Date.now()}`,role:e,content:n,timestamp:new Date};this.messages.push(t),this.renderMessage(t)}renderMessage(e){if(!this.messagesContainer)return;const n=document.createElement("div");n.className=`librebot-message ${e.role}`,n.innerHTML=this.formatMessage(e.content),this.messagesContainer.appendChild(n),this.scrollToBottom()}formatMessage(e){const n=e=>e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;"),t=[];let o=e.replace(/```\s*(\w*)\s*\n?([\s\S]*?)```/g,(e,o,i)=>{const r=n(i.trim()),a=o?` data-language="${n(o)}"`:"";return t.push(`<pre class="librebot-code-block"${a}><code>${r}</code></pre>`),`%%CODEBLOCK${t.length-1}%%`});const i=[];return o=o.replace(/`([^`]+)`/g,(e,t)=>(i.push(`<code class="librebot-inline-code">${n(t)}</code>`),`%%INLINECODE${i.length-1}%%`)),o=n(o),o=o.replace(/^### (.+)$/gm,'<h4 class="librebot-h4">$1</h4>'),o=o.replace(/^## (.+)$/gm,'<h3 class="librebot-h3">$1</h3>'),o=o.replace(/^# (.+)$/gm,'<h2 class="librebot-h2">$1</h2>'),o=o.replace(/\*\*\*([^*]+)\*\*\*/g,"<strong><em>$1</em></strong>"),o=o.replace(/\*\*([^*]+)\*\*/g,"<strong>$1</strong>"),o=o.replace(/\*([^*]+)\*/g,"<em>$1</em>"),o=o.replace(/_([^_]+)_/g,"<em>$1</em>"),o=o.replace(/\[([^\]]+)\]\(([^)]+)\)/g,'<a href="$2" target="_blank" rel="noopener noreferrer" class="librebot-link">$1</a>'),o=o.replace(/^[\*\-] (.+)$/gm,'<li class="librebot-li">$1</li>'),o=o.replace(/(<li class="librebot-li">.*<\/li>\n?)+/g,e=>`<ul class="librebot-ul">${e}</ul>`),o=o.replace(/^\d+\. (.+)$/gm,'<li class="librebot-li-ordered">$1</li>'),o=o.replace(/(<li class="librebot-li-ordered">.*<\/li>\n?)+/g,e=>`<ol class="librebot-ol">${e}</ol>`),o=o.replace(/^---$/gm,'<hr class="librebot-hr">'),o=o.replace(/^&gt; (.+)$/gm,'<blockquote class="librebot-blockquote">$1</blockquote>'),o=o.replace(/\n/g,"<br>"),o=o.replace(/<\/(pre|ul|ol|blockquote|h[2-4])><br>/g,"</$1>"),o=o.replace(/<br><(pre|ul|ol|blockquote|h[2-4])/g,"<$1"),t.forEach((e,n)=>{o=o.replace(`%%CODEBLOCK${n}%%`,e)}),i.forEach((e,n)=>{o=o.replace(`%%INLINECODE${n}%%`,e)}),o}showTyping(){const e=document.createElement("div");return e.className="librebot-typing",e.innerHTML="<span></span><span></span><span></span>",this.messagesContainer?.appendChild(e),this.scrollToBottom(),e}scrollToBottom(){this.messagesContainer&&(this.messagesContainer.scrollTop=this.messagesContainer.scrollHeight)}async sendMessage(){if(!this.input||this.isLoading)return;const e=this.input.value.trim();if(!e)return;this.addMessage("user",e),this.input.value="",this.isLoading=!0;const n=this.showTyping();try{if(this.config.streaming)await this.callStreamingAPI(e,n);else{const t=await this.callAPI(e);n.remove(),t.error?this.addMessage("assistant",`Sorry, I encountered an error: ${t.error}`):this.addMessage("assistant",t.response)}}catch(e){n.remove(),this.addMessage("assistant","Sorry, I had trouble connecting. Please try again."),console.error("LibreBot error:",e)}finally{this.isLoading=!1}}async callStreamingAPI(e,n){const t=await fetch(`${this.config.apiUrl}/chat`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({message:e,context:this.getConversationContext(),stream:!0})});if(!t.ok){n.remove();const e=await t.json().catch(()=>({error:"Request failed"}));return void this.addMessage("assistant",`Sorry, I encountered an error: ${e.error||"Request failed"}`)}n.remove();const o=document.createElement("div");o.className="librebot-message assistant",this.messagesContainer?.appendChild(o);const i=t.body?.getReader();if(!i)return void this.addMessage("assistant","Sorry, streaming is not supported.");const r=new TextDecoder;let a="";try{for(;;){const{done:e,value:n}=await i.read();if(e)break;const t=r.decode(n,{stream:!0}).split("\n").filter(e=>""!==e.trim());for(const e of t)if(e.startsWith("data: ")){const n=e.slice(6);if("[DONE]"===n)continue;try{const e=JSON.parse(n);e.content&&(a+=e.content,o.innerHTML=this.formatMessage(a),this.scrollToBottom())}catch{}}}}catch(e){console.error("Stream reading error:",e)}this.messages.push({id:`msg-${Date.now()}`,role:"assistant",content:a,timestamp:new Date})}async callAPI(e){const n=await fetch(`${this.config.apiUrl}/chat`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${this.config.apiKey}`},body:JSON.stringify({message:e,context:this.getConversationContext()})});if(!n.ok){return{response:"",error:(await n.json().catch(()=>({error:"Request failed"}))).error||"Request failed"}}return n.json()}getConversationContext(){return this.messages.slice(-10).map(e=>({role:e.role,content:e.content}))}destroy(){this.container?.remove(),document.getElementById("librebot-styles")?.remove()}}return function(){const e=document.currentScript||document.querySelector('script[data-key][src*="librebot"]');if(!e)return void console.warn("LibreBot: Could not find script tag");const n={apiKey:e.dataset.key||e.dataset.apiKey||"",apiUrl:e.dataset.apiUrl||"https://api.librebot.io",position:e.dataset.position||"bottom-right",theme:e.dataset.theme||"dark",primaryColor:e.dataset.color||"#14b8a6",title:e.dataset.title||"Libre Bot",subtitle:e.dataset.subtitle||"AI Documentation Assistant",placeholder:e.dataset.placeholder||"Ask a question...",welcomeMessage:e.dataset.welcome||"Hi! I can help you find answers in the documentation. What would you like to know?",streaming:"false"!==e.dataset.streaming};n.apiKey?"loading"===document.readyState?document.addEventListener("DOMContentLoaded",()=>{window.LibreBot=new t(n)}):window.LibreBot=new t(n):console.error("LibreBot: Missing data-key attribute")}(),e.LibreBotWidget=t,e}({});
2
2
  //# sourceMappingURL=librebot.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"librebot.js","sources":["../src/styles.ts","../src/icons.ts","../src/widget.ts","../src/embed.ts"],"sourcesContent":["export const getStyles = (primaryColor: string = '#14b8a6') => `\n .librebot-widget {\n --lb-primary: ${primaryColor};\n --lb-primary-hover: color-mix(in srgb, ${primaryColor} 85%, white);\n --lb-bg: #0f0f0f;\n --lb-bg-secondary: #1a1a1a;\n --lb-text: #ffffff;\n --lb-text-secondary: #9ca3af;\n --lb-border: #2a2a2a;\n font-family: 'Roboto Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .librebot-widget.light {\n --lb-bg: #ffffff;\n --lb-bg-secondary: #f5f5f5;\n --lb-text: #1a1a1a;\n --lb-text-secondary: #666666;\n --lb-border: #e0e0e0;\n }\n\n .librebot-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--lb-primary);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n z-index: 999998;\n }\n\n .librebot-fab:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n }\n\n .librebot-fab svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-fab.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-modal {\n position: fixed;\n bottom: 90px;\n right: 20px;\n width: 380px;\n max-width: calc(100vw - 40px);\n height: 520px;\n max-height: calc(100vh - 120px);\n background: var(--lb-bg);\n border: 1px solid var(--lb-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 999999;\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n }\n\n .librebot-modal.open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .librebot-modal.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-header {\n padding: 16px;\n border-bottom: 1px solid var(--lb-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .librebot-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .librebot-avatar {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: var(--lb-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-avatar svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-title {\n font-weight: 600;\n color: var(--lb-text);\n margin: 0;\n font-size: 16px;\n }\n\n .librebot-subtitle {\n font-size: 12px;\n color: var(--lb-text-secondary);\n margin: 0;\n }\n\n .librebot-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--lb-text-secondary);\n transition: background 0.2s;\n }\n\n .librebot-close:hover {\n background: var(--lb-bg-secondary);\n }\n\n .librebot-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .librebot-message {\n max-width: 85%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .librebot-message.user {\n align-self: flex-end;\n background: var(--lb-primary);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .librebot-message.assistant {\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n border-bottom-left-radius: 4px;\n }\n\n /* Inline code */\n .librebot-inline-code {\n background: rgba(0, 0, 0, 0.3);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n color: #f0f0f0;\n }\n\n .librebot-widget.light .librebot-inline-code {\n background: rgba(0, 0, 0, 0.08);\n color: #1a1a1a;\n }\n\n /* Code blocks */\n .librebot-code-block {\n background: #0d1117;\n padding: 12px 14px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 10px 0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n }\n\n .librebot-widget.light .librebot-code-block {\n background: #f6f8fa;\n border-color: rgba(0, 0, 0, 0.1);\n }\n\n .librebot-code-block code {\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #e6edf3;\n background: none;\n padding: 0;\n white-space: pre;\n display: block;\n }\n\n .librebot-widget.light .librebot-code-block code {\n color: #24292f;\n }\n\n .librebot-code-block[data-language]::before {\n content: attr(data-language);\n position: absolute;\n top: 6px;\n right: 10px;\n font-size: 10px;\n color: rgba(255, 255, 255, 0.4);\n text-transform: uppercase;\n font-family: 'Roboto Mono', monospace;\n }\n\n .librebot-widget.light .librebot-code-block[data-language]::before {\n color: rgba(0, 0, 0, 0.3);\n }\n\n /* Headers */\n .librebot-h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 12px 0 8px 0;\n color: var(--lb-text);\n }\n\n .librebot-h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 10px 0 6px 0;\n color: var(--lb-text);\n }\n\n .librebot-h4 {\n font-size: 13px;\n font-weight: 600;\n margin: 8px 0 4px 0;\n color: var(--lb-text);\n }\n\n /* Lists */\n .librebot-ul, .librebot-ol {\n margin: 8px 0;\n padding-left: 20px;\n }\n\n .librebot-ul {\n list-style-type: disc;\n }\n\n .librebot-ol {\n list-style-type: decimal;\n }\n\n .librebot-li, .librebot-li-ordered {\n margin: 4px 0;\n padding-left: 4px;\n line-height: 1.5;\n }\n\n /* Links */\n .librebot-link {\n color: var(--lb-primary);\n text-decoration: none;\n border-bottom: 1px solid transparent;\n transition: border-color 0.2s;\n }\n\n .librebot-link:hover {\n border-bottom-color: var(--lb-primary);\n }\n\n /* Blockquotes */\n .librebot-blockquote {\n border-left: 3px solid var(--lb-primary);\n margin: 8px 0;\n padding: 4px 12px;\n color: var(--lb-text-secondary);\n font-style: italic;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 0 6px 6px 0;\n }\n\n .librebot-widget.light .librebot-blockquote {\n background: rgba(0, 0, 0, 0.04);\n }\n\n /* Horizontal rule */\n .librebot-hr {\n border: none;\n border-top: 1px solid var(--lb-border);\n margin: 12px 0;\n }\n\n /* Strong and emphasis */\n .librebot-message strong {\n font-weight: 600;\n }\n\n .librebot-message em {\n font-style: italic;\n }\n\n /* Legacy support for old code elements */\n .librebot-message code:not(.librebot-inline-code) {\n background: rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 13px;\n }\n\n .librebot-message pre:not(.librebot-code-block) {\n background: rgba(0, 0, 0, 0.3);\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 8px 0;\n }\n\n .librebot-message pre:not(.librebot-code-block) code {\n background: none;\n padding: 0;\n }\n\n .librebot-typing {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .librebot-typing span {\n width: 8px;\n height: 8px;\n background: var(--lb-text-secondary);\n border-radius: 50%;\n animation: librebot-bounce 1.4s infinite ease-in-out;\n }\n\n .librebot-typing span:nth-child(1) { animation-delay: 0s; }\n .librebot-typing span:nth-child(2) { animation-delay: 0.2s; }\n .librebot-typing span:nth-child(3) { animation-delay: 0.4s; }\n\n @keyframes librebot-bounce {\n 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }\n 40% { transform: scale(1); opacity: 1; }\n }\n\n .librebot-input-area {\n padding: 12px 16px;\n border-top: 1px solid var(--lb-border);\n display: flex;\n gap: 8px;\n }\n\n .librebot-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--lb-border);\n border-radius: 24px;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .librebot-input:focus {\n border-color: var(--lb-primary);\n }\n\n .librebot-input::placeholder {\n color: var(--lb-text-secondary);\n }\n\n .librebot-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: var(--lb-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .librebot-send:hover {\n background: var(--lb-primary-hover);\n }\n\n .librebot-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .librebot-send svg {\n width: 18px;\n height: 18px;\n fill: white;\n }\n\n .librebot-welcome {\n text-align: center;\n padding: 20px;\n color: var(--lb-text-secondary);\n }\n\n .librebot-welcome-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n background: var(--lb-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-welcome-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .librebot-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--lb-text-secondary);\n border-top: 1px solid var(--lb-border);\n }\n\n .librebot-powered a {\n color: var(--lb-primary);\n text-decoration: none;\n }\n\n .librebot-powered a:hover {\n text-decoration: underline;\n }\n`;\n","export const chatIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path></svg>`;\n\nexport const closeIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg>`;\n\nexport const sendIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line><polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon></svg>`;\n\nexport const botIcon = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>`;\n","import { LibreBotConfig, Message, ChatResponse } from './types';\nimport { getStyles } from './styles';\nimport { chatIcon, closeIcon, sendIcon } from './icons';\n\nexport class LibreBotWidget {\n private config!: Required<LibreBotConfig>;\n private container: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private messagesContainer: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private isOpen = false;\n private messages: Message[] = [];\n private isLoading = false;\n\n private defaultConfig: Omit<Required<LibreBotConfig>, 'apiKey'> = {\n apiUrl: 'https://librebot.io/api',\n position: 'bottom-right',\n theme: 'dark',\n primaryColor: '#14b8a6',\n title: 'Libre Bot',\n subtitle: 'AI Documentation Assistant',\n placeholder: 'Ask a question...',\n welcomeMessage: 'Hi! I can help you find answers in the documentation. What would you like to know?',\n streaming: true,\n whiteLabel: false,\n autoLoadConfig: true,\n };\n\n constructor(config: LibreBotConfig) {\n if (!config.apiKey) {\n console.error('LibreBot: API key is required');\n return;\n }\n\n this.config = { ...this.defaultConfig, ...config } as Required<LibreBotConfig>;\n\n // Auto-load config from server if enabled and no custom settings provided\n if (this.config.autoLoadConfig) {\n this.loadRemoteConfig().then(() => this.init());\n } else {\n this.init();\n }\n }\n\n private async loadRemoteConfig(): Promise<void> {\n try {\n const response = await fetch(`${this.config.apiUrl}/widget-config?key=${this.config.apiKey}`);\n if (response.ok) {\n const remoteConfig = await response.json();\n // Merge remote config with local config (local overrides remote)\n this.config = {\n ...this.defaultConfig,\n ...remoteConfig,\n ...this.getProvidedConfig(),\n apiKey: this.config.apiKey,\n apiUrl: this.config.apiUrl,\n autoLoadConfig: this.config.autoLoadConfig,\n } as Required<LibreBotConfig>;\n }\n } catch (error) {\n console.warn('LibreBot: Could not load remote config, using defaults', error);\n }\n }\n\n private getProvidedConfig(): Partial<LibreBotConfig> {\n // Return only the config options that were explicitly provided (not default values)\n const provided: Partial<LibreBotConfig> = {};\n const userConfig = this.config;\n const defaults = this.defaultConfig;\n\n if (userConfig.position !== defaults.position) provided.position = userConfig.position;\n if (userConfig.theme !== defaults.theme) provided.theme = userConfig.theme;\n if (userConfig.primaryColor !== defaults.primaryColor) provided.primaryColor = userConfig.primaryColor;\n if (userConfig.title !== defaults.title) provided.title = userConfig.title;\n if (userConfig.subtitle !== defaults.subtitle) provided.subtitle = userConfig.subtitle;\n if (userConfig.placeholder !== defaults.placeholder) provided.placeholder = userConfig.placeholder;\n if (userConfig.welcomeMessage !== defaults.welcomeMessage) provided.welcomeMessage = userConfig.welcomeMessage;\n if (userConfig.streaming !== defaults.streaming) provided.streaming = userConfig.streaming;\n if (userConfig.whiteLabel !== defaults.whiteLabel) provided.whiteLabel = userConfig.whiteLabel;\n\n return provided;\n }\n\n private init(): void {\n // Inject styles\n this.injectStyles();\n\n // Create widget container\n this.createWidget();\n\n // Add welcome message\n if (this.config.welcomeMessage) {\n this.addMessage('assistant', this.config.welcomeMessage);\n }\n }\n\n private injectStyles(): void {\n const styleId = 'librebot-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = getStyles(this.config.primaryColor);\n document.head.appendChild(style);\n }\n\n private createWidget(): void {\n // Create container\n this.container = document.createElement('div');\n this.container.className = `librebot-widget ${this.config.theme === 'light' ? 'light' : ''}`;\n\n // Create FAB button\n const fab = document.createElement('button');\n fab.className = `librebot-fab ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n fab.innerHTML = chatIcon;\n fab.onclick = () => this.toggle();\n\n // Create modal\n this.modal = document.createElement('div');\n this.modal.className = `librebot-modal ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n this.modal.innerHTML = this.getModalHTML();\n\n // Add to container\n this.container.appendChild(fab);\n this.container.appendChild(this.modal);\n document.body.appendChild(this.container);\n\n // Get references\n this.messagesContainer = this.modal.querySelector('.librebot-messages');\n this.input = this.modal.querySelector('.librebot-input');\n\n // Add event listeners\n const closeBtn = this.modal.querySelector('.librebot-close');\n closeBtn?.addEventListener('click', () => this.close());\n\n const sendBtn = this.modal.querySelector('.librebot-send');\n sendBtn?.addEventListener('click', () => this.sendMessage());\n\n this.input?.addEventListener('keypress', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.sendMessage();\n }\n });\n\n // Auto theme detection\n if (this.config.theme === 'auto') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: light)');\n this.updateTheme(mediaQuery.matches);\n mediaQuery.addEventListener('change', (e) => this.updateTheme(e.matches));\n }\n }\n\n private getModalHTML(): string {\n const poweredByHtml = this.config.whiteLabel\n ? ''\n : `<div class=\"librebot-powered\">\n Powered by <a href=\"https://librebot.io\" target=\"_blank\">Libre Bot</a>\n </div>`;\n\n return `\n <div class=\"librebot-header\">\n <div class=\"librebot-header-content\">\n <div class=\"librebot-avatar\">${chatIcon}</div>\n <div>\n <h3 class=\"librebot-title\">${this.config.title}</h3>\n <p class=\"librebot-subtitle\">${this.config.subtitle}</p>\n </div>\n </div>\n <button class=\"librebot-close\">${closeIcon}</button>\n </div>\n <div class=\"librebot-messages\"></div>\n <div class=\"librebot-input-area\">\n <input type=\"text\" class=\"librebot-input\" placeholder=\"${this.config.placeholder}\" />\n <button class=\"librebot-send\">${sendIcon}</button>\n </div>\n ${poweredByHtml}\n `;\n }\n\n private updateTheme(isLight: boolean): void {\n if (isLight) {\n this.container?.classList.add('light');\n } else {\n this.container?.classList.remove('light');\n }\n }\n\n public toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n public open(): void {\n this.isOpen = true;\n this.modal?.classList.add('open');\n this.input?.focus();\n }\n\n public close(): void {\n this.isOpen = false;\n this.modal?.classList.remove('open');\n }\n\n private addMessage(role: 'user' | 'assistant', content: string): void {\n const message: Message = {\n id: `msg-${Date.now()}`,\n role,\n content,\n timestamp: new Date(),\n };\n\n this.messages.push(message);\n this.renderMessage(message);\n }\n\n private renderMessage(message: Message): void {\n if (!this.messagesContainer) return;\n\n const el = document.createElement('div');\n el.className = `librebot-message ${message.role}`;\n el.innerHTML = this.formatMessage(message.content);\n\n this.messagesContainer.appendChild(el);\n this.scrollToBottom();\n }\n\n private formatMessage(content: string): string {\n // Escape HTML to prevent XSS\n const escapeHtml = (text: string): string => {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n };\n\n // First, extract code blocks to protect them from other formatting\n const codeBlocks: string[] = [];\n let processed = content.replace(/```(\\w*)\\n?([\\s\\S]*?)```/g, (_, lang, code) => {\n const escaped = escapeHtml(code.trim());\n const langClass = lang ? ` data-language=\"${escapeHtml(lang)}\"` : '';\n codeBlocks.push(`<pre class=\"librebot-code-block\"${langClass}><code>${escaped}</code></pre>`);\n return `%%CODEBLOCK${codeBlocks.length - 1}%%`;\n });\n\n // Extract inline code\n const inlineCodes: string[] = [];\n processed = processed.replace(/`([^`]+)`/g, (_, code) => {\n inlineCodes.push(`<code class=\"librebot-inline-code\">${escapeHtml(code)}</code>`);\n return `%%INLINECODE${inlineCodes.length - 1}%%`;\n });\n\n // Now escape remaining HTML\n processed = escapeHtml(processed);\n\n // Headers (## and ###)\n processed = processed.replace(/^### (.+)$/gm, '<h4 class=\"librebot-h4\">$1</h4>');\n processed = processed.replace(/^## (.+)$/gm, '<h3 class=\"librebot-h3\">$1</h3>');\n processed = processed.replace(/^# (.+)$/gm, '<h2 class=\"librebot-h2\">$1</h2>');\n\n // Bold and italic\n processed = processed.replace(/\\*\\*\\*([^*]+)\\*\\*\\*/g, '<strong><em>$1</em></strong>');\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n processed = processed.replace(/_([^_]+)_/g, '<em>$1</em>');\n\n // Links [text](url)\n processed = processed.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"librebot-link\">$1</a>');\n\n // Unordered lists\n processed = processed.replace(/^[\\*\\-] (.+)$/gm, '<li class=\"librebot-li\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ul class=\"librebot-ul\">${match}</ul>`;\n });\n\n // Ordered lists\n processed = processed.replace(/^\\d+\\. (.+)$/gm, '<li class=\"librebot-li-ordered\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li-ordered\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ol class=\"librebot-ol\">${match}</ol>`;\n });\n\n // Horizontal rule\n processed = processed.replace(/^---$/gm, '<hr class=\"librebot-hr\">');\n\n // Blockquotes\n processed = processed.replace(/^&gt; (.+)$/gm, '<blockquote class=\"librebot-blockquote\">$1</blockquote>');\n\n // Convert newlines to <br> (but not inside lists/blockquotes)\n processed = processed.replace(/\\n/g, '<br>');\n\n // Clean up extra <br> after block elements\n processed = processed.replace(/<\\/(pre|ul|ol|blockquote|h[2-4])><br>/g, '</$1>');\n processed = processed.replace(/<br><(pre|ul|ol|blockquote|h[2-4])/g, '<$1');\n\n // Restore code blocks\n codeBlocks.forEach((block, i) => {\n processed = processed.replace(`%%CODEBLOCK${i}%%`, block);\n });\n\n // Restore inline code\n inlineCodes.forEach((code, i) => {\n processed = processed.replace(`%%INLINECODE${i}%%`, code);\n });\n\n return processed;\n }\n\n private showTyping(): HTMLDivElement {\n const typing = document.createElement('div');\n typing.className = 'librebot-typing';\n typing.innerHTML = '<span></span><span></span><span></span>';\n this.messagesContainer?.appendChild(typing);\n this.scrollToBottom();\n return typing;\n }\n\n private scrollToBottom(): void {\n if (this.messagesContainer) {\n this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;\n }\n }\n\n private async sendMessage(): Promise<void> {\n if (!this.input || this.isLoading) return;\n\n const content = this.input.value.trim();\n if (!content) return;\n\n // Add user message\n this.addMessage('user', content);\n this.input.value = '';\n\n // Show typing indicator\n this.isLoading = true;\n const typing = this.showTyping();\n\n try {\n if (this.config.streaming) {\n await this.callStreamingAPI(content, typing);\n } else {\n const response = await this.callAPI(content);\n typing.remove();\n\n if (response.error) {\n this.addMessage('assistant', `Sorry, I encountered an error: ${response.error}`);\n } else {\n this.addMessage('assistant', response.response);\n }\n }\n } catch (error) {\n typing.remove();\n this.addMessage('assistant', 'Sorry, I had trouble connecting. Please try again.');\n console.error('LibreBot error:', error);\n } finally {\n this.isLoading = false;\n }\n }\n\n private async callStreamingAPI(message: string, typing: HTMLDivElement): Promise<void> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n stream: true,\n }),\n });\n\n if (!response.ok) {\n typing.remove();\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n this.addMessage('assistant', `Sorry, I encountered an error: ${error.error || 'Request failed'}`);\n return;\n }\n\n // Remove typing indicator and create streaming message element\n typing.remove();\n const messageEl = document.createElement('div');\n messageEl.className = 'librebot-message assistant';\n this.messagesContainer?.appendChild(messageEl);\n\n const reader = response.body?.getReader();\n if (!reader) {\n this.addMessage('assistant', 'Sorry, streaming is not supported.');\n return;\n }\n\n const decoder = new TextDecoder();\n let fullContent = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n const lines = chunk.split('\\n').filter((line) => line.trim() !== '');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) {\n fullContent += parsed.content;\n messageEl.innerHTML = this.formatMessage(fullContent);\n this.scrollToBottom();\n }\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n } catch (error) {\n console.error('Stream reading error:', error);\n }\n\n // Add to messages array\n this.messages.push({\n id: `msg-${Date.now()}`,\n role: 'assistant',\n content: fullContent,\n timestamp: new Date(),\n });\n }\n\n private async callAPI(message: string): Promise<ChatResponse> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n return { response: '', error: error.error || 'Request failed' };\n }\n\n return response.json();\n }\n\n private getConversationContext(): Array<{ role: string; content: string }> {\n // Get last 10 messages for context\n return this.messages.slice(-10).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n }\n\n public destroy(): void {\n this.container?.remove();\n document.getElementById('librebot-styles')?.remove();\n }\n}\n","import { LibreBotWidget } from './widget';\nimport { LibreBotConfig } from './types';\n\n// Auto-initialize from script tag\n(function () {\n // Find the script tag - document.currentScript may be null with defer\n const script = document.currentScript as HTMLScriptElement\n || document.querySelector('script[data-key][src*=\"librebot\"]') as HTMLScriptElement;\n\n if (!script) {\n console.warn('LibreBot: Could not find script tag');\n return;\n }\n\n // Get config from data attributes\n const config: LibreBotConfig = {\n apiKey: script.dataset.key || script.dataset.apiKey || '',\n apiUrl: script.dataset.apiUrl || 'https://api.librebot.io',\n position: (script.dataset.position as 'bottom-right' | 'bottom-left') || 'bottom-right',\n theme: (script.dataset.theme as 'light' | 'dark' | 'auto') || 'dark',\n primaryColor: script.dataset.color || '#14b8a6',\n title: script.dataset.title || 'Libre Bot',\n subtitle: script.dataset.subtitle || 'AI Documentation Assistant',\n placeholder: script.dataset.placeholder || 'Ask a question...',\n welcomeMessage: script.dataset.welcome || 'Hi! I can help you find answers in the documentation. What would you like to know?',\n streaming: script.dataset.streaming !== 'false', // default true\n };\n\n if (!config.apiKey) {\n console.error('LibreBot: Missing data-key attribute');\n return;\n }\n\n // Initialize when DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n (window as any).LibreBot = new LibreBotWidget(config);\n });\n } else {\n (window as any).LibreBot = new LibreBotWidget(config);\n }\n})();\n\n// Export for manual initialization\nexport { LibreBotWidget, LibreBotConfig };\n"],"names":["chatIcon","LibreBotWidget","constructor","config","this","container","modal","messagesContainer","input","isOpen","messages","isLoading","defaultConfig","apiUrl","position","theme","primaryColor","title","subtitle","placeholder","welcomeMessage","streaming","whiteLabel","autoLoadConfig","apiKey","loadRemoteConfig","then","init","console","error","response","fetch","ok","remoteConfig","json","getProvidedConfig","warn","provided","userConfig","defaults","injectStyles","createWidget","addMessage","styleId","document","getElementById","style","createElement","id","textContent","getStyles","head","appendChild","className","fab","innerHTML","onclick","toggle","getModalHTML","body","querySelector","closeBtn","addEventListener","close","sendBtn","sendMessage","e","key","shiftKey","preventDefault","mediaQuery","window","matchMedia","updateTheme","matches","poweredByHtml","isLight","classList","add","remove","open","focus","role","content","message","Date","now","timestamp","push","renderMessage","el","formatMessage","scrollToBottom","escapeHtml","text","replace","codeBlocks","processed","_","lang","code","escaped","trim","langClass","length","inlineCodes","match","forEach","block","i","showTyping","typing","scrollTop","scrollHeight","value","callStreamingAPI","callAPI","method","headers","Authorization","JSON","stringify","context","getConversationContext","stream","catch","messageEl","reader","getReader","decoder","TextDecoder","fullContent","done","read","lines","decode","split","filter","line","startsWith","data","slice","parsed","parse","map","m","destroy","script","currentScript","dataset","color","welcome","readyState","LibreBot"],"mappings":"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"}
1
+ {"version":3,"file":"librebot.js","sources":["../src/styles.ts","../src/icons.ts","../src/widget.ts","../src/embed.ts"],"sourcesContent":["export const getStyles = (primaryColor: string = '#14b8a6') => `\n .librebot-widget {\n --lb-primary: ${primaryColor};\n --lb-primary-hover: color-mix(in srgb, ${primaryColor} 85%, white);\n --lb-bg: #0f0f0f;\n --lb-bg-secondary: #1a1a1a;\n --lb-text: #ffffff;\n --lb-text-secondary: #9ca3af;\n --lb-border: #2a2a2a;\n font-family: 'Roboto Mono', -apple-system, BlinkMacSystemFont, 'Segoe UI', monospace;\n font-size: 14px;\n line-height: 1.5;\n }\n\n .librebot-widget.light {\n --lb-bg: #ffffff;\n --lb-bg-secondary: #f5f5f5;\n --lb-text: #1a1a1a;\n --lb-text-secondary: #666666;\n --lb-border: #e0e0e0;\n }\n\n .librebot-fab {\n position: fixed;\n bottom: 20px;\n right: 20px;\n width: 56px;\n height: 56px;\n border-radius: 50%;\n background: var(--lb-primary);\n border: none;\n cursor: pointer;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s, box-shadow 0.2s;\n z-index: 999998;\n }\n\n .librebot-fab:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);\n }\n\n .librebot-fab svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-fab.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-modal {\n position: fixed;\n bottom: 90px;\n right: 20px;\n width: 380px;\n max-width: calc(100vw - 40px);\n height: 520px;\n max-height: calc(100vh - 120px);\n background: var(--lb-bg);\n border: 1px solid var(--lb-border);\n border-radius: 16px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n z-index: 999999;\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n transition: opacity 0.2s, transform 0.2s;\n pointer-events: none;\n }\n\n .librebot-modal.open {\n opacity: 1;\n transform: translateY(0) scale(1);\n pointer-events: auto;\n }\n\n .librebot-modal.left {\n right: auto;\n left: 20px;\n }\n\n .librebot-header {\n padding: 16px;\n border-bottom: 1px solid var(--lb-border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .librebot-header-content {\n display: flex;\n align-items: center;\n gap: 12px;\n }\n\n .librebot-avatar {\n width: 40px;\n height: 40px;\n border-radius: 10px;\n background: var(--lb-primary);\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-avatar svg {\n width: 24px;\n height: 24px;\n fill: white;\n }\n\n .librebot-title {\n font-weight: 600;\n color: var(--lb-text);\n margin: 0;\n font-size: 16px;\n }\n\n .librebot-subtitle {\n font-size: 12px;\n color: var(--lb-text-secondary);\n margin: 0;\n }\n\n .librebot-close {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n border: none;\n background: transparent;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--lb-text-secondary);\n transition: background 0.2s;\n }\n\n .librebot-close:hover {\n background: var(--lb-bg-secondary);\n }\n\n .librebot-messages {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n\n .librebot-message {\n max-width: 85%;\n padding: 10px 14px;\n border-radius: 16px;\n word-wrap: break-word;\n }\n\n .librebot-message.user {\n align-self: flex-end;\n background: var(--lb-primary);\n color: white;\n border-bottom-right-radius: 4px;\n }\n\n .librebot-message.assistant {\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n border-bottom-left-radius: 4px;\n }\n\n /* Inline code */\n .librebot-inline-code {\n background: rgba(0, 0, 0, 0.3);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n color: #f0f0f0;\n }\n\n .librebot-widget.light .librebot-inline-code {\n background: rgba(0, 0, 0, 0.08);\n color: #1a1a1a;\n }\n\n /* Code blocks */\n .librebot-code-block {\n background: #0d1117;\n padding: 12px 14px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 10px 0;\n border: 1px solid rgba(255, 255, 255, 0.1);\n position: relative;\n }\n\n .librebot-widget.light .librebot-code-block {\n background: #f6f8fa;\n border-color: rgba(0, 0, 0, 0.1);\n }\n\n .librebot-code-block code {\n font-family: 'Roboto Mono', 'Fira Code', 'Consolas', monospace;\n font-size: 12px;\n line-height: 1.5;\n color: #e6edf3;\n background: none;\n padding: 0;\n white-space: pre;\n display: block;\n }\n\n .librebot-widget.light .librebot-code-block code {\n color: #24292f;\n }\n\n .librebot-code-block[data-language]::before {\n content: attr(data-language);\n position: absolute;\n top: 6px;\n right: 10px;\n font-size: 10px;\n color: rgba(255, 255, 255, 0.4);\n text-transform: uppercase;\n font-family: 'Roboto Mono', monospace;\n }\n\n .librebot-widget.light .librebot-code-block[data-language]::before {\n color: rgba(0, 0, 0, 0.3);\n }\n\n /* Headers */\n .librebot-h2 {\n font-size: 16px;\n font-weight: 600;\n margin: 12px 0 8px 0;\n color: var(--lb-text);\n }\n\n .librebot-h3 {\n font-size: 14px;\n font-weight: 600;\n margin: 10px 0 6px 0;\n color: var(--lb-text);\n }\n\n .librebot-h4 {\n font-size: 13px;\n font-weight: 600;\n margin: 8px 0 4px 0;\n color: var(--lb-text);\n }\n\n /* Lists */\n .librebot-ul, .librebot-ol {\n margin: 8px 0;\n padding-left: 20px;\n }\n\n .librebot-ul {\n list-style-type: disc;\n }\n\n .librebot-ol {\n list-style-type: decimal;\n }\n\n .librebot-li, .librebot-li-ordered {\n margin: 4px 0;\n padding-left: 4px;\n line-height: 1.5;\n }\n\n /* Links */\n .librebot-link {\n color: var(--lb-primary);\n text-decoration: none;\n border-bottom: 1px solid transparent;\n transition: border-color 0.2s;\n }\n\n .librebot-link:hover {\n border-bottom-color: var(--lb-primary);\n }\n\n /* Blockquotes */\n .librebot-blockquote {\n border-left: 3px solid var(--lb-primary);\n margin: 8px 0;\n padding: 4px 12px;\n color: var(--lb-text-secondary);\n font-style: italic;\n background: rgba(0, 0, 0, 0.1);\n border-radius: 0 6px 6px 0;\n }\n\n .librebot-widget.light .librebot-blockquote {\n background: rgba(0, 0, 0, 0.04);\n }\n\n /* Horizontal rule */\n .librebot-hr {\n border: none;\n border-top: 1px solid var(--lb-border);\n margin: 12px 0;\n }\n\n /* Strong and emphasis */\n .librebot-message strong {\n font-weight: 600;\n }\n\n .librebot-message em {\n font-style: italic;\n }\n\n /* Legacy support for old code elements */\n .librebot-message code:not(.librebot-inline-code) {\n background: rgba(0, 0, 0, 0.2);\n padding: 2px 6px;\n border-radius: 4px;\n font-family: monospace;\n font-size: 13px;\n }\n\n .librebot-message pre:not(.librebot-code-block) {\n background: rgba(0, 0, 0, 0.3);\n padding: 10px;\n border-radius: 8px;\n overflow-x: auto;\n margin: 8px 0;\n }\n\n .librebot-message pre:not(.librebot-code-block) code {\n background: none;\n padding: 0;\n }\n\n .librebot-typing {\n display: flex;\n gap: 4px;\n padding: 12px 16px;\n align-self: flex-start;\n background: var(--lb-bg-secondary);\n border-radius: 16px;\n border-bottom-left-radius: 4px;\n }\n\n .librebot-typing span {\n width: 8px;\n height: 8px;\n background: var(--lb-text-secondary);\n border-radius: 50%;\n animation: librebot-bounce 1.4s infinite ease-in-out;\n }\n\n .librebot-typing span:nth-child(1) { animation-delay: 0s; }\n .librebot-typing span:nth-child(2) { animation-delay: 0.2s; }\n .librebot-typing span:nth-child(3) { animation-delay: 0.4s; }\n\n @keyframes librebot-bounce {\n 0%, 80%, 100% { transform: scale(0.8); opacity: 0.5; }\n 40% { transform: scale(1); opacity: 1; }\n }\n\n .librebot-input-area {\n padding: 12px 16px;\n border-top: 1px solid var(--lb-border);\n display: flex;\n gap: 8px;\n }\n\n .librebot-input {\n flex: 1;\n padding: 10px 14px;\n border: 1px solid var(--lb-border);\n border-radius: 24px;\n background: var(--lb-bg-secondary);\n color: var(--lb-text);\n font-size: 14px;\n outline: none;\n transition: border-color 0.2s;\n }\n\n .librebot-input:focus {\n border-color: var(--lb-primary);\n }\n\n .librebot-input::placeholder {\n color: var(--lb-text-secondary);\n }\n\n .librebot-send {\n width: 40px;\n height: 40px;\n border-radius: 50%;\n border: none;\n background: var(--lb-primary);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .librebot-send:hover {\n background: var(--lb-primary-hover);\n }\n\n .librebot-send:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .librebot-send svg {\n width: 18px;\n height: 18px;\n fill: white;\n }\n\n .librebot-welcome {\n text-align: center;\n padding: 20px;\n color: var(--lb-text-secondary);\n }\n\n .librebot-welcome-icon {\n width: 48px;\n height: 48px;\n margin: 0 auto 12px;\n background: var(--lb-primary);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .librebot-welcome-icon svg {\n width: 28px;\n height: 28px;\n fill: white;\n }\n\n .librebot-powered {\n text-align: center;\n padding: 8px;\n font-size: 11px;\n color: var(--lb-text-secondary);\n border-top: 1px solid var(--lb-border);\n }\n\n .librebot-powered a {\n color: var(--lb-primary);\n text-decoration: none;\n }\n\n .librebot-powered a:hover {\n text-decoration: underline;\n }\n`;\n","export const chatIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"></path></svg>`;\n\nexport const closeIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line></svg>`;\n\nexport const sendIcon = `<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line><polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon></svg>`;\n\nexport const botIcon = `<svg viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z\"/></svg>`;\n","import { LibreBotConfig, Message, ChatResponse } from './types';\nimport { getStyles } from './styles';\nimport { chatIcon, closeIcon, sendIcon } from './icons';\n\nexport class LibreBotWidget {\n private config!: Required<LibreBotConfig>;\n private container: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private messagesContainer: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private isOpen = false;\n private messages: Message[] = [];\n private isLoading = false;\n\n private defaultConfig: Omit<Required<LibreBotConfig>, 'apiKey'> = {\n apiUrl: 'https://librebot.io/api',\n position: 'bottom-right',\n theme: 'dark',\n primaryColor: '#14b8a6',\n title: 'Libre Bot',\n subtitle: 'AI Documentation Assistant',\n placeholder: 'Ask a question...',\n welcomeMessage: 'Hi! I can help you find answers in the documentation. What would you like to know?',\n streaming: true,\n whiteLabel: false,\n autoLoadConfig: true,\n };\n\n constructor(config: LibreBotConfig) {\n if (!config.apiKey) {\n console.error('LibreBot: API key is required');\n return;\n }\n\n this.config = { ...this.defaultConfig, ...config } as Required<LibreBotConfig>;\n\n // Auto-load config from server if enabled and no custom settings provided\n if (this.config.autoLoadConfig) {\n this.loadRemoteConfig().then(() => this.init());\n } else {\n this.init();\n }\n }\n\n private async loadRemoteConfig(): Promise<void> {\n try {\n const response = await fetch(`${this.config.apiUrl}/widget-config?key=${this.config.apiKey}`);\n if (response.ok) {\n const remoteConfig = await response.json();\n // Merge remote config with local config (local overrides remote)\n this.config = {\n ...this.defaultConfig,\n ...remoteConfig,\n ...this.getProvidedConfig(),\n apiKey: this.config.apiKey,\n apiUrl: this.config.apiUrl,\n autoLoadConfig: this.config.autoLoadConfig,\n } as Required<LibreBotConfig>;\n }\n } catch (error) {\n console.warn('LibreBot: Could not load remote config, using defaults', error);\n }\n }\n\n private getProvidedConfig(): Partial<LibreBotConfig> {\n // Return only the config options that were explicitly provided (not default values)\n const provided: Partial<LibreBotConfig> = {};\n const userConfig = this.config;\n const defaults = this.defaultConfig;\n\n if (userConfig.position !== defaults.position) provided.position = userConfig.position;\n if (userConfig.theme !== defaults.theme) provided.theme = userConfig.theme;\n if (userConfig.primaryColor !== defaults.primaryColor) provided.primaryColor = userConfig.primaryColor;\n if (userConfig.title !== defaults.title) provided.title = userConfig.title;\n if (userConfig.subtitle !== defaults.subtitle) provided.subtitle = userConfig.subtitle;\n if (userConfig.placeholder !== defaults.placeholder) provided.placeholder = userConfig.placeholder;\n if (userConfig.welcomeMessage !== defaults.welcomeMessage) provided.welcomeMessage = userConfig.welcomeMessage;\n if (userConfig.streaming !== defaults.streaming) provided.streaming = userConfig.streaming;\n if (userConfig.whiteLabel !== defaults.whiteLabel) provided.whiteLabel = userConfig.whiteLabel;\n\n return provided;\n }\n\n private init(): void {\n // Inject styles\n this.injectStyles();\n\n // Create widget container\n this.createWidget();\n\n // Add welcome message\n if (this.config.welcomeMessage) {\n this.addMessage('assistant', this.config.welcomeMessage);\n }\n }\n\n private injectStyles(): void {\n const styleId = 'librebot-styles';\n if (document.getElementById(styleId)) return;\n\n const style = document.createElement('style');\n style.id = styleId;\n style.textContent = getStyles(this.config.primaryColor);\n document.head.appendChild(style);\n }\n\n private createWidget(): void {\n // Create container\n this.container = document.createElement('div');\n this.container.className = `librebot-widget ${this.config.theme === 'light' ? 'light' : ''}`;\n\n // Create FAB button\n const fab = document.createElement('button');\n fab.className = `librebot-fab ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n fab.innerHTML = chatIcon;\n fab.onclick = () => this.toggle();\n\n // Create modal\n this.modal = document.createElement('div');\n this.modal.className = `librebot-modal ${this.config.position === 'bottom-left' ? 'left' : ''}`;\n this.modal.innerHTML = this.getModalHTML();\n\n // Add to container\n this.container.appendChild(fab);\n this.container.appendChild(this.modal);\n document.body.appendChild(this.container);\n\n // Get references\n this.messagesContainer = this.modal.querySelector('.librebot-messages');\n this.input = this.modal.querySelector('.librebot-input');\n\n // Add event listeners\n const closeBtn = this.modal.querySelector('.librebot-close');\n closeBtn?.addEventListener('click', () => this.close());\n\n const sendBtn = this.modal.querySelector('.librebot-send');\n sendBtn?.addEventListener('click', () => this.sendMessage());\n\n this.input?.addEventListener('keypress', (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n this.sendMessage();\n }\n });\n\n // Auto theme detection\n if (this.config.theme === 'auto') {\n const mediaQuery = window.matchMedia('(prefers-color-scheme: light)');\n this.updateTheme(mediaQuery.matches);\n mediaQuery.addEventListener('change', (e) => this.updateTheme(e.matches));\n }\n }\n\n private getModalHTML(): string {\n const poweredByHtml = this.config.whiteLabel\n ? ''\n : `<div class=\"librebot-powered\">\n Powered by <a href=\"https://librebot.io\" target=\"_blank\">Libre Bot</a>\n </div>`;\n\n return `\n <div class=\"librebot-header\">\n <div class=\"librebot-header-content\">\n <div class=\"librebot-avatar\">${chatIcon}</div>\n <div>\n <h3 class=\"librebot-title\">${this.config.title}</h3>\n <p class=\"librebot-subtitle\">${this.config.subtitle}</p>\n </div>\n </div>\n <button class=\"librebot-close\">${closeIcon}</button>\n </div>\n <div class=\"librebot-messages\"></div>\n <div class=\"librebot-input-area\">\n <input type=\"text\" class=\"librebot-input\" placeholder=\"${this.config.placeholder}\" />\n <button class=\"librebot-send\">${sendIcon}</button>\n </div>\n ${poweredByHtml}\n `;\n }\n\n private updateTheme(isLight: boolean): void {\n if (isLight) {\n this.container?.classList.add('light');\n } else {\n this.container?.classList.remove('light');\n }\n }\n\n public toggle(): void {\n this.isOpen ? this.close() : this.open();\n }\n\n public open(): void {\n this.isOpen = true;\n this.modal?.classList.add('open');\n this.input?.focus();\n }\n\n public close(): void {\n this.isOpen = false;\n this.modal?.classList.remove('open');\n }\n\n private addMessage(role: 'user' | 'assistant', content: string): void {\n const message: Message = {\n id: `msg-${Date.now()}`,\n role,\n content,\n timestamp: new Date(),\n };\n\n this.messages.push(message);\n this.renderMessage(message);\n }\n\n private renderMessage(message: Message): void {\n if (!this.messagesContainer) return;\n\n const el = document.createElement('div');\n el.className = `librebot-message ${message.role}`;\n el.innerHTML = this.formatMessage(message.content);\n\n this.messagesContainer.appendChild(el);\n this.scrollToBottom();\n }\n\n private formatMessage(content: string): string {\n // Escape HTML to prevent XSS\n const escapeHtml = (text: string): string => {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n };\n\n // First, extract code blocks to protect them from other formatting\n // Regex handles optional space/newline after ``` and optional language identifier\n const codeBlocks: string[] = [];\n let processed = content.replace(/```\\s*(\\w*)\\s*\\n?([\\s\\S]*?)```/g, (_, lang, code) => {\n const escaped = escapeHtml(code.trim());\n const langClass = lang ? ` data-language=\"${escapeHtml(lang)}\"` : '';\n codeBlocks.push(`<pre class=\"librebot-code-block\"${langClass}><code>${escaped}</code></pre>`);\n return `%%CODEBLOCK${codeBlocks.length - 1}%%`;\n });\n\n // Extract inline code\n const inlineCodes: string[] = [];\n processed = processed.replace(/`([^`]+)`/g, (_, code) => {\n inlineCodes.push(`<code class=\"librebot-inline-code\">${escapeHtml(code)}</code>`);\n return `%%INLINECODE${inlineCodes.length - 1}%%`;\n });\n\n // Now escape remaining HTML\n processed = escapeHtml(processed);\n\n // Headers (## and ###)\n processed = processed.replace(/^### (.+)$/gm, '<h4 class=\"librebot-h4\">$1</h4>');\n processed = processed.replace(/^## (.+)$/gm, '<h3 class=\"librebot-h3\">$1</h3>');\n processed = processed.replace(/^# (.+)$/gm, '<h2 class=\"librebot-h2\">$1</h2>');\n\n // Bold and italic\n processed = processed.replace(/\\*\\*\\*([^*]+)\\*\\*\\*/g, '<strong><em>$1</em></strong>');\n processed = processed.replace(/\\*\\*([^*]+)\\*\\*/g, '<strong>$1</strong>');\n processed = processed.replace(/\\*([^*]+)\\*/g, '<em>$1</em>');\n processed = processed.replace(/_([^_]+)_/g, '<em>$1</em>');\n\n // Links [text](url)\n processed = processed.replace(/\\[([^\\]]+)\\]\\(([^)]+)\\)/g, '<a href=\"$2\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"librebot-link\">$1</a>');\n\n // Unordered lists\n processed = processed.replace(/^[\\*\\-] (.+)$/gm, '<li class=\"librebot-li\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ul class=\"librebot-ul\">${match}</ul>`;\n });\n\n // Ordered lists\n processed = processed.replace(/^\\d+\\. (.+)$/gm, '<li class=\"librebot-li-ordered\">$1</li>');\n processed = processed.replace(/(<li class=\"librebot-li-ordered\">.*<\\/li>\\n?)+/g, (match) => {\n return `<ol class=\"librebot-ol\">${match}</ol>`;\n });\n\n // Horizontal rule\n processed = processed.replace(/^---$/gm, '<hr class=\"librebot-hr\">');\n\n // Blockquotes\n processed = processed.replace(/^&gt; (.+)$/gm, '<blockquote class=\"librebot-blockquote\">$1</blockquote>');\n\n // Convert newlines to <br> (but not inside lists/blockquotes)\n processed = processed.replace(/\\n/g, '<br>');\n\n // Clean up extra <br> after block elements\n processed = processed.replace(/<\\/(pre|ul|ol|blockquote|h[2-4])><br>/g, '</$1>');\n processed = processed.replace(/<br><(pre|ul|ol|blockquote|h[2-4])/g, '<$1');\n\n // Restore code blocks\n codeBlocks.forEach((block, i) => {\n processed = processed.replace(`%%CODEBLOCK${i}%%`, block);\n });\n\n // Restore inline code\n inlineCodes.forEach((code, i) => {\n processed = processed.replace(`%%INLINECODE${i}%%`, code);\n });\n\n return processed;\n }\n\n private showTyping(): HTMLDivElement {\n const typing = document.createElement('div');\n typing.className = 'librebot-typing';\n typing.innerHTML = '<span></span><span></span><span></span>';\n this.messagesContainer?.appendChild(typing);\n this.scrollToBottom();\n return typing;\n }\n\n private scrollToBottom(): void {\n if (this.messagesContainer) {\n this.messagesContainer.scrollTop = this.messagesContainer.scrollHeight;\n }\n }\n\n private async sendMessage(): Promise<void> {\n if (!this.input || this.isLoading) return;\n\n const content = this.input.value.trim();\n if (!content) return;\n\n // Add user message\n this.addMessage('user', content);\n this.input.value = '';\n\n // Show typing indicator\n this.isLoading = true;\n const typing = this.showTyping();\n\n try {\n if (this.config.streaming) {\n await this.callStreamingAPI(content, typing);\n } else {\n const response = await this.callAPI(content);\n typing.remove();\n\n if (response.error) {\n this.addMessage('assistant', `Sorry, I encountered an error: ${response.error}`);\n } else {\n this.addMessage('assistant', response.response);\n }\n }\n } catch (error) {\n typing.remove();\n this.addMessage('assistant', 'Sorry, I had trouble connecting. Please try again.');\n console.error('LibreBot error:', error);\n } finally {\n this.isLoading = false;\n }\n }\n\n private async callStreamingAPI(message: string, typing: HTMLDivElement): Promise<void> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n stream: true,\n }),\n });\n\n if (!response.ok) {\n typing.remove();\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n this.addMessage('assistant', `Sorry, I encountered an error: ${error.error || 'Request failed'}`);\n return;\n }\n\n // Remove typing indicator and create streaming message element\n typing.remove();\n const messageEl = document.createElement('div');\n messageEl.className = 'librebot-message assistant';\n this.messagesContainer?.appendChild(messageEl);\n\n const reader = response.body?.getReader();\n if (!reader) {\n this.addMessage('assistant', 'Sorry, streaming is not supported.');\n return;\n }\n\n const decoder = new TextDecoder();\n let fullContent = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n const chunk = decoder.decode(value, { stream: true });\n const lines = chunk.split('\\n').filter((line) => line.trim() !== '');\n\n for (const line of lines) {\n if (line.startsWith('data: ')) {\n const data = line.slice(6);\n if (data === '[DONE]') continue;\n\n try {\n const parsed = JSON.parse(data);\n if (parsed.content) {\n fullContent += parsed.content;\n messageEl.innerHTML = this.formatMessage(fullContent);\n this.scrollToBottom();\n }\n } catch {\n // Skip malformed JSON\n }\n }\n }\n }\n } catch (error) {\n console.error('Stream reading error:', error);\n }\n\n // Add to messages array\n this.messages.push({\n id: `msg-${Date.now()}`,\n role: 'assistant',\n content: fullContent,\n timestamp: new Date(),\n });\n }\n\n private async callAPI(message: string): Promise<ChatResponse> {\n const response = await fetch(`${this.config.apiUrl}/chat`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${this.config.apiKey}`,\n },\n body: JSON.stringify({\n message,\n context: this.getConversationContext(),\n }),\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({ error: 'Request failed' }));\n return { response: '', error: error.error || 'Request failed' };\n }\n\n return response.json();\n }\n\n private getConversationContext(): Array<{ role: string; content: string }> {\n // Get last 10 messages for context\n return this.messages.slice(-10).map((m) => ({\n role: m.role,\n content: m.content,\n }));\n }\n\n public destroy(): void {\n this.container?.remove();\n document.getElementById('librebot-styles')?.remove();\n }\n}\n","import { LibreBotWidget } from './widget';\nimport { LibreBotConfig } from './types';\n\n// Auto-initialize from script tag\n(function () {\n // Find the script tag - document.currentScript may be null with defer\n const script = document.currentScript as HTMLScriptElement\n || document.querySelector('script[data-key][src*=\"librebot\"]') as HTMLScriptElement;\n\n if (!script) {\n console.warn('LibreBot: Could not find script tag');\n return;\n }\n\n // Get config from data attributes\n const config: LibreBotConfig = {\n apiKey: script.dataset.key || script.dataset.apiKey || '',\n apiUrl: script.dataset.apiUrl || 'https://api.librebot.io',\n position: (script.dataset.position as 'bottom-right' | 'bottom-left') || 'bottom-right',\n theme: (script.dataset.theme as 'light' | 'dark' | 'auto') || 'dark',\n primaryColor: script.dataset.color || '#14b8a6',\n title: script.dataset.title || 'Libre Bot',\n subtitle: script.dataset.subtitle || 'AI Documentation Assistant',\n placeholder: script.dataset.placeholder || 'Ask a question...',\n welcomeMessage: script.dataset.welcome || 'Hi! I can help you find answers in the documentation. What would you like to know?',\n streaming: script.dataset.streaming !== 'false', // default true\n };\n\n if (!config.apiKey) {\n console.error('LibreBot: Missing data-key attribute');\n return;\n }\n\n // Initialize when DOM is ready\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', () => {\n (window as any).LibreBot = new LibreBotWidget(config);\n });\n } else {\n (window as any).LibreBot = new LibreBotWidget(config);\n }\n})();\n\n// Export for manual initialization\nexport { LibreBotWidget, LibreBotConfig };\n"],"names":["chatIcon","LibreBotWidget","constructor","config","this","container","modal","messagesContainer","input","isOpen","messages","isLoading","defaultConfig","apiUrl","position","theme","primaryColor","title","subtitle","placeholder","welcomeMessage","streaming","whiteLabel","autoLoadConfig","apiKey","loadRemoteConfig","then","init","console","error","response","fetch","ok","remoteConfig","json","getProvidedConfig","warn","provided","userConfig","defaults","injectStyles","createWidget","addMessage","styleId","document","getElementById","style","createElement","id","textContent","getStyles","head","appendChild","className","fab","innerHTML","onclick","toggle","getModalHTML","body","querySelector","closeBtn","addEventListener","close","sendBtn","sendMessage","e","key","shiftKey","preventDefault","mediaQuery","window","matchMedia","updateTheme","matches","poweredByHtml","isLight","classList","add","remove","open","focus","role","content","message","Date","now","timestamp","push","renderMessage","el","formatMessage","scrollToBottom","escapeHtml","text","replace","codeBlocks","processed","_","lang","code","escaped","trim","langClass","length","inlineCodes","match","forEach","block","i","showTyping","typing","scrollTop","scrollHeight","value","callStreamingAPI","callAPI","method","headers","Authorization","JSON","stringify","context","getConversationContext","stream","catch","messageEl","reader","getReader","decoder","TextDecoder","fullContent","done","read","lines","decode","split","filter","line","startsWith","data","slice","parsed","parse","map","m","destroy","script","currentScript","dataset","color","welcome","readyState","LibreBot"],"mappings":"sCAAO,MCAMA,EAAW,yNCIXC,EAwBX,WAAAC,CAAYC,GAtBJC,KAAAC,UAAmC,KACnCD,KAAAE,MAA+B,KAC/BF,KAAAG,kBAA2C,KAC3CH,KAAAI,MAAiC,KACjCJ,KAAAK,QAAS,EACTL,KAAAM,SAAsB,GACtBN,KAAAO,WAAY,EAEZP,KAAAQ,cAA0D,CAChEC,OAAQ,0BACRC,SAAU,eACVC,MAAO,OACPC,aAAc,UACdC,MAAO,YACPC,SAAU,6BACVC,YAAa,oBACbC,eAAgB,qFAChBC,WAAW,EACXC,YAAY,EACZC,gBAAgB,GAIXpB,EAAOqB,QAKZpB,KAAKD,OAAS,IAAKC,KAAKQ,iBAAkBT,GAGtCC,KAAKD,OAAOoB,eACdnB,KAAKqB,mBAAmBC,KAAK,IAAMtB,KAAKuB,QAExCvB,KAAKuB,QAVLC,QAAQC,MAAM,gCAYlB,CAEQ,sBAAMJ,GACZ,IACE,MAAMK,QAAiBC,MAAM,GAAG3B,KAAKD,OAAOU,4BAA4BT,KAAKD,OAAOqB,UACpF,GAAIM,EAASE,GAAI,CACf,MAAMC,QAAqBH,EAASI,OAEpC9B,KAAKD,OAAS,IACTC,KAAKQ,iBACLqB,KACA7B,KAAK+B,oBACRX,OAAQpB,KAAKD,OAAOqB,OACpBX,OAAQT,KAAKD,OAAOU,OACpBU,eAAgBnB,KAAKD,OAAOoB,eAEhC,CACF,CAAE,MAAOM,GACPD,QAAQQ,KAAK,yDAA0DP,EACzE,CACF,CAEQ,iBAAAM,GAEN,MAAME,EAAoC,CAAA,EACpCC,EAAalC,KAAKD,OAClBoC,EAAWnC,KAAKQ,cAYtB,OAVI0B,EAAWxB,WAAayB,EAASzB,WAAUuB,EAASvB,SAAWwB,EAAWxB,UAC1EwB,EAAWvB,QAAUwB,EAASxB,QAAOsB,EAAStB,MAAQuB,EAAWvB,OACjEuB,EAAWtB,eAAiBuB,EAASvB,eAAcqB,EAASrB,aAAesB,EAAWtB,cACtFsB,EAAWrB,QAAUsB,EAAStB,QAAOoB,EAASpB,MAAQqB,EAAWrB,OACjEqB,EAAWpB,WAAaqB,EAASrB,WAAUmB,EAASnB,SAAWoB,EAAWpB,UAC1EoB,EAAWnB,cAAgBoB,EAASpB,cAAakB,EAASlB,YAAcmB,EAAWnB,aACnFmB,EAAWlB,iBAAmBmB,EAASnB,iBAAgBiB,EAASjB,eAAiBkB,EAAWlB,gBAC5FkB,EAAWjB,YAAckB,EAASlB,YAAWgB,EAAShB,UAAYiB,EAAWjB,WAC7EiB,EAAWhB,aAAeiB,EAASjB,aAAYe,EAASf,WAAagB,EAAWhB,YAE7Ee,CACT,CAEQ,IAAAV,GAENvB,KAAKoC,eAGLpC,KAAKqC,eAGDrC,KAAKD,OAAOiB,gBACdhB,KAAKsC,WAAW,YAAatC,KAAKD,OAAOiB,eAE7C,CAEQ,YAAAoB,GACN,MAAMG,EAAU,kBAChB,GAAIC,SAASC,eAAeF,GAAU,OAEtC,MAAMG,EAAQF,SAASG,cAAc,SACrCD,EAAME,GAAKL,EACXG,EAAMG,YFtGe,EAACjC,EAAuB,YAAc,6CAE3CA,kDACyBA,wvTEmGrBkC,CAAU9C,KAAKD,OAAOa,cAC1C4B,SAASO,KAAKC,YAAYN,EAC5B,CAEQ,YAAAL,GAENrC,KAAKC,UAAYuC,SAASG,cAAc,OACxC3C,KAAKC,UAAUgD,UAAY,oBAAyC,UAAtBjD,KAAKD,OAAOY,MAAoB,QAAU,IAGxF,MAAMuC,EAAMV,SAASG,cAAc,UACnCO,EAAID,UAAY,iBAAyC,gBAAzBjD,KAAKD,OAAOW,SAA6B,OAAS,IAClFwC,EAAIC,UAAYvD,EAChBsD,EAAIE,QAAU,IAAMpD,KAAKqD,SAGzBrD,KAAKE,MAAQsC,SAASG,cAAc,OACpC3C,KAAKE,MAAM+C,UAAY,mBAA2C,gBAAzBjD,KAAKD,OAAOW,SAA6B,OAAS,IAC3FV,KAAKE,MAAMiD,UAAYnD,KAAKsD,eAG5BtD,KAAKC,UAAU+C,YAAYE,GAC3BlD,KAAKC,UAAU+C,YAAYhD,KAAKE,OAChCsC,SAASe,KAAKP,YAAYhD,KAAKC,WAG/BD,KAAKG,kBAAoBH,KAAKE,MAAMsD,cAAc,sBAClDxD,KAAKI,MAAQJ,KAAKE,MAAMsD,cAAc,mBAGtC,MAAMC,EAAWzD,KAAKE,MAAMsD,cAAc,mBAC1CC,GAAUC,iBAAiB,QAAS,IAAM1D,KAAK2D,SAE/C,MAAMC,EAAU5D,KAAKE,MAAMsD,cAAc,kBAWzC,GAVAI,GAASF,iBAAiB,QAAS,IAAM1D,KAAK6D,eAE9C7D,KAAKI,OAAOsD,iBAAiB,WAAaI,IAC1B,UAAVA,EAAEC,KAAoBD,EAAEE,WAC1BF,EAAEG,iBACFjE,KAAK6D,iBAKiB,SAAtB7D,KAAKD,OAAOY,MAAkB,CAChC,MAAMuD,EAAaC,OAAOC,WAAW,iCACrCpE,KAAKqE,YAAYH,EAAWI,SAC5BJ,EAAWR,iBAAiB,SAAWI,GAAM9D,KAAKqE,YAAYP,EAAEQ,SAClE,CACF,CAEQ,YAAAhB,GACN,MAAMiB,EAAgBvE,KAAKD,OAAOmB,WAC9B,GACA,+HAIJ,MAAO,gIAG8BtB,oEAEAI,KAAKD,OAAOc,wDACVb,KAAKD,OAAOe,+dAOUd,KAAKD,OAAOgB,4TAGrEwD,SAEN,CAEQ,WAAAF,CAAYG,GACdA,EACFxE,KAAKC,WAAWwE,UAAUC,IAAI,SAE9B1E,KAAKC,WAAWwE,UAAUE,OAAO,QAErC,CAEO,MAAAtB,GACLrD,KAAKK,OAASL,KAAK2D,QAAU3D,KAAK4E,MACpC,CAEO,IAAAA,GACL5E,KAAKK,QAAS,EACdL,KAAKE,OAAOuE,UAAUC,IAAI,QAC1B1E,KAAKI,OAAOyE,OACd,CAEO,KAAAlB,GACL3D,KAAKK,QAAS,EACdL,KAAKE,OAAOuE,UAAUE,OAAO,OAC/B,CAEQ,UAAArC,CAAWwC,EAA4BC,GAC7C,MAAMC,EAAmB,CACvBpC,GAAI,OAAOqC,KAAKC,QAChBJ,OACAC,UACAI,UAAW,IAAIF,MAGjBjF,KAAKM,SAAS8E,KAAKJ,GACnBhF,KAAKqF,cAAcL,EACrB,CAEQ,aAAAK,CAAcL,GACpB,IAAKhF,KAAKG,kBAAmB,OAE7B,MAAMmF,EAAK9C,SAASG,cAAc,OAClC2C,EAAGrC,UAAY,oBAAoB+B,EAAQF,OAC3CQ,EAAGnC,UAAYnD,KAAKuF,cAAcP,EAAQD,SAE1C/E,KAAKG,kBAAkB6C,YAAYsC,GACnCtF,KAAKwF,gBACP,CAEQ,aAAAD,CAAcR,GAEpB,MAAMU,EAAcC,GACXA,EACJC,QAAQ,KAAM,SACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,QACdA,QAAQ,KAAM,UACdA,QAAQ,KAAM,UAKbC,EAAuB,GAC7B,IAAIC,EAAYd,EAAQY,QAAQ,kCAAmC,CAACG,EAAGC,EAAMC,KAC3E,MAAMC,EAAUR,EAAWO,EAAKE,QAC1BC,EAAYJ,EAAO,mBAAmBN,EAAWM,MAAW,GAElE,OADAH,EAAWR,KAAK,mCAAmCe,WAAmBF,kBAC/D,cAAcL,EAAWQ,OAAS,QAI3C,MAAMC,EAAwB,GA0D9B,OAzDAR,EAAYA,EAAUF,QAAQ,aAAc,CAACG,EAAGE,KAC9CK,EAAYjB,KAAK,sCAAsCK,EAAWO,aAC3D,eAAeK,EAAYD,OAAS,QAI7CP,EAAYJ,EAAWI,GAGvBA,EAAYA,EAAUF,QAAQ,eAAgB,mCAC9CE,EAAYA,EAAUF,QAAQ,cAAe,mCAC7CE,EAAYA,EAAUF,QAAQ,aAAc,mCAG5CE,EAAYA,EAAUF,QAAQ,uBAAwB,gCACtDE,EAAYA,EAAUF,QAAQ,mBAAoB,uBAClDE,EAAYA,EAAUF,QAAQ,eAAgB,eAC9CE,EAAYA,EAAUF,QAAQ,aAAc,eAG5CE,EAAYA,EAAUF,QAAQ,2BAA4B,uFAG1DE,EAAYA,EAAUF,QAAQ,kBAAmB,mCACjDE,EAAYA,EAAUF,QAAQ,0CAA4CW,GACjE,2BAA2BA,UAIpCT,EAAYA,EAAUF,QAAQ,iBAAkB,2CAChDE,EAAYA,EAAUF,QAAQ,kDAAoDW,GACzE,2BAA2BA,UAIpCT,EAAYA,EAAUF,QAAQ,UAAW,4BAGzCE,EAAYA,EAAUF,QAAQ,gBAAiB,2DAG/CE,EAAYA,EAAUF,QAAQ,MAAO,QAGrCE,EAAYA,EAAUF,QAAQ,yCAA0C,SACxEE,EAAYA,EAAUF,QAAQ,sCAAuC,OAGrEC,EAAWW,QAAQ,CAACC,EAAOC,KACzBZ,EAAYA,EAAUF,QAAQ,cAAcc,MAAOD,KAIrDH,EAAYE,QAAQ,CAACP,EAAMS,KACzBZ,EAAYA,EAAUF,QAAQ,eAAec,MAAOT,KAG/CH,CACT,CAEQ,UAAAa,GACN,MAAMC,EAASnE,SAASG,cAAc,OAKtC,OAJAgE,EAAO1D,UAAY,kBACnB0D,EAAOxD,UAAY,0CACnBnD,KAAKG,mBAAmB6C,YAAY2D,GACpC3G,KAAKwF,iBACEmB,CACT,CAEQ,cAAAnB,GACFxF,KAAKG,oBACPH,KAAKG,kBAAkByG,UAAY5G,KAAKG,kBAAkB0G,aAE9D,CAEQ,iBAAMhD,GACZ,IAAK7D,KAAKI,OAASJ,KAAKO,UAAW,OAEnC,MAAMwE,EAAU/E,KAAKI,MAAM0G,MAAMZ,OACjC,IAAKnB,EAAS,OAGd/E,KAAKsC,WAAW,OAAQyC,GACxB/E,KAAKI,MAAM0G,MAAQ,GAGnB9G,KAAKO,WAAY,EACjB,MAAMoG,EAAS3G,KAAK0G,aAEpB,IACE,GAAI1G,KAAKD,OAAOkB,gBACRjB,KAAK+G,iBAAiBhC,EAAS4B,OAChC,CACL,MAAMjF,QAAiB1B,KAAKgH,QAAQjC,GACpC4B,EAAOhC,SAEHjD,EAASD,MACXzB,KAAKsC,WAAW,YAAa,kCAAkCZ,EAASD,SAExEzB,KAAKsC,WAAW,YAAaZ,EAASA,SAE1C,CACF,CAAE,MAAOD,GACPkF,EAAOhC,SACP3E,KAAKsC,WAAW,YAAa,sDAC7Bd,QAAQC,MAAM,kBAAmBA,EACnC,SACEzB,KAAKO,WAAY,CACnB,CACF,CAEQ,sBAAMwG,CAAiB/B,EAAiB2B,GAC9C,MAAMjF,QAAiBC,MAAM,GAAG3B,KAAKD,OAAOU,cAAe,CACzDwG,OAAQ,OACRC,QAAS,CACP,eAAgB,mBAChBC,cAAe,UAAUnH,KAAKD,OAAOqB,UAEvCmC,KAAM6D,KAAKC,UAAU,CACnBrC,UACAsC,QAAStH,KAAKuH,yBACdC,QAAQ,MAIZ,IAAK9F,EAASE,GAAI,CAChB+E,EAAOhC,SACP,MAAMlD,QAAcC,EAASI,OAAO2F,MAAM,MAAShG,MAAO,oBAE1D,YADAzB,KAAKsC,WAAW,YAAa,kCAAkCb,EAAMA,OAAS,mBAEhF,CAGAkF,EAAOhC,SACP,MAAM+C,EAAYlF,SAASG,cAAc,OACzC+E,EAAUzE,UAAY,6BACtBjD,KAAKG,mBAAmB6C,YAAY0E,GAEpC,MAAMC,EAASjG,EAAS6B,MAAMqE,YAC9B,IAAKD,EAEH,YADA3H,KAAKsC,WAAW,YAAa,sCAI/B,MAAMuF,EAAU,IAAIC,YACpB,IAAIC,EAAc,GAElB,IACE,OAAa,CACX,MAAMC,KAAEA,EAAIlB,MAAEA,SAAgBa,EAAOM,OACrC,GAAID,EAAM,MAEV,MACME,EADQL,EAAQM,OAAOrB,EAAO,CAAEU,QAAQ,IAC1BY,MAAM,MAAMC,OAAQC,GAAyB,KAAhBA,EAAKpC,QAEtD,IAAK,MAAMoC,KAAQJ,EACjB,GAAII,EAAKC,WAAW,UAAW,CAC7B,MAAMC,EAAOF,EAAKG,MAAM,GACxB,GAAa,WAATD,EAAmB,SAEvB,IACE,MAAME,EAAStB,KAAKuB,MAAMH,GACtBE,EAAO3D,UACTgD,GAAeW,EAAO3D,QACtB2C,EAAUvE,UAAYnD,KAAKuF,cAAcwC,GACzC/H,KAAKwF,iBAET,CAAE,MAEF,CACF,CAEJ,CACF,CAAE,MAAO/D,GACPD,QAAQC,MAAM,wBAAyBA,EACzC,CAGAzB,KAAKM,SAAS8E,KAAK,CACjBxC,GAAI,OAAOqC,KAAKC,QAChBJ,KAAM,YACNC,QAASgD,EACT5C,UAAW,IAAIF,MAEnB,CAEQ,aAAM+B,CAAQhC,GACpB,MAAMtD,QAAiBC,MAAM,GAAG3B,KAAKD,OAAOU,cAAe,CACzDwG,OAAQ,OACRC,QAAS,CACP,eAAgB,mBAChBC,cAAe,UAAUnH,KAAKD,OAAOqB,UAEvCmC,KAAM6D,KAAKC,UAAU,CACnBrC,UACAsC,QAAStH,KAAKuH,6BAIlB,IAAK7F,EAASE,GAAI,CAEhB,MAAO,CAAEF,SAAU,GAAID,aADHC,EAASI,OAAO2F,MAAM,MAAShG,MAAO,qBACtBA,OAAS,iBAC/C,CAEA,OAAOC,EAASI,MAClB,CAEQ,sBAAAyF,GAEN,OAAOvH,KAAKM,SAASmI,OAAM,IAAKG,IAAKC,IAAC,CACpC/D,KAAM+D,EAAE/D,KACRC,QAAS8D,EAAE9D,UAEf,CAEO,OAAA+D,GACL9I,KAAKC,WAAW0E,SAChBnC,SAASC,eAAe,oBAAoBkC,QAC9C,SC/cF,WAEE,MAAMoE,EAASvG,SAASwG,eACnBxG,SAASgB,cAAc,qCAE5B,IAAKuF,EAEH,YADAvH,QAAQQ,KAAK,uCAKf,MAAMjC,EAAyB,CAC7BqB,OAAQ2H,EAAOE,QAAQlF,KAAOgF,EAAOE,QAAQ7H,QAAU,GACvDX,OAAQsI,EAAOE,QAAQxI,QAAU,0BACjCC,SAAWqI,EAAOE,QAAQvI,UAA+C,eACzEC,MAAQoI,EAAOE,QAAQtI,OAAuC,OAC9DC,aAAcmI,EAAOE,QAAQC,OAAS,UACtCrI,MAAOkI,EAAOE,QAAQpI,OAAS,YAC/BC,SAAUiI,EAAOE,QAAQnI,UAAY,6BACrCC,YAAagI,EAAOE,QAAQlI,aAAe,oBAC3CC,eAAgB+H,EAAOE,QAAQE,SAAW,qFAC1ClI,UAAwC,UAA7B8H,EAAOE,QAAQhI,WAGvBlB,EAAOqB,OAMgB,YAAxBoB,SAAS4G,WACX5G,SAASkB,iBAAiB,mBAAoB,KAC3CS,OAAekF,SAAW,IAAIxJ,EAAeE,KAG/CoE,OAAekF,SAAW,IAAIxJ,EAAeE,GAV9CyB,QAAQC,MAAM,uCAYjB,CArCD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kroonen-ai/librebot-widget",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "type": "module",
5
5
  "description": "Libre Bot - AI documentation assistant widget",
6
6
  "main": "dist/librebot.js",