@headwai/chat-bubble 3.0.4 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.dev.md +225 -27
- package/README.md +153 -105
- package/dist-widget/chat-bubble.js +4 -4
- package/package.json +1 -1
package/README.dev.md
CHANGED
|
@@ -12,17 +12,20 @@ The chat bubble is based on a Svelte integration for the [deep-chat](https://www
|
|
|
12
12
|
### Setup
|
|
13
13
|
|
|
14
14
|
1. Clone this repository:
|
|
15
|
+
|
|
15
16
|
```bash
|
|
16
17
|
git clone <your-repo-url>
|
|
17
18
|
cd chat-bubble
|
|
18
19
|
```
|
|
19
20
|
|
|
20
21
|
2. Install dependencies:
|
|
22
|
+
|
|
21
23
|
```bash
|
|
22
24
|
npm install
|
|
23
25
|
```
|
|
24
26
|
|
|
25
27
|
3. Create a `.env` file in the root directory:
|
|
28
|
+
|
|
26
29
|
```bash
|
|
27
30
|
cp .env.example .env
|
|
28
31
|
```
|
|
@@ -30,47 +33,54 @@ cp .env.example .env
|
|
|
30
33
|
4. Configure your environment variables (see [Configuration](#configuration) section)
|
|
31
34
|
|
|
32
35
|
5. Start the development server:
|
|
36
|
+
|
|
33
37
|
```bash
|
|
34
38
|
npm run dev
|
|
35
39
|
```
|
|
36
40
|
|
|
37
41
|
6. Open embedded Headwai Chat Bubble in Browser
|
|
42
|
+
|
|
38
43
|
```bash
|
|
39
44
|
http://localhost:5174/
|
|
40
45
|
```
|
|
41
46
|
|
|
42
47
|
7. Alternatively, build and test deployed version:
|
|
43
|
-
[Build and Deploy](#build-and-deploy) and open `./test-widget.html` in a browser.
|
|
48
|
+
[Build and Deploy](#build-and-deploy) and open `./test-widget.html` in a browser.
|
|
44
49
|
|
|
45
50
|
## Configuration
|
|
46
51
|
|
|
47
|
-
The Headwai Chat Bubble can be configured using environment variables or by changing the attributes of the instance.
|
|
52
|
+
The Headwai Chat Bubble can be configured using environment variables or by changing the attributes of the instance.
|
|
48
53
|
|
|
49
54
|
### Environment Variables
|
|
55
|
+
|
|
50
56
|
Create a `.env` by copying `.env.example` file in your project root with the following variables:
|
|
51
57
|
|
|
52
58
|
### Window Object Configuration
|
|
59
|
+
|
|
53
60
|
```html
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
<script>
|
|
62
|
+
// Runtime configuration override
|
|
63
|
+
window.HEADWAI_CHAT_BUBBLE_CONFIG = {
|
|
64
|
+
apiUrl: 'https://customer-api.com/chat',
|
|
65
|
+
apiKey: 'customer-api-key',
|
|
66
|
+
modelId: 'gpt-4',
|
|
67
|
+
};
|
|
68
|
+
</script>
|
|
62
69
|
```
|
|
63
70
|
|
|
64
|
-
### Via data attributes (Multiple chat bubbles)
|
|
71
|
+
### Via data attributes (Multiple chat bubbles):\*\*
|
|
72
|
+
|
|
65
73
|
```html
|
|
66
|
-
<div
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
<div
|
|
75
|
+
data-chat-bubble
|
|
76
|
+
data-chat-bubble-api-url="https://api1.com/chat"
|
|
77
|
+
data-chat-bubble-api-key="key1"
|
|
78
|
+
data-chat-bubble-user-message-background-color="#ff9500"
|
|
79
|
+
data-chat-bubble-ai-message-background-color="#00c851"
|
|
80
|
+
data-chat-bubble-user-message-text-color="#ffffff"
|
|
81
|
+
data-chat-bubble-ai-message-text-color="#004225"
|
|
82
|
+
data-chat-bubble-favicon-background-color="#ff6f00"
|
|
83
|
+
></div>
|
|
74
84
|
```
|
|
75
85
|
|
|
76
86
|
## Including Chat Bubble in Customer Websites
|
|
@@ -82,13 +92,16 @@ For simple integration instructions, see [README.md](README.md) which provides a
|
|
|
82
92
|
This project builds a standalone widget that can be integrated into any website.
|
|
83
93
|
|
|
84
94
|
**What gets bundled:**
|
|
95
|
+
|
|
85
96
|
- ✅ All logic and request/response interceptors
|
|
86
97
|
- ✅ Environment variable configuration
|
|
87
98
|
- ✅ All chat functionality
|
|
88
99
|
- ✅ UI components and styling
|
|
89
100
|
|
|
90
101
|
**Build and deployment steps:**
|
|
102
|
+
|
|
91
103
|
1. **Configure environment variables** for production:
|
|
104
|
+
|
|
92
105
|
```bash
|
|
93
106
|
# Production .env file
|
|
94
107
|
VITE_CHAT_BUBBLE_API_URL=https://api.customer-domain.com/chat
|
|
@@ -97,23 +110,26 @@ VITE_CHAT_BUBBLE_MODEL_ID=gpt-4
|
|
|
97
110
|
```
|
|
98
111
|
|
|
99
112
|
2. **Bump package version**
|
|
100
|
-
Bump up the `version` in `package.json`
|
|
113
|
+
Bump up the `version` in `package.json`
|
|
101
114
|
|
|
102
115
|
## Publishing to NPM and jsDelivr Access
|
|
103
116
|
|
|
104
117
|
### Publishing Steps
|
|
105
118
|
|
|
106
119
|
3. **Build widget**:
|
|
120
|
+
|
|
107
121
|
```bash
|
|
108
122
|
npm run build
|
|
109
123
|
```
|
|
110
124
|
|
|
111
125
|
4. **Login to NPM** (if not already logged in):
|
|
126
|
+
|
|
112
127
|
```bash
|
|
113
128
|
npm login
|
|
114
129
|
```
|
|
115
130
|
|
|
116
131
|
5. **Publish the package**:
|
|
132
|
+
|
|
117
133
|
```bash
|
|
118
134
|
npm publish
|
|
119
135
|
```
|
|
@@ -123,16 +139,193 @@ npm publish
|
|
|
123
139
|
Once published to NPM, your package is automatically available on jsDelivr:
|
|
124
140
|
|
|
125
141
|
**For Widget/Script Embed:**
|
|
142
|
+
|
|
126
143
|
```html
|
|
127
144
|
<!-- Latest version -->
|
|
128
|
-
<link
|
|
145
|
+
<link
|
|
146
|
+
rel="stylesheet"
|
|
147
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.css"
|
|
148
|
+
/>
|
|
129
149
|
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.js"></script>
|
|
130
150
|
|
|
131
151
|
<!-- Specific version -->
|
|
132
|
-
<link
|
|
152
|
+
<link
|
|
153
|
+
rel="stylesheet"
|
|
154
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.0.0/dist-widget/chat-bubble.css"
|
|
155
|
+
/>
|
|
133
156
|
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.0.0/dist-widget/chat-bubble.js"></script>
|
|
134
157
|
```
|
|
135
158
|
|
|
159
|
+
## API Reference
|
|
160
|
+
|
|
161
|
+
### APIs Called
|
|
162
|
+
|
|
163
|
+
The chat bubble makes requests to the following API endpoints:
|
|
164
|
+
|
|
165
|
+
#### 1. Chat Completions API
|
|
166
|
+
|
|
167
|
+
- **Endpoint**: `{apiUrl}/api/chat-bubble/chat/completions`
|
|
168
|
+
- **Method**: WebSocket (streaming)
|
|
169
|
+
- **Purpose**: Main chat conversation endpoint for sending messages and receiving AI responses
|
|
170
|
+
- **Authentication**: Bearer token via `Authorization` header
|
|
171
|
+
- **Request Format**: OpenAI-compatible chat completions format
|
|
172
|
+
- **Response Format**: Server-sent events with OpenAI-compatible streaming format
|
|
173
|
+
|
|
174
|
+
#### 2. Chat Creation API
|
|
175
|
+
|
|
176
|
+
- **Endpoint**: `{apiUrl}/api/chat-bubble/v1/chats/new`
|
|
177
|
+
- **Method**: POST
|
|
178
|
+
- **Purpose**: Create a new chat session when starting a conversation
|
|
179
|
+
- **Authentication**: Bearer token via `Authorization` header
|
|
180
|
+
- **Request Body**: Chat metadata including models, history, messages, and timestamps
|
|
181
|
+
|
|
182
|
+
#### 3. Chat Storage API
|
|
183
|
+
|
|
184
|
+
- **Endpoint**: `{apiUrl}/api/chat-bubble/v1/chats/{chatId}`
|
|
185
|
+
- **Method**: POST
|
|
186
|
+
- **Purpose**: Store/update chat history and conversation state
|
|
187
|
+
- **Authentication**: Bearer token via `Authorization` header
|
|
188
|
+
- **Request Body**: Complete chat state including message history and metadata
|
|
189
|
+
|
|
190
|
+
#### 4. Feedback API
|
|
191
|
+
|
|
192
|
+
- **Endpoint**: `{apiUrl}/api/chat-bubble/v1/evaluations/feedback`
|
|
193
|
+
- **Method**: POST
|
|
194
|
+
- **Purpose**: Submit user feedback (thumbs up/down) for AI responses
|
|
195
|
+
- **Authentication**: Bearer token via `Authorization` header
|
|
196
|
+
- **Request Body**: Feedback data including rating, message metadata, and chat snapshot
|
|
197
|
+
|
|
198
|
+
### Configuration Attributes
|
|
199
|
+
|
|
200
|
+
The chat bubble can be configured using environment variables, data attributes, or runtime configuration. All attributes have fallback defaults.
|
|
201
|
+
|
|
202
|
+
#### Core API Configuration
|
|
203
|
+
|
|
204
|
+
| Attribute | Environment Variable | Data Attribute | Purpose | Default |
|
|
205
|
+
| --------- | --------------------------- | --------------------------- | ---------------------------------------- | ------------------- |
|
|
206
|
+
| `apiUrl` | `VITE_CHAT_BUBBLE_API_URL` | `data-chat-bubble-api-url` | Base URL for API endpoints | `https://localhost` |
|
|
207
|
+
| `apiKey` | `VITE_CHAT_BUBBLE_API_KEY` | `data-chat-bubble-api-key` | Authentication token for API requests | `''` |
|
|
208
|
+
| `modelId` | `VITE_CHAT_BUBBLE_MODEL_ID` | `data-chat-bubble-model-id` | AI model identifier to use for responses | `test-model` |
|
|
209
|
+
|
|
210
|
+
#### Message Configuration
|
|
211
|
+
|
|
212
|
+
| Attribute | Environment Variable | Data Attribute | Purpose | Default |
|
|
213
|
+
| ----------------- | ----------------------------------- | ----------------------------------- | ------------------------------------------------------ | --------------------------- |
|
|
214
|
+
| `maxMessages` | `VITE_CHAT_BUBBLE_MAX_MESSAGES` | `data-chat-bubble-max-messages` | Maximum messages to include in context (0 = unlimited) | `0` |
|
|
215
|
+
| `initialMessage` | `VITE_CHAT_BUBBLE_INITIAL_MESSAGE` | `data-chat-bubble-initial-message` | First message shown when chat opens | `Hey, how can I help you?` |
|
|
216
|
+
| `placeholderText` | `VITE_CHAT_BUBBLE_PLACEHOLDER_TEXT` | `data-chat-bubble-placeholder-text` | Input field placeholder text | `Enter your questions here` |
|
|
217
|
+
|
|
218
|
+
#### UI Styling Configuration
|
|
219
|
+
|
|
220
|
+
| Attribute | Environment Variable | Data Attribute | Purpose | Default |
|
|
221
|
+
| -------------------------------- | ---------------------------------------------- | ---------------------------------------------------- | ------------------------------------- | --------- |
|
|
222
|
+
| `userMessageBackgroundColor` | `VITE_CHAT_BUBBLE_USER_MESSAGE_BG_COLOR` | `data-chat-bubble-user-message-background-color` | Background color for user messages | `#007bff` |
|
|
223
|
+
| `userMessageTextColor` | `VITE_CHAT_BUBBLE_USER_MESSAGE_TEXT_COLOR` | `data-chat-bubble-user-message-text-color` | Text color for user messages | `#000000` |
|
|
224
|
+
| `aiMessageBackgroundColor` | `VITE_CHAT_BUBBLE_AI_MESSAGE_BG_COLOR` | `data-chat-bubble-ai-message-background-color` | Background color for AI messages | `#f1f3f4` |
|
|
225
|
+
| `aiMessageTextColor` | `VITE_CHAT_BUBBLE_AI_MESSAGE_TEXT_COLOR` | `data-chat-bubble-ai-message-text-color` | Text color for AI messages | `#000000` |
|
|
226
|
+
| `feedbackMessageBackgroundColor` | `VITE_CHAT_BUBBLE_FEEDBACK_MESSAGE_BG_COLOR` | `data-chat-bubble-feedback-message-background-color` | Background color for feedback buttons | `#ffffff` |
|
|
227
|
+
| `feedbackMessageTextColor` | `VITE_CHAT_BUBBLE_FEEDBACK_MESSAGE_TEXT_COLOR` | `data-chat-bubble-feedback-message-text-color` | Text color for feedback buttons | `#000000` |
|
|
228
|
+
| `faviconBackgroundColor` | `VITE_CHAT_BUBBLE_FAVICON_BG_COLOR` | `data-chat-bubble-favicon-background-color` | Background color for chat icon | `#667eea` |
|
|
229
|
+
| `fontFamily` | `VITE_CHAT_BUBBLE_FONT_FAMILY` | `data-chat-bubble-font-family` | Font family for chat interface | `inherit` |
|
|
230
|
+
| `fontSize` | `VITE_CHAT_BUBBLE_FONT_SIZE` | `data-chat-bubble-font-size` | Font size for chat interface | `inherit` |
|
|
231
|
+
|
|
232
|
+
#### Branding Configuration
|
|
233
|
+
|
|
234
|
+
| Attribute | Environment Variable | Data Attribute | Purpose | Default |
|
|
235
|
+
| ------------- | ------------------------------- | ------------------------------- | -------------------------- | --------------------- |
|
|
236
|
+
| `chatTitle` | `VITE_CHAT_BUBBLE_CHAT_TITLE` | `data-chat-bubble-chat-title` | Title shown in chat header | `Headwai Chat Bubble` |
|
|
237
|
+
| `faviconPath` | `VITE_CHAT_BUBBLE_FAVICON_PATH` | `data-chat-bubble-favicon-path` | Path to chat icon/logo | `./icons/favicon.svg` |
|
|
238
|
+
|
|
239
|
+
### API Request Flow and Data Format
|
|
240
|
+
|
|
241
|
+
#### Chat Completions Request
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
{
|
|
245
|
+
"messages": [
|
|
246
|
+
{
|
|
247
|
+
"role": "user|assistant",
|
|
248
|
+
"content": "message text"
|
|
249
|
+
}
|
|
250
|
+
],
|
|
251
|
+
"model": "model-id",
|
|
252
|
+
"stream": true,
|
|
253
|
+
"chat_id": "uuid-if-existing",
|
|
254
|
+
"params": {},
|
|
255
|
+
"tool_servers": [],
|
|
256
|
+
"features": {
|
|
257
|
+
"image_generation": false,
|
|
258
|
+
"code_interpreter": false,
|
|
259
|
+
"web_search": false,
|
|
260
|
+
"memory": false
|
|
261
|
+
},
|
|
262
|
+
"variables": {
|
|
263
|
+
"{{USER_NAME}}": "David Schneebauer | headwAI GmbH",
|
|
264
|
+
"{{USER_LOCATION}}": "Unknown",
|
|
265
|
+
"{{CURRENT_DATETIME}}": "2025-01-07 15:30:45",
|
|
266
|
+
// ... additional template variables
|
|
267
|
+
},
|
|
268
|
+
"background_tasks": {
|
|
269
|
+
"title_generation": true,
|
|
270
|
+
"tags_generation": false,
|
|
271
|
+
"follow_up_generation": false
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Chat Creation Request
|
|
277
|
+
|
|
278
|
+
```javascript
|
|
279
|
+
{
|
|
280
|
+
"chat": {
|
|
281
|
+
"id": "",
|
|
282
|
+
"title": "New Chatbubble Chat",
|
|
283
|
+
"models": ["model-id"],
|
|
284
|
+
"params": {},
|
|
285
|
+
"history": {
|
|
286
|
+
"messages": {"message-id": {...}},
|
|
287
|
+
"currentId": "last-message-id"
|
|
288
|
+
},
|
|
289
|
+
"messages": [{
|
|
290
|
+
"id": "uuid",
|
|
291
|
+
"parentId": "parent-uuid",
|
|
292
|
+
"childrenIds": ["child-uuid"],
|
|
293
|
+
"role": "assistant|user",
|
|
294
|
+
"content": "message content",
|
|
295
|
+
"timestamp": 1704636645,
|
|
296
|
+
"models": ["model-id"]
|
|
297
|
+
}],
|
|
298
|
+
"tags": [],
|
|
299
|
+
"timestamp": 1704636645000
|
|
300
|
+
},
|
|
301
|
+
"folder_id": null
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
#### Feedback Request
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
{
|
|
309
|
+
"type": "rating",
|
|
310
|
+
"data": {
|
|
311
|
+
"rating": 1, // 1 for positive, -1 for negative
|
|
312
|
+
"model_id": "model-id"
|
|
313
|
+
},
|
|
314
|
+
"meta": {
|
|
315
|
+
"model_id": "model-id",
|
|
316
|
+
"message_id": "message-uuid",
|
|
317
|
+
"message_index": 2,
|
|
318
|
+
"chat_id": "chat-uuid",
|
|
319
|
+
"base_models": {"model-id": "model-id"}
|
|
320
|
+
},
|
|
321
|
+
"snapshot": {
|
|
322
|
+
"chat": {
|
|
323
|
+
// Complete chat state for context
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
136
329
|
## API Compatibility
|
|
137
330
|
|
|
138
331
|
This component is designed to work with OpenAI-compatible APIs. The request and response interceptors handle the message format transformation between deep-chat and OpenAI formats.
|
|
@@ -162,15 +355,20 @@ This component is designed to work with OpenAI-compatible APIs. The request and
|
|
|
162
355
|
**Authentication Failures**: Verify your API key is correct and has proper permissions
|
|
163
356
|
**Environment Variables Not Loading**: Ensure variables are prefixed with `VITE_CHAT_BUBBLE_`
|
|
164
357
|
**CDN Version Delays**: Sometimes the `@latest` tag on jsDelivr CDN takes time to propagate to all edge servers and may not deliver the newest version immediately. If you need the latest features or fixes, specify the exact version number instead of using `@latest`:
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
358
|
+
|
|
359
|
+
```html
|
|
360
|
+
<!-- Instead of @latest -->
|
|
361
|
+
<link
|
|
362
|
+
rel="stylesheet"
|
|
363
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.2.3/dist-widget/chat-bubble.css"
|
|
364
|
+
/>
|
|
365
|
+
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.2.3/dist-widget/chat-bubble.js"></script>
|
|
366
|
+
```
|
|
170
367
|
|
|
171
368
|
## Support
|
|
172
369
|
|
|
173
370
|
For issues and questions:
|
|
371
|
+
|
|
174
372
|
- Create an issue in this repository
|
|
175
373
|
- Check the [deep-chat documentation](https://deepchat.dev/)
|
|
176
374
|
- Review the [API compatibility guide](https://deepchat.dev/docs/connect)
|
package/README.md
CHANGED
|
@@ -16,40 +16,43 @@ Add the Headwai Chat Bubble to the respective .html file.
|
|
|
16
16
|
```html
|
|
17
17
|
<!DOCTYPE html>
|
|
18
18
|
<html>
|
|
19
|
-
<head>
|
|
19
|
+
<head>
|
|
20
20
|
<title>Customer Website</title>
|
|
21
21
|
<!-- Configure via global variables -->
|
|
22
22
|
<script>
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
23
|
+
// Runtime configuration override
|
|
24
|
+
window.HEADWAI_CHAT_BUBBLE_CONFIG = {
|
|
25
|
+
apiUrl: 'https://company.localchat.at', // required
|
|
26
|
+
apiKey: 'chat-bubble-proxy-api-key', // required
|
|
27
|
+
modelId: 'customer-support-model-id', // required
|
|
28
|
+
maxMessages: 0, // optional - 0 means unlimited
|
|
29
|
+
placeholderText: 'Ask your question here!', // optional - default: 'Enter your questions here'
|
|
30
|
+
faviconPath: 'https://cdn.company.at/icons/favicon.svg', // optional - default: '/icons/favicon.svg'
|
|
31
|
+
initialMessage: 'Hey! My name is Supporty, how can I help you?', // optional - default: 'Hey, how can I help you?'
|
|
32
|
+
chatTitle: 'Customer Support', // optional - default: 'Headwai Chat Bubble'
|
|
33
|
+
userMessageBackgroundColor: '#007bff', // optional - default: '#007bff'
|
|
34
|
+
aiMessageBackgroundColor: '#f1f3f4', // optional - default: '#f1f3f4'
|
|
35
|
+
userMessageTextColor: '#000000', // optional - default: '#000000'
|
|
36
|
+
aiMessageTextColor: '#000000', // optional - default: '#000000'
|
|
37
|
+
faviconBackgroundColor: '#667eea', // optional - default: '#667eea'
|
|
38
|
+
fontFamily: '"Inter", system-ui, sans-serif', // optional - default: 'inherit'
|
|
39
|
+
fontSize: '16px', // optional - default: 'inherit'
|
|
40
|
+
};
|
|
41
41
|
</script>
|
|
42
|
-
</head>
|
|
43
|
-
<body>
|
|
42
|
+
</head>
|
|
43
|
+
<body>
|
|
44
44
|
<!-- Your existing content -->
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
<!-- Chat Bubble Integration - Auto-initializes! -->
|
|
47
47
|
<div id="chat-bubble-container"></div>
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
<!-- Include from jsDelivr CDN -->
|
|
50
|
-
<link
|
|
50
|
+
<link
|
|
51
|
+
rel="stylesheet"
|
|
52
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.css"
|
|
53
|
+
/>
|
|
51
54
|
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.js"></script>
|
|
52
|
-
</body>
|
|
55
|
+
</body>
|
|
53
56
|
</html>
|
|
54
57
|
```
|
|
55
58
|
|
|
@@ -58,61 +61,71 @@ Get the desired version of the JavaScript and CSS in your `<body>`.
|
|
|
58
61
|
|
|
59
62
|
```html
|
|
60
63
|
<!-- Latest version -->
|
|
61
|
-
<link
|
|
64
|
+
<link
|
|
65
|
+
rel="stylesheet"
|
|
66
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.css"
|
|
67
|
+
/>
|
|
62
68
|
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.js"></script>
|
|
63
69
|
|
|
64
70
|
<!-- Specific version -->
|
|
65
|
-
<link
|
|
71
|
+
<link
|
|
72
|
+
rel="stylesheet"
|
|
73
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.0.0/dist-widget/chat-bubble.css"
|
|
74
|
+
/>
|
|
66
75
|
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.0.0/dist-widget/chat-bubble.js"></script>
|
|
67
76
|
```
|
|
68
77
|
|
|
69
78
|
Place the Headwai Chat Bubble into the `<body>` tag. It will apear on the right corner of your website.
|
|
70
79
|
|
|
71
|
-
|
|
72
80
|
#### Multiple Headwai Chat Bubbles
|
|
73
81
|
|
|
74
82
|
For multiple instances use data attributes of the `<div>` tag for configuration instead.
|
|
75
83
|
|
|
76
84
|
```html
|
|
77
85
|
<!-- Chat bubble with specific configuration -->
|
|
78
|
-
<div
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
86
|
+
<div
|
|
87
|
+
data-chat-bubble
|
|
88
|
+
data-chat-bubble-api-url="https://company.localchat.at"
|
|
89
|
+
data-chat-bubble-api-key="chat-bubble-proxy-api-key"
|
|
90
|
+
data-chat-bubble-model-id="customer-support-model-id"
|
|
91
|
+
data-chat-bubble-max-messages="0"
|
|
92
|
+
data-chat-bubble-placeholder-text="Ask your question here!"
|
|
93
|
+
data-chat-bubble-favicon-path="https://cdn.company.at/icons/favicon.svg"
|
|
94
|
+
data-chat-bubble-initial-message="Hey! My name is Supporty, how can I help you?"
|
|
95
|
+
data-chat-bubble-chat-title="Customer Support"
|
|
96
|
+
data-chat-bubble-user-message-background-color="#007bff"
|
|
97
|
+
data-chat-bubble-ai-message-background-color="#f1f3f4"
|
|
98
|
+
data-chat-bubble-user-message-text-color="#000000"
|
|
99
|
+
data-chat-bubble-ai-message-text-color="#000000"
|
|
100
|
+
data-chat-bubble-favicon-background-color="#667eea"
|
|
101
|
+
data-chat-bubble-font-family='"Inter", system-ui, sans-serif'
|
|
102
|
+
data-chat-bubble-font-size="16px"
|
|
103
|
+
></div>
|
|
95
104
|
|
|
96
105
|
<!-- Another chat bubble with different config -->
|
|
97
|
-
<div
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
<div
|
|
107
|
+
data-chat-bubble
|
|
108
|
+
data-chat-bubble-api-url="https://company.localchat.at"
|
|
109
|
+
data-chat-bubble-api-key="chat-bubble-proxy-api-key"
|
|
110
|
+
data-chat-bubble-model-id="FAQ-model-id"
|
|
111
|
+
data-chat-bubble-max-messages="10"
|
|
112
|
+
data-chat-bubble-placeholder-text="Ask about our FAQ..."
|
|
113
|
+
data-chat-bubble-favicon-path="https://cdn.company.at/icons/faq-icon.svg"
|
|
114
|
+
data-chat-bubble-initial-message="Hello! I can help you with frequently asked questions."
|
|
115
|
+
data-chat-bubble-chat-title="FAQ Assistant"
|
|
116
|
+
data-chat-bubble-user-message-background-color="#28a745"
|
|
117
|
+
data-chat-bubble-ai-message-background-color="#e9ecef"
|
|
118
|
+
data-chat-bubble-user-message-text-color="#ffffff"
|
|
119
|
+
data-chat-bubble-ai-message-text-color="#495057"
|
|
120
|
+
data-chat-bubble-favicon-background-color="#28a745"
|
|
121
|
+
data-chat-bubble-font-family='"Roboto", sans-serif'
|
|
122
|
+
data-chat-bubble-font-size="14px"
|
|
123
|
+
></div>
|
|
124
|
+
|
|
125
|
+
<link
|
|
126
|
+
rel="stylesheet"
|
|
127
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.css"
|
|
128
|
+
/>
|
|
116
129
|
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@latest/dist-widget/chat-bubble.js"></script>
|
|
117
130
|
```
|
|
118
131
|
|
|
@@ -123,17 +136,21 @@ The Headwai Chat Bubble can be configured using either the global `window.DEEP_C
|
|
|
123
136
|
### Required Configuration
|
|
124
137
|
|
|
125
138
|
#### `apiUrl`
|
|
139
|
+
|
|
126
140
|
**Type:** `string` | **Required:** ✅
|
|
127
141
|
The base URL of your LocalChat API endpoint where the chat bubble will send messages. This is the same URL you access your LocalCaht instance in the Webbrowser.
|
|
142
|
+
|
|
128
143
|
```javascript
|
|
129
|
-
apiUrl: 'https://company.localchat.at'
|
|
144
|
+
apiUrl: 'https://company.localchat.at';
|
|
130
145
|
```
|
|
131
146
|
|
|
132
|
-
#### `apiKey`
|
|
147
|
+
#### `apiKey`
|
|
148
|
+
|
|
133
149
|
**Type:** `string` | **Required:** ✅
|
|
134
|
-
The API Key of
|
|
150
|
+
The API Key of the dedicated Headwai Chat Bubble Proxy for LocalChat.
|
|
151
|
+
|
|
135
152
|
```javascript
|
|
136
|
-
apiKey: '
|
|
153
|
+
apiKey: 'chat-bubble-proxy-api-key';
|
|
137
154
|
```
|
|
138
155
|
|
|
139
156
|
**How to get your API Key:**
|
|
@@ -152,130 +169,159 @@ apiKey: 'customer-support-user-api-key'
|
|
|
152
169
|
|
|
153
170
|
**⚠️ Security Note:** When using permanent API Keys, ensure they are stored securely (e.g., environment variables, secure configuration) and never expose them directly in client-side code. If using JWT Tokens, implement an automatic refresh mechanism since they expire after 7 days - consider using a server-side proxy to handle token renewal and keep tokens secure.
|
|
154
171
|
|
|
155
|
-
|
|
156
172
|
#### `modelId`
|
|
173
|
+
|
|
157
174
|
**Type:** `string` | **Required:** ✅
|
|
158
175
|
The identifier of the AI model to use for generating responses. This should match a model configured in your LocalChat instance.
|
|
176
|
+
|
|
159
177
|
```javascript
|
|
160
|
-
modelId: 'customer-support-model-id'
|
|
178
|
+
modelId: 'customer-support-model-id';
|
|
161
179
|
```
|
|
162
180
|
|
|
163
181
|
1. **Navigate to Model**: Login to LocalChat with the dedicated Headwai Chat Bubble user (Or any other user that is allowed to see the desired model) and click on the `Workspace` menu, then select `Models`. Search for the name of the desired model (Or create one). Click onto the edit-`Pen`.
|
|
164
182
|
|
|
165
183
|
<img src="docs/images/model-edit.png" alt="LocalChat User Menu" width="50%" />
|
|
166
184
|
|
|
167
|
-
1. **Copy Model Id**: Now the model is displayed with its `name` and right underneath the `model-id`. Copy the `model-id`.
|
|
185
|
+
1. **Copy Model Id**: Now the model is displayed with its `name` and right underneath the `model-id`. Copy the `model-id`.
|
|
168
186
|
|
|
169
187
|
<img src="docs/images/model-id.png" alt="LocalChat User Menu" width="50%" />
|
|
170
188
|
|
|
171
189
|
### Optional Configuration
|
|
172
190
|
|
|
173
191
|
#### `maxMessages`
|
|
192
|
+
|
|
174
193
|
**Type:** `number` | **Default:** `0` (unlimited)
|
|
175
194
|
Limits the number of messages stored in the conversation history in one singel conversation. Set to `0` for unlimited messages, or specify a positive number to limit history.
|
|
195
|
+
|
|
176
196
|
```javascript
|
|
177
|
-
maxMessages: 10 // Keep and use only last 10 messages
|
|
197
|
+
maxMessages: 10; // Keep and use only last 10 messages
|
|
178
198
|
```
|
|
179
199
|
|
|
180
200
|
#### `placeholderText`
|
|
201
|
+
|
|
181
202
|
**Type:** `string` | **Default:** `'Type your message...'`
|
|
182
203
|
The placeholder text displayed in the message input field when it's empty.
|
|
204
|
+
|
|
183
205
|
```javascript
|
|
184
|
-
placeholderText: 'Ask your question here!'
|
|
206
|
+
placeholderText: 'Ask your question here!';
|
|
185
207
|
```
|
|
186
208
|
|
|
187
209
|
#### `faviconPath`
|
|
210
|
+
|
|
188
211
|
**Type:** `string` | **Default:** `'/icons/favicon.svg'`
|
|
189
212
|
Path or URL to the icon displayed on the chat bubble toggle button. Can be a relative path or absolute URL.
|
|
213
|
+
|
|
190
214
|
```javascript
|
|
191
|
-
faviconPath: 'https://cdn.company.at/icons/favicon.svg'
|
|
215
|
+
faviconPath: 'https://cdn.company.at/icons/favicon.svg';
|
|
192
216
|
```
|
|
193
217
|
|
|
194
218
|
#### `initialMessage`
|
|
219
|
+
|
|
195
220
|
**Type:** `string` | **Default:** `undefined`
|
|
196
221
|
An optional welcome message that appears when the chat is first opened. If not set, no initial message is displayed.
|
|
222
|
+
|
|
197
223
|
```javascript
|
|
198
|
-
initialMessage: 'Hey! My name is Supporty, how can I help you?'
|
|
224
|
+
initialMessage: 'Hey! My name is Supporty, how can I help you?';
|
|
199
225
|
```
|
|
200
226
|
|
|
201
227
|
#### `chatTitle`
|
|
228
|
+
|
|
202
229
|
**Type:** `string` | **Default:** `'Headwai Chat Bubble'`
|
|
203
230
|
The title displayed in the chat window header at the top of the chat interface.
|
|
231
|
+
|
|
204
232
|
```javascript
|
|
205
|
-
chatTitle: 'Customer Support'
|
|
233
|
+
chatTitle: 'Customer Support';
|
|
206
234
|
```
|
|
207
235
|
|
|
208
236
|
### Styling Configuration
|
|
209
237
|
|
|
210
238
|
#### `userMessageBackgroundColor`
|
|
239
|
+
|
|
211
240
|
**Type:** `string` | **Default:** `'#007bff'`
|
|
212
241
|
Background color for messages sent by the user. Accepts any valid CSS color value.
|
|
242
|
+
|
|
213
243
|
```javascript
|
|
214
|
-
userMessageBackgroundColor: '#007bff'
|
|
244
|
+
userMessageBackgroundColor: '#007bff';
|
|
215
245
|
```
|
|
216
246
|
|
|
217
247
|
#### `aiMessageBackgroundColor`
|
|
248
|
+
|
|
218
249
|
**Type:** `string` | **Default:** `'#f1f3f4'`
|
|
219
250
|
Background color for messages sent by the Headwai Chat Bubble. Accepts any valid CSS color value.
|
|
251
|
+
|
|
220
252
|
```javascript
|
|
221
|
-
aiMessageBackgroundColor: '#f1f3f4'
|
|
253
|
+
aiMessageBackgroundColor: '#f1f3f4';
|
|
222
254
|
```
|
|
223
255
|
|
|
224
256
|
#### `userMessageTextColor`
|
|
257
|
+
|
|
225
258
|
**Type:** `string` | **Default:** `'#000000'`
|
|
226
259
|
Text color for user messages. Accepts any valid CSS color value.
|
|
260
|
+
|
|
227
261
|
```javascript
|
|
228
|
-
userMessageTextColor: '#ffffff'
|
|
262
|
+
userMessageTextColor: '#ffffff';
|
|
229
263
|
```
|
|
230
264
|
|
|
231
265
|
#### `aiMessageTextColor`
|
|
266
|
+
|
|
232
267
|
**Type:** `string` | **Default:** `'#000000'`
|
|
233
268
|
Text color for Headwai Chat Bubble messages. Accepts any valid CSS color value.
|
|
269
|
+
|
|
234
270
|
```javascript
|
|
235
|
-
aiMessageTextColor: '#333333'
|
|
271
|
+
aiMessageTextColor: '#333333';
|
|
236
272
|
```
|
|
237
273
|
|
|
238
274
|
#### `faviconBackgroundColor`
|
|
275
|
+
|
|
239
276
|
**Type:** `string` | **Default:** `'#667eea'`
|
|
240
277
|
Base color used for the assistant icon gradient. This color influences the overall appearance of the Headwai Chat Bubble's avatar.
|
|
278
|
+
|
|
241
279
|
```javascript
|
|
242
|
-
faviconBackgroundColor: '#667eea'
|
|
280
|
+
faviconBackgroundColor: '#667eea';
|
|
243
281
|
```
|
|
244
282
|
|
|
245
283
|
#### `fontFamily`
|
|
284
|
+
|
|
246
285
|
**Type:** `string` | **Default:** `'inherit'`
|
|
247
286
|
Font family used for all text in the chat interface, including messages and the input field. Accepts any valid CSS font-family value.
|
|
287
|
+
|
|
248
288
|
```javascript
|
|
249
|
-
fontFamily: '"Inter", system-ui, sans-serif'
|
|
250
|
-
fontFamily: '"Roboto", "Helvetica Neue", Arial, sans-serif'
|
|
251
|
-
fontFamily: 'system-ui, -apple-system, sans-serif'
|
|
289
|
+
fontFamily: '"Inter", system-ui, sans-serif';
|
|
290
|
+
fontFamily: '"Roboto", "Helvetica Neue", Arial, sans-serif';
|
|
291
|
+
fontFamily: 'system-ui, -apple-system, sans-serif';
|
|
252
292
|
```
|
|
253
293
|
|
|
254
294
|
**Note:** When using Google Fonts or other web fonts, make sure to include the appropriate `<link>` tag in your HTML `<head>` section:
|
|
295
|
+
|
|
255
296
|
```html
|
|
256
297
|
<head>
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
298
|
+
<!-- For Google Fonts -->
|
|
299
|
+
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
300
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
|
301
|
+
<link
|
|
302
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
|
303
|
+
rel="stylesheet"
|
|
304
|
+
/>
|
|
305
|
+
|
|
306
|
+
<!-- Your chat bubble configuration -->
|
|
307
|
+
<script>
|
|
308
|
+
window.HEADWAI_CHAT_BUBBLE_CONFIG = {
|
|
309
|
+
// ... other config
|
|
310
|
+
fontFamily: '"Inter", system-ui, sans-serif',
|
|
311
|
+
};
|
|
312
|
+
</script>
|
|
269
313
|
</head>
|
|
270
314
|
```
|
|
271
315
|
|
|
272
316
|
#### `fontSize`
|
|
317
|
+
|
|
273
318
|
**Type:** `string` | **Default:** `'inherit'`
|
|
274
319
|
Font size used for all text in the chat interface. Accepts any valid CSS font-size value.
|
|
320
|
+
|
|
275
321
|
```javascript
|
|
276
|
-
fontSize: '16px'
|
|
277
|
-
fontSize: '1rem'
|
|
278
|
-
fontSize: '14px'
|
|
322
|
+
fontSize: '16px';
|
|
323
|
+
fontSize: '1rem';
|
|
324
|
+
fontSize: '14px';
|
|
279
325
|
```
|
|
280
326
|
|
|
281
327
|
### Data Attribute Format
|
|
@@ -294,10 +340,12 @@ When using data attributes for multiple chat bubbles, convert camelCase property
|
|
|
294
340
|
**CORS Errors**: Ensure your API endpoint allows requests from your domain
|
|
295
341
|
**Authentication Failures**: Verify your API key is correct and has proper permissions
|
|
296
342
|
**CDN Version Delays**: Sometimes the `@latest` tag on jsDelivr CDN takes time to propagate to all edge servers and may not deliver the newest version immediately. If you need the latest features or fixes, specify the exact version number instead of using `@latest`:
|
|
297
|
-
```html
|
|
298
|
-
<!-- Instead of @latest -->
|
|
299
|
-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.2.3/dist-widget/chat-bubble.css">
|
|
300
|
-
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.2.3/dist-widget/chat-bubble.js"></script>
|
|
301
|
-
```
|
|
302
|
-
|
|
303
343
|
|
|
344
|
+
```html
|
|
345
|
+
<!-- Instead of @latest -->
|
|
346
|
+
<link
|
|
347
|
+
rel="stylesheet"
|
|
348
|
+
href="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.2.3/dist-widget/chat-bubble.css"
|
|
349
|
+
/>
|
|
350
|
+
<script src="https://cdn.jsdelivr.net/npm/@headwai/chat-bubble@1.2.3/dist-widget/chat-bubble.js"></script>
|
|
351
|
+
```
|
|
@@ -276,7 +276,7 @@ new Remarkable().use(linkify)
|
|
|
276
276
|
|
|
277
277
|
${Array.from(e).sort((a,s)=>a-s).map(a=>{const o=r[a].name||"Untitled Reference";return`**[${a+1}]** ${o}`}).join(`
|
|
278
278
|
|
|
279
|
-
`)}`}function _c(r){if(!r||typeof r!="string")return r;const i=/\n\n---\n\n\*\*References:\*\*[\s\S]*$/;return r.replace(i,"").trim()}function Or(r){if(Z.group("Message History"),r.length===0){Z.log("No messages in history");return}r.forEach((i,t)=>{const e=i.content.length>50?i.content.substring(0,50)+"...":i.content;Z.log(`${t+1}. ${i.role.toUpperCase()}: ${e}`)})}const dt=[];function ot(r,i=ve){let t;const e=new Set;function n(o){if(rn(r,o)&&(r=o,t)){const l=!dt.length;for(const u of e)u[1](),dt.push(u,r);if(l){for(let u=0;u<dt.length;u+=2)dt[u][0](dt[u+1]);dt.length=0}}}function a(o){n(o(r))}function s(o,l=ve){const u=[o,l];return e.add(u),e.size===1&&(t=i(n,a)||ve),o(r),()=>{e.delete(u),e.size===0&&t&&(t(),t=null)}}return{set:n,update:a,subscribe:s}}const xn=ot(""),In=ot(""),Rn=ot([]),Ln=ot([]),On=ot(null),Pn=ot([]),qn=ot(!1);function Sc(r){let i,t,e,n,a,s,o,l,u,c,d,f,h,v,p,g,y,b,T,R,S;return{c(){i=ge("div"),t=ge("div"),e=ge("img"),a=mt(),s=ge("h3"),o=oi(r[1]),l=mt(),u=ge("div"),c=ge("button"),c.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>',d=mt(),f=ge("button"),h=un("svg"),v=un("path"),p=un("polyline"),g=un("line"),b=mt(),T=ge("button"),T.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>',Nn(e.src,n=r[0])||j(e,"src",n),j(e,"alt","Headwai Chat Bubble"),j(e,"class","chat-header-icon svelte-1dl0fot"),j(s,"class","chat-title svelte-1dl0fot"),vt(s,"font-family",r[2]),j(c,"class","chat-new-button svelte-1dl0fot"),j(c,"aria-label","Start new chat"),j(c,"title","Start new chat"),j(v,"d","M21 15V19A2 2 0 0 1 19 21H5A2 2 0 0 1 3 19V15"),j(v,"stroke","currentColor"),j(v,"stroke-width","2"),j(v,"stroke-linecap","round"),j(v,"stroke-linejoin","round"),j(p,"points","7,10 12,15 17,10"),j(p,"stroke","currentColor"),j(p,"stroke-width","2"),j(p,"stroke-linecap","round"),j(p,"stroke-linejoin","round"),j(g,"x1","12"),j(g,"y1","15"),j(g,"x2","12"),j(g,"y2","3"),j(g,"stroke","currentColor"),j(g,"stroke-width","2"),j(g,"stroke-linecap","round"),j(g,"stroke-linejoin","round"),j(h,"width","16"),j(h,"height","16"),j(h,"viewBox","0 0 24 24"),j(h,"fill","none"),j(h,"xmlns","http://www.w3.org/2000/svg"),j(f,"class","chat-download-button svelte-1dl0fot"),j(f,"aria-label","Download chat history"),j(f,"title","Download chat history"),f.disabled=y=!r[4]||r[5].length===0,j(T,"class","chat-close-button svelte-1dl0fot"),j(T,"aria-label","Close chat"),j(T,"title","Close chat"),j(u,"class","chat-header-buttons svelte-1dl0fot"),j(t,"class","chat-header-content svelte-1dl0fot"),j(i,"class","chat-header svelte-1dl0fot"),vt(i,"background",r[3])},m(C,P){an(C,i,P),ie(i,t),ie(t,e),ie(t,a),ie(t,s),ie(s,o),ie(t,l),ie(t,u),ie(u,c),ie(u,d),ie(u,f),ie(f,h),ie(h,v),ie(h,p),ie(h,g),ie(u,b),ie(u,T),R||(S=[He(c,"click",r[7]),He(c,"keydown",r[14]),He(f,"click",r[8]),He(f,"keydown",r[15]),He(T,"click",r[6]),He(T,"keydown",r[16])],R=!0)},p(C,[P]){P&1&&!Nn(e.src,n=C[0])&&j(e,"src",n),P&2&&hs(o,C[1]),P&4&&vt(s,"font-family",C[2]),P&48&&y!==(y=!C[4]||C[5].length===0)&&(f.disabled=y),P&8&&vt(i,"background",C[3])},i:ve,o:ve,d(C){C&&kt(i),R=!1,tt(S)}}}function Ec(r,i,t){let e,n;Ae(r,On,S=>t(4,e=S)),Ae(r,Pn,S=>t(5,n=S));let{iconPath:a}=i,{chatTitle:s}=i,{fontFamily:o}=i,{chatHeaderBackground:l}=i,{initialMessage:u}=i,{deepChatRef:c}=i,{modelId:d}=i,{apiUrl:f}=i,{apiKey:h}=i;function v(){qn.set(!1)}function p(){On.set(null),Pn.set([]),Ln.set([]),In.set(""),xn.set(""),Rn.set([]),g([{role:"assistant",content:u}]),c&&(c.clearMessages(),c.addMessage({text:u,role:"ai"},!1))}async function g(S){var C;try{const P=Math.floor(Date.now()/1e3),L=[d],H=[],I={};let x=null;S.forEach((ne,Y)=>{const ae=Xt(),fe=Y<S.length-1?Xt():null,ue={id:ae,parentId:x,childrenIds:fe?[fe]:[],role:ne.role,content:ne.content,timestamp:P,models:L};ne.role==="assistant"&&(ue.model=L[0],ue.modelId=L[0],ue.modelIdx=0),H.push(ue),I[ae]=ue,x=ae}),H.forEach((ne,Y)=>{Y<H.length-1&&(ne.childrenIds=[H[Y+1].id])});const A=(C=H[H.length-1])==null?void 0:C.id,D={chat:{id:"",title:"New Chatbubble Chat",models:L,params:{},history:{messages:I,currentId:A},messages:H,tags:[],timestamp:Date.now()},folder_id:null},W=`${f}/api/v1/chats/new`,ee=await fetch(W,{method:"POST",headers:{Authorization:`Bearer ${h}`,"Content-Type":"application/json"},body:JSON.stringify(D)});if(ee.ok){const ne=await ee.json();return On.set(ne.id),Z.log("New chat created with ID:",e),Pn.set(H),Or(n),e}else return Z.error("Failed to create new chat:",ee.statusText),null}catch{return null}}function y(){if(!e||c.getMessages().length===0)return;let S=`Chat ID: ${e}
|
|
279
|
+
`)}`}function _c(r){if(!r||typeof r!="string")return r;const i=/\n\n---\n\n\*\*References:\*\*[\s\S]*$/;return r.replace(i,"").trim()}function Or(r){if(Z.group("Message History"),r.length===0){Z.log("No messages in history");return}r.forEach((i,t)=>{const e=i.content.length>50?i.content.substring(0,50)+"...":i.content;Z.log(`${t+1}. ${i.role.toUpperCase()}: ${e}`)})}const dt=[];function ot(r,i=ve){let t;const e=new Set;function n(o){if(rn(r,o)&&(r=o,t)){const l=!dt.length;for(const u of e)u[1](),dt.push(u,r);if(l){for(let u=0;u<dt.length;u+=2)dt[u][0](dt[u+1]);dt.length=0}}}function a(o){n(o(r))}function s(o,l=ve){const u=[o,l];return e.add(u),e.size===1&&(t=i(n,a)||ve),o(r),()=>{e.delete(u),e.size===0&&t&&(t(),t=null)}}return{set:n,update:a,subscribe:s}}const xn=ot(""),In=ot(""),Rn=ot([]),Ln=ot([]),On=ot(null),Pn=ot([]),qn=ot(!1);function Sc(r){let i,t,e,n,a,s,o,l,u,c,d,f,h,v,p,g,y,b,T,R,S;return{c(){i=ge("div"),t=ge("div"),e=ge("img"),a=mt(),s=ge("h3"),o=oi(r[1]),l=mt(),u=ge("div"),c=ge("button"),c.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 5V19M5 12H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>',d=mt(),f=ge("button"),h=un("svg"),v=un("path"),p=un("polyline"),g=un("line"),b=mt(),T=ge("button"),T.innerHTML='<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M18 6L6 18M6 6L18 18" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>',Nn(e.src,n=r[0])||j(e,"src",n),j(e,"alt","Headwai Chat Bubble"),j(e,"class","chat-header-icon svelte-1dl0fot"),j(s,"class","chat-title svelte-1dl0fot"),vt(s,"font-family",r[2]),j(c,"class","chat-new-button svelte-1dl0fot"),j(c,"aria-label","Start new chat"),j(c,"title","Start new chat"),j(v,"d","M21 15V19A2 2 0 0 1 19 21H5A2 2 0 0 1 3 19V15"),j(v,"stroke","currentColor"),j(v,"stroke-width","2"),j(v,"stroke-linecap","round"),j(v,"stroke-linejoin","round"),j(p,"points","7,10 12,15 17,10"),j(p,"stroke","currentColor"),j(p,"stroke-width","2"),j(p,"stroke-linecap","round"),j(p,"stroke-linejoin","round"),j(g,"x1","12"),j(g,"y1","15"),j(g,"x2","12"),j(g,"y2","3"),j(g,"stroke","currentColor"),j(g,"stroke-width","2"),j(g,"stroke-linecap","round"),j(g,"stroke-linejoin","round"),j(h,"width","16"),j(h,"height","16"),j(h,"viewBox","0 0 24 24"),j(h,"fill","none"),j(h,"xmlns","http://www.w3.org/2000/svg"),j(f,"class","chat-download-button svelte-1dl0fot"),j(f,"aria-label","Download chat history"),j(f,"title","Download chat history"),f.disabled=y=!r[4]||r[5].length===0,j(T,"class","chat-close-button svelte-1dl0fot"),j(T,"aria-label","Close chat"),j(T,"title","Close chat"),j(u,"class","chat-header-buttons svelte-1dl0fot"),j(t,"class","chat-header-content svelte-1dl0fot"),j(i,"class","chat-header svelte-1dl0fot"),vt(i,"background",r[3])},m(C,P){an(C,i,P),ie(i,t),ie(t,e),ie(t,a),ie(t,s),ie(s,o),ie(t,l),ie(t,u),ie(u,c),ie(u,d),ie(u,f),ie(f,h),ie(h,v),ie(h,p),ie(h,g),ie(u,b),ie(u,T),R||(S=[He(c,"click",r[7]),He(c,"keydown",r[14]),He(f,"click",r[8]),He(f,"keydown",r[15]),He(T,"click",r[6]),He(T,"keydown",r[16])],R=!0)},p(C,[P]){P&1&&!Nn(e.src,n=C[0])&&j(e,"src",n),P&2&&hs(o,C[1]),P&4&&vt(s,"font-family",C[2]),P&48&&y!==(y=!C[4]||C[5].length===0)&&(f.disabled=y),P&8&&vt(i,"background",C[3])},i:ve,o:ve,d(C){C&&kt(i),R=!1,tt(S)}}}function Ec(r,i,t){let e,n;Ae(r,On,S=>t(4,e=S)),Ae(r,Pn,S=>t(5,n=S));let{iconPath:a}=i,{chatTitle:s}=i,{fontFamily:o}=i,{chatHeaderBackground:l}=i,{initialMessage:u}=i,{deepChatRef:c}=i,{modelId:d}=i,{apiUrl:f}=i,{apiKey:h}=i;function v(){qn.set(!1)}function p(){On.set(null),Pn.set([]),Ln.set([]),In.set(""),xn.set(""),Rn.set([]),g([{role:"assistant",content:u}]),c&&(c.clearMessages(),c.addMessage({text:u,role:"ai"},!1))}async function g(S){var C;try{const P=Math.floor(Date.now()/1e3),L=[d],H=[],I={};let x=null;S.forEach((ne,Y)=>{const ae=Xt(),fe=Y<S.length-1?Xt():null,ue={id:ae,parentId:x,childrenIds:fe?[fe]:[],role:ne.role,content:ne.content,timestamp:P,models:L};ne.role==="assistant"&&(ue.model=L[0],ue.modelId=L[0],ue.modelIdx=0),H.push(ue),I[ae]=ue,x=ae}),H.forEach((ne,Y)=>{Y<H.length-1&&(ne.childrenIds=[H[Y+1].id])});const A=(C=H[H.length-1])==null?void 0:C.id,D={chat:{id:"",title:"New Chatbubble Chat",models:L,params:{},history:{messages:I,currentId:A},messages:H,tags:[],timestamp:Date.now()},folder_id:null},W=`${f}/api/chat-bubble/v1/chats/new`,ee=await fetch(W,{method:"POST",headers:{Authorization:`Bearer ${h}`,"Content-Type":"application/json"},body:JSON.stringify(D)});if(ee.ok){const ne=await ee.json();return On.set(ne.id),Z.log("New chat created with ID:",e),Pn.set(H),Or(n),e}else return Z.error("Failed to create new chat:",ee.statusText),null}catch{return null}}function y(){if(!e||c.getMessages().length===0)return;let S=`Chat ID: ${e}
|
|
280
280
|
|
|
281
281
|
`;c.getMessages().forEach(H=>{if(Z.log("Processing message for download:",H),H.role!=="feedback"){const I=H.role.toUpperCase();if(Z.log(`Adding ${I} message to download content`),H.custom&&H.custom.timestamp){const x=new Date(H.custom.timestamp*1e3).toLocaleString();S+=`[${x}]
|
|
282
282
|
|
|
@@ -286,7 +286,7 @@ ${H.text}
|
|
|
286
286
|
`,Z.log(`Message timestamp: ${x}, content: ${S}`)}else S+=`[${I}]:
|
|
287
287
|
${H.text}
|
|
288
288
|
|
|
289
|
-
`,Z.log(`Message content: ${S}`)}});const C=new Blob([S],{type:"text/plain"}),P=URL.createObjectURL(C),L=document.createElement("a");L.href=P,L.download=`chat-history-${e}.txt`,document.body.appendChild(L),L.click(),document.body.removeChild(L),URL.revokeObjectURL(P),Z.log("Message history downloaded")}ps(()=>{p()});const b=S=>S.key==="Enter"&&p(),T=S=>S.key==="Enter"&&y(),R=S=>S.key==="Enter"&&v();return r.$$set=S=>{"iconPath"in S&&t(0,a=S.iconPath),"chatTitle"in S&&t(1,s=S.chatTitle),"fontFamily"in S&&t(2,o=S.fontFamily),"chatHeaderBackground"in S&&t(3,l=S.chatHeaderBackground),"initialMessage"in S&&t(9,u=S.initialMessage),"deepChatRef"in S&&t(10,c=S.deepChatRef),"modelId"in S&&t(11,d=S.modelId),"apiUrl"in S&&t(12,f=S.apiUrl),"apiKey"in S&&t(13,h=S.apiKey)},[a,s,o,l,e,n,v,p,y,u,c,d,f,h,b,T,R]}class wc extends zn{constructor(i){super(),Vn(this,i,Ec,Sc,rn,{iconPath:0,chatTitle:1,fontFamily:2,chatHeaderBackground:3,initialMessage:9,deepChatRef:10,modelId:11,apiUrl:12,apiKey:13})}}function Cc(r){let i,t,e,n,a;return{c(){i=ge("div"),t=ge("img"),Nn(t.src,e=r[1])||j(t,"src",e),j(t,"alt","Headwai Chat Bubble"),j(t,"class","svelte-15lda29"),j(i,"class","ai-assistant-icon svelte-15lda29"),vt(i,"background",r[0]),j(i,"role","button"),j(i,"tabindex","0")},m(s,o){an(s,i,o),ie(i,t),n||(a=[He(i,"click",r[2]),He(i,"keydown",r[3])],n=!0)},p(s,[o]){o&2&&!Nn(t.src,e=s[1])&&j(t,"src",e),o&1&&vt(i,"background",s[0])},i:ve,o:ve,d(s){s&&kt(i),n=!1,tt(a)}}}function Tc(r,i,t){let e;Ae(r,qn,l=>t(4,e=l));let{faviconBackgroundColor:n}=i,{iconPath:a}=i;function s(){qn.set(!e)}const o=l=>l.key==="Enter"&&s();return r.$$set=l=>{"faviconBackgroundColor"in l&&t(0,n=l.faviconBackgroundColor),"iconPath"in l&&t(1,a=l.iconPath)},[n,a,s,o]}class Ac extends zn{constructor(i){super(),Vn(this,i,Tc,Cc,rn,{faviconBackgroundColor:0,iconPath:1})}}function Mc(r){let i,t;return{c(){i=ge("div"),t=ge("deep-chat"),Oe(t,"demo","false"),Oe(t,"
|
|
289
|
+
`,Z.log(`Message content: ${S}`)}});const C=new Blob([S],{type:"text/plain"}),P=URL.createObjectURL(C),L=document.createElement("a");L.href=P,L.download=`chat-history-${e}.txt`,document.body.appendChild(L),L.click(),document.body.removeChild(L),URL.revokeObjectURL(P),Z.log("Message history downloaded")}ps(()=>{p()});const b=S=>S.key==="Enter"&&p(),T=S=>S.key==="Enter"&&y(),R=S=>S.key==="Enter"&&v();return r.$$set=S=>{"iconPath"in S&&t(0,a=S.iconPath),"chatTitle"in S&&t(1,s=S.chatTitle),"fontFamily"in S&&t(2,o=S.fontFamily),"chatHeaderBackground"in S&&t(3,l=S.chatHeaderBackground),"initialMessage"in S&&t(9,u=S.initialMessage),"deepChatRef"in S&&t(10,c=S.deepChatRef),"modelId"in S&&t(11,d=S.modelId),"apiUrl"in S&&t(12,f=S.apiUrl),"apiKey"in S&&t(13,h=S.apiKey)},[a,s,o,l,e,n,v,p,y,u,c,d,f,h,b,T,R]}class wc extends zn{constructor(i){super(),Vn(this,i,Ec,Sc,rn,{iconPath:0,chatTitle:1,fontFamily:2,chatHeaderBackground:3,initialMessage:9,deepChatRef:10,modelId:11,apiUrl:12,apiKey:13})}}function Cc(r){let i,t,e,n,a;return{c(){i=ge("div"),t=ge("img"),Nn(t.src,e=r[1])||j(t,"src",e),j(t,"alt","Headwai Chat Bubble"),j(t,"class","svelte-15lda29"),j(i,"class","ai-assistant-icon svelte-15lda29"),vt(i,"background",r[0]),j(i,"role","button"),j(i,"tabindex","0")},m(s,o){an(s,i,o),ie(i,t),n||(a=[He(i,"click",r[2]),He(i,"keydown",r[3])],n=!0)},p(s,[o]){o&2&&!Nn(t.src,e=s[1])&&j(t,"src",e),o&1&&vt(i,"background",s[0])},i:ve,o:ve,d(s){s&&kt(i),n=!1,tt(a)}}}function Tc(r,i,t){let e;Ae(r,qn,l=>t(4,e=l));let{faviconBackgroundColor:n}=i,{iconPath:a}=i;function s(){qn.set(!e)}const o=l=>l.key==="Enter"&&s();return r.$$set=l=>{"faviconBackgroundColor"in l&&t(0,n=l.faviconBackgroundColor),"iconPath"in l&&t(1,a=l.iconPath)},[n,a,s,o]}class Ac extends zn{constructor(i){super(),Vn(this,i,Tc,Cc,rn,{faviconBackgroundColor:0,iconPath:1})}}function Mc(r){let i,t;return{c(){i=ge("div"),t=ge("deep-chat"),Oe(t,"demo","false"),Oe(t,"textInput",r[1]),Oe(t,"messageStyles",r[2]),Oe(t,"history",r[3]),Oe(t,"connect",r[4]),Oe(t,"requestBodyLimits",r[5]),Oe(t,"requestInterceptor",r[6]),Oe(t,"responseInterceptor",r[7]),Oe(t,"onMessage",r[8]),j(i,"class","chat-content svelte-i2r2w9")},m(e,n){an(e,i,n),ie(i,t),r[23](t)},p:ve,i:ve,o:ve,d(e){e&&kt(i),r[23](null)}}}function xc(r){return r.map(i=>{let t=i.text||i.content;return{role:i.role==="ai"?"assistant":i.role,content:t}})}function Ic(r,i,t){let e,n,a,s,o,l;Ae(r,Pn,M=>t(24,e=M)),Ae(r,On,M=>t(25,n=M)),Ae(r,Rn,M=>t(26,a=M)),Ae(r,In,M=>t(27,s=M)),Ae(r,xn,M=>t(28,o=M)),Ae(r,Ln,M=>t(29,l=M));let{deepChatRef:u}=i,{placeholderText:c}=i,{fontFamily:d}=i,{fontSize:f}=i,{userMessageBackgroundColor:h}=i,{userMessageTextColor:v}=i,{aiMessageBackgroundColor:p}=i,{aiMessageTextColor:g}=i,{feedbackMessageBackgroundColor:y}=i,{feedbackMessageTextColor:b}=i,{initialMessage:T}=i,{apiUrl:R}=i,{apiKey:S}=i,{modelId:C}=i,{maxMessages:P}=i;const L={placeholder:{text:c},styles:{container:{fontFamily:d,fontSize:f}}},H={default:{shared:{bubble:{fontFamily:d,fontSize:f}},user:{bubble:{backgroundColor:h,color:v}},ai:{bubble:{backgroundColor:p,color:g}},feedback:{bubble:{backgroundColor:y,color:b}}}},I=[{role:"ai",text:T,custom:{timestamp:Math.floor(Date.now()/1e3)}}],x={type:"websocket",url:`${R}/api/chat-bubble/chat/completions`,headers:{Authorization:`Bearer ${S}`,"Content-Type":"application/json"},additionalBodyProps:{model:C,stream:!0,params:{},tool_servers:[],features:{image_generation:!1,code_interpreter:!1,web_search:!1,memory:!1},variables:{"{{USER_NAME}}":"David Schneebauer | headwAI GmbH","{{USER_LOCATION}}":"Unknown","{{CURRENT_DATETIME}}":new Date().toISOString().slice(0,19).replace("T"," "),"{{CURRENT_DATE}}":new Date().toISOString().slice(0,10),"{{CURRENT_TIME}}":new Date().toTimeString().slice(0,8),"{{CURRENT_WEEKDAY}}":new Date().toLocaleDateString("en-US",{weekday:"long"}),"{{CURRENT_TIMEZONE}}":Intl.DateTimeFormat().resolvedOptions().timeZone,"{{USER_LANGUAGE}}":"en-GB"},...n&&{chat_id:n},background_tasks:{title_generation:!0,tags_generation:!1,follow_up_generation:!1}},stream:!0},A={maxMessages:P},D=async M=>{if(M.body&&M.body.messages){M.body.messages=xc(M.body.messages).map(J=>(J.role==="assistant"&&J.content&&(J.content=_c(J.content)),J)),M.body.messages=M.body.messages.filter(J=>J.role!=="feedback");const K=M.body.messages.filter(J=>J.role==="user");K.length>0&&xn.set(K[K.length-1].content),n&&(M.body.chat_id=n)}return M},w=M=>{Z.log(M),M.sources&&Array.isArray(M.sources)&&(Rn.set(M.sources),Z.log(`Found ${M.sources.length} sources in response`),Z.log("assistantMessageSources:",M.sources));try{const K=bc(M);K.length>0&&(Ln.set(K),Z.log(`Found ${K.length} references in response`))}catch{}if(M.choices&&M.choices[0]&&M.choices[0].delta){const K=M.choices[0].delta,J=K.content||"";return J&&In.update(te=>te+J),M.choices[0].finish_reason&&Z.log("Streaming response ended"),{text:J,role:K.role==="assistant"?"ai":K.role||"ai"}}if(M.choices&&M.choices[0]&&M.choices[0].message){const K=M.choices[0].message;return Z.log("Non-streaming response received"),{text:K.content,role:K.role==="assistant"?"ai":K.role}}return M.text||M.html||M.files?M:typeof M=="string"?{text:M}:M};async function W(M){const{message:K,isHistory:J}=M;if(Z.log(M),!J&&(K.role==="ai"||K.role==="assistant")){Z.log("🤖 AI answered:",K.text);const te=K.text||"";let _e=te;if(l.length>0&&u){Z.log("📚 Formatting and updating AI message with references");const Le=kc(l,te);_e=te+Le,Le?(Z.log("Found inline citations, adding references"),u.updateMessage({text:_e},u.getMessages().length-1)):Z.log("No inline citations found, skipping references")}u.scrollToBottom(),ee(o,s,a);const he=e.filter(Le=>Le.role==="assistant").pop();Z.log("Last assistant message:",he);const Se=he?he.id:Xt();Z.log("Using assistant message ID for feedback:",Se);const Te=u.getMessages().length;u.addMessage({html:`
|
|
290
290
|
<div class="feedback">
|
|
291
291
|
<div class="feedback-icons">
|
|
292
292
|
<span class="feedback-icon feedback-icon-positive" title="Good response" onclick="window.handleFeedback('${Se}', 'positive', '${Te}')" style="cursor: pointer;">
|
|
@@ -325,7 +325,7 @@ ${H.text}
|
|
|
325
325
|
</span>
|
|
326
326
|
</div>
|
|
327
327
|
</div>
|
|
328
|
-
`,role:"feedback"}),xn.set(""),In.set(""),Rn.set([]),Ln.set([])}}async function ee(M,K,J){if(n){Z.log("assistantMessageSources:",J);try{const te=Math.floor(Date.now()/1e3),_e=[C],he=Xt(),Se=Xt(),Te=e[e.length-1],Le={id:he,parentId:Te?Te.id:null,childrenIds:[Se],role:"user",content:M,timestamp:te,models:_e},lt={id:Se,parentId:he,childrenIds:[],role:"assistant",content:K,model:_e[0],modelId:_e[0],modelIdx:0,timestamp:te,sources:J};Te&&(Te.childrenIds=[he]),e.push(Le,lt);const Ce={};e.forEach($r=>{Ce[$r.id]=$r});const Ee={chat:{models:_e,history:{messages:Ce,currentId:Se},messages:e,params:{}}},ss=`${R}/api/v1/chats/${n}`,Qr=await fetch(ss,{method:"POST",headers:{Authorization:`Bearer ${S}`,"Content-Type":"application/json"},body:JSON.stringify(Ee)});Qr.ok?(Z.log("Chat history stored successfully"),Or(e)):Z.error("Failed to store chat history:",Qr.statusText)}catch{}}}async function ne(M,K,J){ae(M,K,J),Z.log(`Feedback recorded for message ${M}: ${K}`);const _e=await Y(M,K==="positive"?1:-1);await fe(M,_e)}async function Y(M,K){var J;try{if(!n){Z.error("Cannot send feedback: no chat ID available");return}if(!e.find(Ee=>Ee.id===M)){Z.error(`Message not found in history for feedback ID: ${M}`);return}const _e=e.findIndex(Ee=>Ee.id===M),he=C,Se={type:"rating",data:{rating:K,model_id:he},meta:{model_id:he,message_id:M,message_index:_e,chat_id:n,base_models:{[he]:he}},snapshot:{chat:{id:n,user_id:null,title:"New Chatbubble Chat",chat:{id:"",title:"New Chatbubble Chat",models:[he],params:{},history:{messages:{},currentId:M},messages:e,params:{}},updated_at:Date.now(),created_at:Date.now(),share_id:null,archived:!1,pinned:!1,meta:{},folder_id:null}}},Te={};e.forEach(Ee=>{Te[Ee.id]=Ee}),Se.snapshot.chat.chat.history.messages=Te,Se.snapshot.chat.chat.history.currentId=(J=e[e.length-1])==null?void 0:J.id;const lt=`${R}/api/v1/evaluations/feedback`,Ce=await fetch(lt,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify(Se)});if(Ce.ok){const Ee=await Ce.json();return Z.log("Feedback sent successfully:",Ee),Ee}else{const Ee=await Ce.json().catch(()=>null);Z.error("Failed to send feedback:",Ce.statusText,Ee)}}catch{}return null}function ae(M,K,J){Z.log(M,K,J),K==="positive"?u.updateMessage({html:`
|
|
328
|
+
`,role:"feedback"}),xn.set(""),In.set(""),Rn.set([]),Ln.set([])}}async function ee(M,K,J){if(n){Z.log("assistantMessageSources:",J);try{const te=Math.floor(Date.now()/1e3),_e=[C],he=Xt(),Se=Xt(),Te=e[e.length-1],Le={id:he,parentId:Te?Te.id:null,childrenIds:[Se],role:"user",content:M,timestamp:te,models:_e},lt={id:Se,parentId:he,childrenIds:[],role:"assistant",content:K,model:_e[0],modelId:_e[0],modelIdx:0,timestamp:te,sources:J};Te&&(Te.childrenIds=[he]),e.push(Le,lt);const Ce={};e.forEach($r=>{Ce[$r.id]=$r});const Ee={chat:{models:_e,history:{messages:Ce,currentId:Se},messages:e,params:{}}},ss=`${R}/api/chat-bubble/v1/chats/${n}`,Qr=await fetch(ss,{method:"POST",headers:{Authorization:`Bearer ${S}`,"Content-Type":"application/json"},body:JSON.stringify(Ee)});Qr.ok?(Z.log("Chat history stored successfully"),Or(e)):Z.error("Failed to store chat history:",Qr.statusText)}catch{}}}async function ne(M,K,J){ae(M,K,J),Z.log(`Feedback recorded for message ${M}: ${K}`);const _e=await Y(M,K==="positive"?1:-1);await fe(M,_e)}async function Y(M,K){var J;try{if(!n){Z.error("Cannot send feedback: no chat ID available");return}if(!e.find(Ee=>Ee.id===M)){Z.error(`Message not found in history for feedback ID: ${M}`);return}const _e=e.findIndex(Ee=>Ee.id===M),he=C,Se={type:"rating",data:{rating:K,model_id:he},meta:{model_id:he,message_id:M,message_index:_e,chat_id:n,base_models:{[he]:he}},snapshot:{chat:{id:n,user_id:null,title:"New Chatbubble Chat",chat:{id:"",title:"New Chatbubble Chat",models:[he],params:{},history:{messages:{},currentId:M},messages:e,params:{}},updated_at:Date.now(),created_at:Date.now(),share_id:null,archived:!1,pinned:!1,meta:{},folder_id:null}}},Te={};e.forEach(Ee=>{Te[Ee.id]=Ee}),Se.snapshot.chat.chat.history.messages=Te,Se.snapshot.chat.chat.history.currentId=(J=e[e.length-1])==null?void 0:J.id;const lt=`${R}/api/chat-bubble/v1/evaluations/feedback`,Ce=await fetch(lt,{method:"POST",headers:{Accept:"application/json","Content-Type":"application/json",Authorization:`Bearer ${S}`},body:JSON.stringify(Se)});if(Ce.ok){const Ee=await Ce.json();return Z.log("Feedback sent successfully:",Ee),Ee}else{const Ee=await Ce.json().catch(()=>null);Z.error("Failed to send feedback:",Ce.statusText,Ee)}}catch{}return null}function ae(M,K,J){Z.log(M,K,J),K==="positive"?u.updateMessage({html:`
|
|
329
329
|
<div class="feedback">
|
|
330
330
|
<div class="feedback-icons">
|
|
331
331
|
<span class="feedback-icon feedback-icon-positive" title="Good response" onclick="window.handleFeedback('${M}', 'positive', ${J})" style="cursor: pointer;">
|
|
@@ -403,4 +403,4 @@ ${H.text}
|
|
|
403
403
|
</span>
|
|
404
404
|
</div>
|
|
405
405
|
</div>
|
|
406
|
-
`,role:"feedback"},J)}async function fe(M,K){if(!(!n||!K||!M||(e.forEach(te=>{te.id===M&&te.role==="assistant"&&(te.feedbackId=K.id,te.annotation={rating:K.data.rating})}),!e.find(te=>te.id===M))))try{const te=e.filter(Ce=>Ce.role==="assistant");if(te.length===0){Z.error("No assistant messages found to update with feedback");return}const _e=te[te.length-1],he={};e.forEach(Ce=>{he[Ce.id]=Ce});const Se={chat:{models:[C],history:{messages:he,currentId:_e.id},messages:e,params:{}}},Le=`${R}/api/v1/chats/${n}`,lt=await fetch(Le,{method:"POST",headers:{Authorization:`Bearer ${S}`,"Content-Type":"application/json"},body:JSON.stringify(Se)});lt.ok?(Z.log("Assistant message updated with feedback successfully"),Or(e)):Z.error("Failed to update assistant message with feedback:",lt.statusText)}catch{}}typeof window<"u"&&(window.handleFeedback=ne);function ue(M){Bn[M?"unshift":"push"](()=>{u=M,t(0,u)})}return r.$$set=M=>{"deepChatRef"in M&&t(0,u=M.deepChatRef),"placeholderText"in M&&t(9,c=M.placeholderText),"fontFamily"in M&&t(10,d=M.fontFamily),"fontSize"in M&&t(11,f=M.fontSize),"userMessageBackgroundColor"in M&&t(12,h=M.userMessageBackgroundColor),"userMessageTextColor"in M&&t(13,v=M.userMessageTextColor),"aiMessageBackgroundColor"in M&&t(14,p=M.aiMessageBackgroundColor),"aiMessageTextColor"in M&&t(15,g=M.aiMessageTextColor),"feedbackMessageBackgroundColor"in M&&t(16,y=M.feedbackMessageBackgroundColor),"feedbackMessageTextColor"in M&&t(17,b=M.feedbackMessageTextColor),"initialMessage"in M&&t(18,T=M.initialMessage),"apiUrl"in M&&t(19,R=M.apiUrl),"apiKey"in M&&t(20,S=M.apiKey),"modelId"in M&&t(21,C=M.modelId),"maxMessages"in M&&t(22,P=M.maxMessages)},[u,L,H,I,x,A,D,w,W,c,d,f,h,v,p,g,y,b,T,R,S,C,P,ue]}class Rc extends zn{constructor(i){super(),Vn(this,i,Ic,Mc,rn,{deepChatRef:0,placeholderText:9,fontFamily:10,fontSize:11,userMessageBackgroundColor:12,userMessageTextColor:13,aiMessageBackgroundColor:14,aiMessageTextColor:15,feedbackMessageBackgroundColor:16,feedbackMessageTextColor:17,initialMessage:18,apiUrl:19,apiKey:20,modelId:21,maxMessages:22},null,[-1,-1])}}function ri(r){let i,t;return i=new Ac({props:{faviconBackgroundColor:r[15],iconPath:r[13]}}),{c(){ur(i.$$.fragment)},m(e,n){Dn(i,e,n),t=!0},p:ve,i(e){t||(Me(i.$$.fragment,e),t=!0)},o(e){Je(i.$$.fragment,e),t=!1},d(e){Fn(i,e)}}}function ai(r){let i,t,e,n,a,s;t=new wc({props:{iconPath:r[13],chatTitle:r[9]||void 0||"Headwai Chat Bubble",fontFamily:r[14],chatHeaderBackground:r[15],initialMessage:r[12],deepChatRef:r[10],modelId:r[16],apiUrl:r[17],apiKey:r[18]}});function o(u){r[26](u)}let l={placeholderText:r[1]||
|
|
406
|
+
`,role:"feedback"},J)}async function fe(M,K){if(!(!n||!K||!M||(e.forEach(te=>{te.id===M&&te.role==="assistant"&&(te.feedbackId=K.id,te.annotation={rating:K.data.rating})}),!e.find(te=>te.id===M))))try{const te=e.filter(Ce=>Ce.role==="assistant");if(te.length===0){Z.error("No assistant messages found to update with feedback");return}const _e=te[te.length-1],he={};e.forEach(Ce=>{he[Ce.id]=Ce});const Se={chat:{models:[C],history:{messages:he,currentId:_e.id},messages:e,params:{}}},Le=`${R}/api/chat-bubble/v1/chats/${n}`,lt=await fetch(Le,{method:"POST",headers:{Authorization:`Bearer ${S}`,"Content-Type":"application/json"},body:JSON.stringify(Se)});lt.ok?(Z.log("Assistant message updated with feedback successfully"),Or(e)):Z.error("Failed to update assistant message with feedback:",lt.statusText)}catch{}}typeof window<"u"&&(window.handleFeedback=ne);function ue(M){Bn[M?"unshift":"push"](()=>{u=M,t(0,u)})}return r.$$set=M=>{"deepChatRef"in M&&t(0,u=M.deepChatRef),"placeholderText"in M&&t(9,c=M.placeholderText),"fontFamily"in M&&t(10,d=M.fontFamily),"fontSize"in M&&t(11,f=M.fontSize),"userMessageBackgroundColor"in M&&t(12,h=M.userMessageBackgroundColor),"userMessageTextColor"in M&&t(13,v=M.userMessageTextColor),"aiMessageBackgroundColor"in M&&t(14,p=M.aiMessageBackgroundColor),"aiMessageTextColor"in M&&t(15,g=M.aiMessageTextColor),"feedbackMessageBackgroundColor"in M&&t(16,y=M.feedbackMessageBackgroundColor),"feedbackMessageTextColor"in M&&t(17,b=M.feedbackMessageTextColor),"initialMessage"in M&&t(18,T=M.initialMessage),"apiUrl"in M&&t(19,R=M.apiUrl),"apiKey"in M&&t(20,S=M.apiKey),"modelId"in M&&t(21,C=M.modelId),"maxMessages"in M&&t(22,P=M.maxMessages)},[u,L,H,I,x,A,D,w,W,c,d,f,h,v,p,g,y,b,T,R,S,C,P,ue]}class Rc extends zn{constructor(i){super(),Vn(this,i,Ic,Mc,rn,{deepChatRef:0,placeholderText:9,fontFamily:10,fontSize:11,userMessageBackgroundColor:12,userMessageTextColor:13,aiMessageBackgroundColor:14,aiMessageTextColor:15,feedbackMessageBackgroundColor:16,feedbackMessageTextColor:17,initialMessage:18,apiUrl:19,apiKey:20,modelId:21,maxMessages:22},null,[-1,-1])}}function ri(r){let i,t;return i=new Ac({props:{faviconBackgroundColor:r[15],iconPath:r[13]}}),{c(){ur(i.$$.fragment)},m(e,n){Dn(i,e,n),t=!0},p:ve,i(e){t||(Me(i.$$.fragment,e),t=!0)},o(e){Je(i.$$.fragment,e),t=!1},d(e){Fn(i,e)}}}function ai(r){let i,t,e,n,a,s;t=new wc({props:{iconPath:r[13],chatTitle:r[9]||void 0||"Headwai Chat Bubble",fontFamily:r[14],chatHeaderBackground:r[15],initialMessage:r[12],deepChatRef:r[10],modelId:r[16],apiUrl:r[17],apiKey:r[18]}});function o(u){r[26](u)}let l={placeholderText:r[1]||"Welcome to the demo!",fontFamily:r[14],fontSize:r[8]||"16px",userMessageBackgroundColor:r[2]||void 0||"#007bff",userMessageTextColor:r[4]||void 0||"#000000",aiMessageBackgroundColor:r[3]||void 0||"#f1f3f4",aiMessageTextColor:r[5]||void 0||"#000000",feedbackMessageBackgroundColor:r[6]||void 0||"#ffffff",feedbackMessageTextColor:r[7]||void 0||"#000000",initialMessage:r[12],apiUrl:r[17],apiKey:r[18],modelId:r[16],maxMessages:parseInt(r[0]||void 0)||0};return r[10]!==void 0&&(l.deepChatRef=r[10]),n=new Rc({props:l}),Bn.push(()=>ks(n,"deepChatRef",o)),{c(){i=ge("div"),ur(t.$$.fragment),e=mt(),ur(n.$$.fragment),j(i,"class","chat-container svelte-hopfzj")},m(u,c){an(u,i,c),Dn(t,i,null),ie(i,e),Dn(n,i,null),s=!0},p(u,c){const d={};c&512&&(d.chatTitle=u[9]||void 0||"Headwai Chat Bubble"),c&1024&&(d.deepChatRef=u[10]),t.$set(d);const f={};c&2&&(f.placeholderText=u[1]||"Welcome to the demo!"),c&256&&(f.fontSize=u[8]||"16px"),c&4&&(f.userMessageBackgroundColor=u[2]||void 0||"#007bff"),c&16&&(f.userMessageTextColor=u[4]||void 0||"#000000"),c&8&&(f.aiMessageBackgroundColor=u[3]||void 0||"#f1f3f4"),c&32&&(f.aiMessageTextColor=u[5]||void 0||"#000000"),c&64&&(f.feedbackMessageBackgroundColor=u[6]||void 0||"#ffffff"),c&128&&(f.feedbackMessageTextColor=u[7]||void 0||"#000000"),c&1&&(f.maxMessages=parseInt(u[0]||void 0)||0),!a&&c&1024&&(a=!0,f.deepChatRef=u[10],gs(()=>a=!1)),n.$set(f)},i(u){s||(Me(t.$$.fragment,u),Me(n.$$.fragment,u),s=!0)},o(u){Je(t.$$.fragment,u),Je(n.$$.fragment,u),s=!1},d(u){u&&kt(i),Fn(t),Fn(n)}}}function Lc(r){let i,t,e,n=!r[11]&&ri(r),a=r[11]&&ai(r);return{c(){i=ge("main"),n&&n.c(),t=mt(),a&&a.c(),j(i,"class","svelte-hopfzj")},m(s,o){an(s,i,o),n&&n.m(i,null),ie(i,t),a&&a.m(i,null),e=!0},p(s,[o]){s[11]?n&&(ta(),Je(n,1,1,()=>{n=null}),na()):n?(n.p(s,o),o&2048&&Me(n,1)):(n=ri(s),n.c(),Me(n,1),n.m(i,t)),s[11]?a?(a.p(s,o),o&2048&&Me(a,1)):(a=ai(s),a.c(),Me(a,1),a.m(i,null)):a&&(ta(),Je(a,1,1,()=>{a=null}),na())},i(s){e||(Me(n),Me(a),e=!0)},o(s){Je(n),Je(a),e=!1},d(s){s&&kt(i),n&&n.d(),a&&a.d()}}}function Oc(r,i,t){let e;Ae(r,qn,w=>t(11,e=w));let{apiUrl:n=void 0}=i,{apiKey:a=void 0}=i,{modelId:s=void 0}=i,{maxMessages:o=void 0}=i,{placeholderText:l=void 0}=i,{faviconPath:u=void 0}=i,{initialMessage:c=void 0}=i,{userMessageBackgroundColor:d=void 0}=i,{aiMessageBackgroundColor:f=void 0}=i,{userMessageTextColor:h=void 0}=i,{aiMessageTextColor:v=void 0}=i,{feedbackMessageBackgroundColor:p=void 0}=i,{feedbackMessageTextColor:g=void 0}=i,{faviconBackgroundColor:y=void 0}=i,{fontFamily:b=void 0}=i,{fontSize:T=void 0}=i,{chatTitle:R=void 0}=i,S;const C=c||void 0||"Hey, how can I help you?",P=u||void 0||yc,L=b||'"Bitcount Grid Double", system-ui',H=y||void 0||"#667eea",I=s||"test-model",x=(n||"https://localhost").replace(/\/$/,""),A=a||"123";function D(w){S=w,t(10,S)}return r.$$set=w=>{"apiUrl"in w&&t(19,n=w.apiUrl),"apiKey"in w&&t(20,a=w.apiKey),"modelId"in w&&t(21,s=w.modelId),"maxMessages"in w&&t(0,o=w.maxMessages),"placeholderText"in w&&t(1,l=w.placeholderText),"faviconPath"in w&&t(22,u=w.faviconPath),"initialMessage"in w&&t(23,c=w.initialMessage),"userMessageBackgroundColor"in w&&t(2,d=w.userMessageBackgroundColor),"aiMessageBackgroundColor"in w&&t(3,f=w.aiMessageBackgroundColor),"userMessageTextColor"in w&&t(4,h=w.userMessageTextColor),"aiMessageTextColor"in w&&t(5,v=w.aiMessageTextColor),"feedbackMessageBackgroundColor"in w&&t(6,p=w.feedbackMessageBackgroundColor),"feedbackMessageTextColor"in w&&t(7,g=w.feedbackMessageTextColor),"faviconBackgroundColor"in w&&t(24,y=w.faviconBackgroundColor),"fontFamily"in w&&t(25,b=w.fontFamily),"fontSize"in w&&t(8,T=w.fontSize),"chatTitle"in w&&t(9,R=w.chatTitle)},[o,l,d,f,h,v,p,g,T,R,S,e,C,P,L,H,I,x,A,n,a,s,u,c,y,b,D]}class Pr extends zn{constructor(i){super(),Vn(this,i,Oc,Lc,rn,{apiUrl:19,apiKey:20,modelId:21,maxMessages:0,placeholderText:1,faviconPath:22,initialMessage:23,userMessageBackgroundColor:2,aiMessageBackgroundColor:3,userMessageTextColor:4,aiMessageTextColor:5,feedbackMessageBackgroundColor:6,feedbackMessageTextColor:7,faviconBackgroundColor:24,fontFamily:25,fontSize:8,chatTitle:9})}}function is(){const r={apiUrl:"https://localhost",apiKey:"123",modelId:"test-model",maxMessages:void 0,placeholderText:"Welcome to the demo!",userMessageBackgroundColor:void 0,aiMessageBackgroundColor:void 0,userMessageTextColor:void 0,aiMessageTextColor:void 0,faviconBackgroundColor:void 0,chatTitle:void 0},i=typeof window<"u"&&window.HEADWAI_CHAT_BUBBLE_CONFIG||{};return{...r,...i}}typeof window<"u"&&window.document&&document.addEventListener("DOMContentLoaded",()=>{const r=is(),i=document.querySelectorAll("[data-chat-bubble]");if(i.length===0){const t=document.getElementById("chat-bubble-container");t&&new Pr({target:t,props:r})}else i.forEach(t=>{const e={...r},n={chatBubbleApiUrl:"apiUrl",chatBubbleApiKey:"apiKey",chatBubbleModelId:"modelId",chatBubbleMaxMessages:"maxMessages",chatBubblePlaceholderText:"placeholderText",chatBubbleFaviconPath:"faviconPath",chatBubbleInitialMessage:"initialMessage",chatBubbleUserMessageBackgroundColor:"userMessageBackgroundColor",chatBubbleAiMessageBackgroundColor:"aiMessageBackgroundColor",chatBubbleUserMessageTextColor:"userMessageTextColor",chatBubbleAiMessageTextColor:"aiMessageTextColor",chatBubbleFaviconBackgroundColor:"faviconBackgroundColor",chatBubbleChatTitle:"chatTitle"};Object.keys(t.dataset).forEach(a=>{n[a]&&(e[n[a]]=t.dataset[a])}),new Pr({target:t,props:e})})});window.ChatBubble={init:(r,i={})=>new Pr({target:r,props:{...is(),...i}})};
|