@a.izzuddin/ai-chat 0.2.2 → 0.2.4

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.
@@ -66,12 +66,6 @@
66
66
  }
67
67
  ]
68
68
  },
69
- {
70
- "kind": "javascript-module",
71
- "path": "dist/index.js",
72
- "declarations": [],
73
- "exports": []
74
- },
75
69
  {
76
70
  "kind": "javascript-module",
77
71
  "path": "examples/angular.component.ts",
@@ -162,6 +156,18 @@
162
156
  }
163
157
  ]
164
158
  },
159
+ {
160
+ "kind": "javascript-module",
161
+ "path": "dist/index.js",
162
+ "declarations": [
163
+ {
164
+ "kind": "variable",
165
+ "name": "faqs",
166
+ "default": "void 0"
167
+ }
168
+ ],
169
+ "exports": []
170
+ },
165
171
  {
166
172
  "kind": "javascript-module",
167
173
  "path": "lib/utils.ts",
@@ -213,6 +219,12 @@
213
219
  }
214
220
  ]
215
221
  },
222
+ {
223
+ "kind": "javascript-module",
224
+ "path": "tests/chat.spec.ts",
225
+ "declarations": [],
226
+ "exports": []
227
+ },
216
228
  {
217
229
  "kind": "javascript-module",
218
230
  "path": "tests/web-component.spec.ts",
@@ -549,6 +561,26 @@
549
561
  "default": "[]",
550
562
  "attribute": "initialMessages"
551
563
  },
564
+ {
565
+ "kind": "field",
566
+ "name": "botAvatarUrl",
567
+ "privacy": "public",
568
+ "type": {
569
+ "text": "string"
570
+ },
571
+ "default": "''",
572
+ "attribute": "bot-avatar-url"
573
+ },
574
+ {
575
+ "kind": "field",
576
+ "name": "backgroundImageUrl",
577
+ "privacy": "public",
578
+ "type": {
579
+ "text": "string"
580
+ },
581
+ "default": "''",
582
+ "attribute": "background-image-url"
583
+ },
552
584
  {
553
585
  "kind": "field",
554
586
  "name": "messages",
@@ -616,6 +648,19 @@
616
648
  }
617
649
  ]
618
650
  },
651
+ {
652
+ "kind": "method",
653
+ "name": "handleFAQClick",
654
+ "privacy": "private",
655
+ "parameters": [
656
+ {
657
+ "name": "question",
658
+ "type": {
659
+ "text": "string"
660
+ }
661
+ }
662
+ ]
663
+ },
619
664
  {
620
665
  "kind": "method",
621
666
  "name": "handleSubmit",
@@ -706,6 +751,22 @@
706
751
  },
707
752
  "default": "[]",
708
753
  "fieldName": "initialMessages"
754
+ },
755
+ {
756
+ "name": "bot-avatar-url",
757
+ "type": {
758
+ "text": "string"
759
+ },
760
+ "default": "''",
761
+ "fieldName": "botAvatarUrl"
762
+ },
763
+ {
764
+ "name": "background-image-url",
765
+ "type": {
766
+ "text": "string"
767
+ },
768
+ "default": "''",
769
+ "fieldName": "backgroundImageUrl"
709
770
  }
710
771
  ],
711
772
  "superclass": {
package/dist/index.d.mts CHANGED
@@ -2,10 +2,15 @@ import * as lit_html from 'lit-html';
2
2
  import * as lit from 'lit';
3
3
  import { LitElement, PropertyValues } from 'lit';
4
4
 
5
+ interface FAQ {
6
+ "no.": string;
7
+ question: string;
8
+ }
5
9
  interface Message {
6
10
  id: string;
7
11
  role: 'user' | 'assistant';
8
12
  content: string;
13
+ faqs?: FAQ[];
9
14
  }
10
15
  /**
11
16
  * AI Chat Web Component
@@ -31,6 +36,8 @@ declare class AIChat extends LitElement {
31
36
  theme: 'light' | 'dark';
32
37
  mode: 'fullscreen' | 'widget';
33
38
  initialMessages: Message[];
39
+ botAvatarUrl: string;
40
+ backgroundImageUrl: string;
34
41
  private messages;
35
42
  private input;
36
43
  private isLoading;
@@ -59,6 +66,14 @@ declare class AIChat extends LitElement {
59
66
  initialMessages: {
60
67
  type: ArrayConstructor;
61
68
  };
69
+ botAvatarUrl: {
70
+ type: StringConstructor;
71
+ attribute: string;
72
+ };
73
+ backgroundImageUrl: {
74
+ type: StringConstructor;
75
+ attribute: string;
76
+ };
62
77
  };
63
78
  constructor();
64
79
  private toggleWidget;
@@ -66,6 +81,7 @@ declare class AIChat extends LitElement {
66
81
  updated(changedProperties: PropertyValues): void;
67
82
  private scrollToBottom;
68
83
  private handleInput;
84
+ private handleFAQClick;
69
85
  private handleSubmit;
70
86
  private renderChatUI;
71
87
  render(): lit_html.TemplateResult<1>;
package/dist/index.d.ts CHANGED
@@ -2,10 +2,15 @@ import * as lit_html from 'lit-html';
2
2
  import * as lit from 'lit';
3
3
  import { LitElement, PropertyValues } from 'lit';
4
4
 
5
+ interface FAQ {
6
+ "no.": string;
7
+ question: string;
8
+ }
5
9
  interface Message {
6
10
  id: string;
7
11
  role: 'user' | 'assistant';
8
12
  content: string;
13
+ faqs?: FAQ[];
9
14
  }
10
15
  /**
11
16
  * AI Chat Web Component
@@ -31,6 +36,8 @@ declare class AIChat extends LitElement {
31
36
  theme: 'light' | 'dark';
32
37
  mode: 'fullscreen' | 'widget';
33
38
  initialMessages: Message[];
39
+ botAvatarUrl: string;
40
+ backgroundImageUrl: string;
34
41
  private messages;
35
42
  private input;
36
43
  private isLoading;
@@ -59,6 +66,14 @@ declare class AIChat extends LitElement {
59
66
  initialMessages: {
60
67
  type: ArrayConstructor;
61
68
  };
69
+ botAvatarUrl: {
70
+ type: StringConstructor;
71
+ attribute: string;
72
+ };
73
+ backgroundImageUrl: {
74
+ type: StringConstructor;
75
+ attribute: string;
76
+ };
62
77
  };
63
78
  constructor();
64
79
  private toggleWidget;
@@ -66,6 +81,7 @@ declare class AIChat extends LitElement {
66
81
  updated(changedProperties: PropertyValues): void;
67
82
  private scrollToBottom;
68
83
  private handleInput;
84
+ private handleFAQClick;
69
85
  private handleSubmit;
70
86
  private renderChatUI;
71
87
  render(): lit_html.TemplateResult<1>;
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ var __decorateClass = (decorators, target, key, kind) => {
15
15
  if (kind && result) __defProp(target, key, result);
16
16
  return result;
17
17
  };
18
- var VERSION = "0.2.2";
18
+ var VERSION = "0.2.4";
19
19
  exports.AIChat = class AIChat extends lit.LitElement {
20
20
  constructor() {
21
21
  super();
@@ -25,6 +25,8 @@ exports.AIChat = class AIChat extends lit.LitElement {
25
25
  this.theme = "light";
26
26
  this.mode = "fullscreen";
27
27
  this.initialMessages = [];
28
+ this.botAvatarUrl = "";
29
+ this.backgroundImageUrl = "";
28
30
  this.messages = [];
29
31
  this.input = "";
30
32
  this.isLoading = false;
@@ -53,6 +55,12 @@ exports.AIChat = class AIChat extends lit.LitElement {
53
55
  handleInput(e) {
54
56
  this.input = e.target.value;
55
57
  }
58
+ handleFAQClick(question) {
59
+ if (this.isLoading) return;
60
+ this.input = question;
61
+ const submitEvent = new Event("submit", { cancelable: true });
62
+ this.handleSubmit(submitEvent);
63
+ }
56
64
  async handleSubmit(e) {
57
65
  e.preventDefault();
58
66
  if (!this.input.trim() || this.isLoading || !this.apiUrl) return;
@@ -84,16 +92,79 @@ exports.AIChat = class AIChat extends lit.LitElement {
84
92
  throw new Error(`Backend error: ${response.status} ${errorText}`);
85
93
  }
86
94
  const data = await response.json();
95
+ console.log("\u{1F50D} Raw API response:", data);
87
96
  let responseText = "No response from agent";
88
- if (typeof data === "string") {
97
+ let faqs = void 0;
98
+ if (data && typeof data === "object" && data.response && typeof data.response === "string") {
99
+ console.log("\u{1F4DD} data.response type:", typeof data.response);
100
+ console.log("\u{1F4DD} data.response preview:", data.response.substring(0, 100));
101
+ const trimmedResponse = data.response.trim();
102
+ if (trimmedResponse.startsWith("{") || trimmedResponse.startsWith("[")) {
103
+ console.log("\u{1F504} Detected stringified JSON, parsing...");
104
+ try {
105
+ let innerData = JSON.parse(data.response);
106
+ console.log("\u2705 Parsed inner data with JSON.parse");
107
+ if (innerData && innerData.response && typeof innerData.response === "string") {
108
+ responseText = innerData.response;
109
+ faqs = innerData.faqs_used || void 0;
110
+ console.log("\u2705 Extracted text length:", responseText.length);
111
+ console.log("\u2705 Extracted FAQs count:", faqs?.length || 0);
112
+ } else {
113
+ responseText = data.response;
114
+ faqs = data.faqs_used || void 0;
115
+ }
116
+ } catch (parseError) {
117
+ console.warn("\u26A0\uFE0F JSON.parse failed, using regex extraction...", parseError);
118
+ const responsePattern = /"response"\s*:\s*"([^"]*(?:\\.[^"]*)*)"/s;
119
+ const responseMatch = data.response.match(responsePattern);
120
+ if (responseMatch) {
121
+ responseText = responseMatch[1].replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\r/g, "\r").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
122
+ console.log("\u2705 Extracted response text, length:", responseText.length);
123
+ } else {
124
+ console.error("\u274C Could not extract response");
125
+ responseText = "Error: Could not parse response";
126
+ }
127
+ const faqsPattern = /"faqs_used"\s*:\s*(\[[^\]]*\])/s;
128
+ const faqsMatch = data.response.match(faqsPattern);
129
+ if (faqsMatch) {
130
+ try {
131
+ faqs = JSON.parse(faqsMatch[1]);
132
+ console.log("\u2705 Extracted FAQs, count:", faqs?.length || 0);
133
+ } catch {
134
+ console.log("\u26A0\uFE0F Could not parse FAQs, trying multiline...");
135
+ const faqsMultiPattern = /"faqs_used"\s*:\s*(\[[\s\S]*?\n\s*\])/;
136
+ const faqsMultiMatch = data.response.match(faqsMultiPattern);
137
+ if (faqsMultiMatch) {
138
+ try {
139
+ faqs = JSON.parse(faqsMultiMatch[1]);
140
+ console.log("\u2705 Extracted multi-line FAQs, count:", faqs?.length || 0);
141
+ } catch {
142
+ faqs = void 0;
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+ } else {
149
+ console.log("\u{1F4C4} Direct text response (not JSON)");
150
+ responseText = data.response;
151
+ faqs = data.faqs_used || void 0;
152
+ }
153
+ } else if (typeof data === "string") {
154
+ console.log("\u{1F4C4} Response is a plain string");
89
155
  responseText = data;
90
156
  } else if (data && typeof data === "object") {
91
- responseText = data.response || data.message || data.answer || JSON.stringify(data);
157
+ console.warn("\u26A0\uFE0F Unexpected format, using fallback");
158
+ responseText = data.message || data.answer || "Error: Unexpected response format";
92
159
  }
160
+ console.log("\u{1F3AF} Final responseText length:", responseText.length);
161
+ console.log("\u{1F3AF} Final responseText preview:", responseText.substring(0, 100));
162
+ console.log("\u{1F3AF} Final FAQs:", faqs);
93
163
  const assistantMessage = {
94
164
  id: (Date.now() + 1).toString(),
95
165
  role: "assistant",
96
- content: responseText
166
+ content: responseText,
167
+ faqs
97
168
  };
98
169
  this.messages = [...this.messages, assistantMessage];
99
170
  this.dispatchEvent(new CustomEvent("response-received", {
@@ -106,7 +177,7 @@ exports.AIChat = class AIChat extends lit.LitElement {
106
177
  const errorMessage = {
107
178
  id: (Date.now() + 1).toString(),
108
179
  role: "assistant",
109
- content: `Error: ${err.message}
180
+ content: `Error: ${err instanceof Error ? err.message : "Unknown error"}
110
181
 
111
182
  Please check your API endpoint configuration.`
112
183
  };
@@ -130,7 +201,7 @@ Please check your API endpoint configuration.`
130
201
  </div>
131
202
 
132
203
  <!-- Messages Area -->
133
- <div class="messages-area">
204
+ <div class="messages-area" style="${this.backgroundImageUrl ? `--background-image-url: url('${this.backgroundImageUrl}')` : ""}">
134
205
  <div class="messages-container">
135
206
  ${this.messages.length === 0 ? lit.html`
136
207
  <div class="empty-state">
@@ -145,17 +216,31 @@ Please check your API endpoint configuration.`
145
216
  assistant: msg.role === "assistant"
146
217
  })}>
147
218
  <div class="avatar">
148
- ${msg.role === "user" ? "U" : "AI"}
219
+ ${msg.role === "user" ? "U" : this.botAvatarUrl ? lit.html`<img src="${this.botAvatarUrl}" alt="AI" class="avatar-image" />` : "AI"}
149
220
  </div>
150
221
  <div class="message-content">
151
222
  <p class="message-text">${msg.content}</p>
223
+ ${msg.role === "assistant" && msg.faqs && msg.faqs.length > 0 ? lit.html`
224
+ <div class="faq-section">
225
+ <p class="faq-title">Related FAQs:</p>
226
+ <ul class="faq-list">
227
+ ${msg.faqs.map((faq) => lit.html`
228
+ <li class="faq-item" @click=${() => this.handleFAQClick(faq.question)}>
229
+ ${faq.question}
230
+ </li>
231
+ `)}
232
+ </ul>
233
+ </div>
234
+ ` : ""}
152
235
  </div>
153
236
  </div>
154
237
  `)}
155
238
 
156
239
  ${this.isLoading ? lit.html`
157
240
  <div class="loading">
158
- <div class="avatar">AI</div>
241
+ <div class="avatar">
242
+ ${this.botAvatarUrl ? lit.html`<img src="${this.botAvatarUrl}" alt="AI" class="avatar-image" />` : "AI"}
243
+ </div>
159
244
  <div class="message-content">
160
245
  <div class="spinner"></div>
161
246
  </div>
@@ -351,6 +436,23 @@ exports.AIChat.styles = lit.css`
351
436
  flex: 1;
352
437
  overflow-y: auto;
353
438
  padding: 1.5rem 1rem;
439
+ position: relative;
440
+ }
441
+
442
+ .messages-area::before {
443
+ content: '';
444
+ position: absolute;
445
+ top: 0;
446
+ left: 0;
447
+ right: 0;
448
+ bottom: 0;
449
+ background-image: var(--background-image-url);
450
+ background-size: 200px auto 60%;
451
+ background-position: center center;
452
+ background-repeat: no-repeat;
453
+ opacity: 0.5;
454
+ pointer-events: none;
455
+ z-index: 0;
354
456
  }
355
457
 
356
458
  .messages-container {
@@ -359,6 +461,8 @@ exports.AIChat.styles = lit.css`
359
461
  display: flex;
360
462
  flex-direction: column;
361
463
  gap: 1.5rem;
464
+ position: relative;
465
+ z-index: 1;
362
466
  }
363
467
 
364
468
  .empty-state {
@@ -397,12 +501,19 @@ exports.AIChat.styles = lit.css`
397
501
  flex-shrink: 0;
398
502
  font-weight: 500;
399
503
  font-size: 0.875rem;
504
+ overflow: hidden;
400
505
  }
401
506
 
402
507
  :host([theme="dark"]) .avatar {
403
508
  background: #3f3f46;
404
509
  }
405
510
 
511
+ .avatar-image {
512
+ width: 100%;
513
+ height: 100%;
514
+ object-fit: cover;
515
+ }
516
+
406
517
  .message-content {
407
518
  max-width: 36rem;
408
519
  padding: 0.75rem 1rem;
@@ -431,6 +542,59 @@ exports.AIChat.styles = lit.css`
431
542
  margin: 0;
432
543
  }
433
544
 
545
+ .faq-section {
546
+ margin-top: 1rem;
547
+ padding-top: 1rem;
548
+ border-top: 1px solid #e4e4e7;
549
+ }
550
+
551
+ :host([theme="dark"]) .faq-section {
552
+ border-top-color: #3f3f46;
553
+ }
554
+
555
+ .faq-title {
556
+ font-size: 0.875rem;
557
+ font-weight: 500;
558
+ color: #3f3f46;
559
+ margin: 0 0 0.5rem 0;
560
+ }
561
+
562
+ :host([theme="dark"]) .faq-title {
563
+ color: #d4d4d8;
564
+ }
565
+
566
+ .faq-list {
567
+ list-style: none;
568
+ padding: 0;
569
+ margin: 0;
570
+ display: flex;
571
+ flex-direction: column;
572
+ gap: 0.5rem;
573
+ }
574
+
575
+ .faq-item {
576
+ font-size: 0.875rem;
577
+ color: #52525b;
578
+ padding: 0.5rem;
579
+ border-radius: 0.375rem;
580
+ cursor: pointer;
581
+ transition: background-color 0.2s, color 0.2s;
582
+ }
583
+
584
+ .faq-item:hover {
585
+ background-color: #f4f4f5;
586
+ color: #18181b;
587
+ }
588
+
589
+ :host([theme="dark"]) .faq-item {
590
+ color: #a1a1aa;
591
+ }
592
+
593
+ :host([theme="dark"]) .faq-item:hover {
594
+ background-color: #27272a;
595
+ color: #fafafa;
596
+ }
597
+
434
598
  .loading {
435
599
  display: flex;
436
600
  gap: 1rem;
@@ -543,7 +707,9 @@ exports.AIChat.properties = {
543
707
  chatTitle: { type: String, attribute: "title" },
544
708
  theme: { type: String },
545
709
  mode: { type: String, reflect: true },
546
- initialMessages: { type: Array }
710
+ initialMessages: { type: Array },
711
+ botAvatarUrl: { type: String, attribute: "bot-avatar-url" },
712
+ backgroundImageUrl: { type: String, attribute: "background-image-url" }
547
713
  };
548
714
  __decorateClass([
549
715
  decorators_js.state()
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ai-chat.ts"],"names":["AIChat","LitElement","html","repeat","classMap","css","state","customElement"],"mappings":"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","file":"index.js","sourcesContent":["import { LitElement, html, css, PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nconst VERSION = '0.2.2';\n\nexport interface Message {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n}\n\n/**\n * AI Chat Web Component\n *\n * @fires message-sent - Fired when user sends a message\n * @fires response-received - Fired when AI responds\n * @fires error - Fired when an error occurs\n *\n * @example\n * ```html\n * <ai-chat\n * api-url=\"https://api.example.com\"\n * session-id=\"user-123\"\n * title=\"My AI Assistant\">\n * </ai-chat>\n * ```\n */\n@customElement('ai-chat')\nexport class AIChat extends LitElement {\n static styles = css`\n :host {\n font-family: system-ui, -apple-system, sans-serif;\n color: #09090b;\n }\n\n /* Fullscreen mode (default) */\n :host([mode=\"fullscreen\"]) {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #fafafa;\n }\n\n :host([mode=\"fullscreen\"][theme=\"dark\"]) {\n background: #000;\n color: #fafafa;\n }\n\n /* Widget mode */\n :host([mode=\"widget\"]) {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 9999;\n }\n\n .widget-container {\n position: relative;\n }\n\n .widget-button {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: #2563eb;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n\n .widget-button:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n .widget-button svg {\n width: 28px;\n height: 28px;\n color: white;\n }\n\n .widget-window {\n position: absolute;\n bottom: 80px;\n right: 0;\n width: 380px;\n height: 600px;\n background: #fff;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n opacity: 0;\n transform: scale(0.9) translateY(20px);\n pointer-events: none;\n transition: opacity 0.2s, transform 0.2s;\n }\n\n .widget-window.open {\n opacity: 1;\n transform: scale(1) translateY(0);\n pointer-events: all;\n }\n\n :host([theme=\"dark\"]) .widget-window {\n background: #18181b;\n color: #fafafa;\n }\n\n @media (max-width: 480px) {\n .widget-window {\n width: calc(100vw - 40px);\n height: calc(100vh - 100px);\n bottom: 80px;\n right: 0;\n }\n }\n\n .header {\n border-bottom: 1px solid #e4e4e7;\n background: #fff;\n padding: 1rem;\n }\n\n :host([theme=\"dark\"]) .header {\n border-bottom-color: #27272a;\n background: #18181b;\n }\n\n .header-content {\n max-width: 56rem;\n margin: 0 auto;\n }\n\n .title {\n font-size: 1.25rem;\n font-weight: 600;\n margin: 0;\n }\n\n .messages-area {\n flex: 1;\n overflow-y: auto;\n padding: 1.5rem 1rem;\n }\n\n .messages-container {\n max-width: 56rem;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n }\n\n .empty-state {\n text-align: center;\n color: #71717a;\n margin-top: 5rem;\n }\n\n :host([theme=\"dark\"]) .empty-state {\n color: #a1a1aa;\n }\n\n .empty-state p {\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n }\n\n .message {\n display: flex;\n gap: 1rem;\n }\n\n .message.user {\n flex-direction: row-reverse;\n }\n\n .avatar {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 9999px;\n background: #e4e4e7;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-weight: 500;\n font-size: 0.875rem;\n }\n\n :host([theme=\"dark\"]) .avatar {\n background: #3f3f46;\n }\n\n .message-content {\n max-width: 36rem;\n padding: 0.75rem 1rem;\n border-radius: 1rem;\n }\n\n .message.user .message-content {\n background: #2563eb;\n color: #fff;\n }\n\n .message.assistant .message-content {\n background: #fff;\n border: 1px solid #e4e4e7;\n color: #09090b;\n }\n\n :host([theme=\"dark\"]) .message.assistant .message-content {\n background: #27272a;\n border-color: #3f3f46;\n color: #fafafa;\n }\n\n .message-text {\n white-space: pre-wrap;\n margin: 0;\n }\n\n .loading {\n display: flex;\n gap: 1rem;\n }\n\n .spinner {\n display: inline-block;\n width: 1.25rem;\n height: 1.25rem;\n border: 2px solid #e4e4e7;\n border-top-color: #71717a;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n\n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n .input-area {\n border-top: 1px solid #e4e4e7;\n background: #fff;\n padding: 1rem;\n }\n\n :host([theme=\"dark\"]) .input-area {\n border-top-color: #27272a;\n background: #000;\n }\n\n .input-form {\n max-width: 56rem;\n margin: 0 auto;\n display: flex;\n gap: 0.75rem;\n }\n\n .input-field {\n flex: 1;\n height: 3rem;\n padding: 0 1rem;\n border: 1px solid #e4e4e7;\n border-radius: 0.5rem;\n font-size: 1rem;\n font-family: inherit;\n background: #fff;\n color: #09090b;\n }\n\n :host([theme=\"dark\"]) .input-field {\n border-color: #3f3f46;\n background: #18181b;\n color: #fafafa;\n }\n\n .input-field:focus {\n outline: 2px solid #2563eb;\n outline-offset: 2px;\n }\n\n .input-field:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .send-button {\n width: 3rem;\n height: 3rem;\n border-radius: 9999px;\n border: none;\n background: #2563eb;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .send-button:hover:not(:disabled) {\n background: #1d4ed8;\n }\n\n .send-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .send-icon {\n width: 1.25rem;\n height: 1.25rem;\n }\n\n .version-tag {\n text-align: center;\n padding: 0.5rem;\n font-size: 0.75rem;\n color: #71717a;\n border-top: 1px solid #e4e4e7;\n }\n\n :host([theme=\"dark\"]) .version-tag {\n color: #a1a1aa;\n border-top-color: #27272a;\n }\n `;\n\n declare apiUrl: string;\n declare sessionId: string;\n declare chatTitle: string;\n declare theme: 'light' | 'dark';\n declare mode: 'fullscreen' | 'widget';\n declare initialMessages: Message[];\n\n @state()\n private declare messages: Message[];\n\n @state()\n private declare input: string;\n\n @state()\n private declare isLoading: boolean;\n\n @state()\n private declare isOpen: boolean;\n\n private messagesEndRef?: HTMLDivElement;\n\n static override properties = {\n apiUrl: { type: String, attribute: 'api-url' },\n sessionId: { type: String, attribute: 'session-id' },\n chatTitle: { type: String, attribute: 'title' },\n theme: { type: String },\n mode: { type: String, reflect: true },\n initialMessages: { type: Array },\n };\n\n constructor() {\n super();\n this.apiUrl = '';\n this.sessionId = 'default-session';\n this.chatTitle = 'My AI Agent';\n this.theme = 'light';\n this.mode = 'fullscreen';\n this.initialMessages = [];\n this.messages = [];\n this.input = '';\n this.isLoading = false;\n this.isOpen = false;\n }\n\n private toggleWidget() {\n this.isOpen = !this.isOpen;\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (this.initialMessages && this.initialMessages.length > 0) {\n this.messages = [...this.initialMessages];\n }\n }\n\n updated(changedProperties: PropertyValues) {\n super.updated(changedProperties);\n if (changedProperties.has('messages')) {\n this.scrollToBottom();\n }\n }\n\n private scrollToBottom() {\n requestAnimationFrame(() => {\n this.messagesEndRef?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n\n private handleInput(e: Event) {\n this.input = (e.target as HTMLInputElement).value;\n }\n\n private async handleSubmit(e: Event) {\n e.preventDefault();\n\n if (!this.input.trim() || this.isLoading || !this.apiUrl) return;\n\n const userMessage: Message = {\n id: Date.now().toString(),\n role: 'user',\n content: this.input.trim(),\n };\n\n this.messages = [...this.messages, userMessage];\n const questionText = this.input.trim();\n this.input = '';\n this.isLoading = true;\n\n // Dispatch message-sent event\n this.dispatchEvent(new CustomEvent('message-sent', {\n detail: userMessage,\n bubbles: true,\n composed: true,\n }));\n\n try {\n const response = await fetch(`${this.apiUrl}/ask`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n session_id: this.sessionId,\n question: questionText,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Backend error: ${response.status} ${errorText}`);\n }\n\n const data = await response.json();\n\n // Extract the response text properly\n let responseText = 'No response from agent';\n\n if (typeof data === 'string') {\n responseText = data;\n } else if (data && typeof data === 'object') {\n // Handle the server response format: { response: \"text\", tags_used: [] }\n responseText = data.response || data.message || data.answer || JSON.stringify(data);\n }\n\n const assistantMessage: Message = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: responseText,\n };\n\n this.messages = [...this.messages, assistantMessage];\n\n // Dispatch response-received event\n this.dispatchEvent(new CustomEvent('response-received', {\n detail: assistantMessage,\n bubbles: true,\n composed: true,\n }));\n } catch (err: any) {\n console.error('Backend connection failed:', err);\n\n const errorMessage: Message = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: `Error: ${err.message}\\n\\nPlease check your API endpoint configuration.`,\n };\n\n this.messages = [...this.messages, errorMessage];\n\n // Dispatch error event\n this.dispatchEvent(new CustomEvent('error', {\n detail: err,\n bubbles: true,\n composed: true,\n }));\n } finally {\n this.isLoading = false;\n }\n }\n\n private renderChatUI() {\n return html`\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-content\">\n <h1 class=\"title\">${this.chatTitle}</h1>\n </div>\n </div>\n\n <!-- Messages Area -->\n <div class=\"messages-area\">\n <div class=\"messages-container\">\n ${this.messages.length === 0 ? html`\n <div class=\"empty-state\">\n <p>How can I help you today?</p>\n </div>\n ` : ''}\n\n ${repeat(this.messages, (msg) => msg.id, (msg) => html`\n <div class=${classMap({\n message: true,\n user: msg.role === 'user',\n assistant: msg.role === 'assistant'\n })}>\n <div class=\"avatar\">\n ${msg.role === 'user' ? 'U' : 'AI'}\n </div>\n <div class=\"message-content\">\n <p class=\"message-text\">${msg.content}</p>\n </div>\n </div>\n `)}\n\n ${this.isLoading ? html`\n <div class=\"loading\">\n <div class=\"avatar\">AI</div>\n <div class=\"message-content\">\n <div class=\"spinner\"></div>\n </div>\n </div>\n ` : ''}\n\n <div ${(el: Element) => this.messagesEndRef = el as HTMLDivElement}></div>\n </div>\n </div>\n\n <!-- Input Area -->\n <div class=\"input-area\">\n <form class=\"input-form\" @submit=${this.handleSubmit}>\n <input\n type=\"text\"\n class=\"input-field\"\n placeholder=\"Type your message...\"\n .value=${this.input}\n @input=${this.handleInput}\n ?disabled=${this.isLoading}\n />\n <button\n type=\"submit\"\n class=\"send-button\"\n ?disabled=${this.isLoading || !this.input.trim()}\n aria-label=\"Send message\"\n >\n ${this.isLoading ? html`\n <div class=\"spinner\" style=\"border-color: #fff; border-top-color: transparent;\"></div>\n ` : html`\n <svg class=\"send-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n `}\n </button>\n </form>\n </div>\n\n <!-- Version -->\n <div class=\"version-tag\">v${VERSION}</div>\n `;\n }\n\n render() {\n if (this.mode === 'widget') {\n return html`\n <div class=\"widget-container\">\n <!-- Chat Window -->\n <div class=${classMap({ 'widget-window': true, 'open': this.isOpen })}>\n ${this.renderChatUI()}\n </div>\n\n <!-- Toggle Button -->\n <button\n class=\"widget-button\"\n @click=${this.toggleWidget}\n aria-label=${this.isOpen ? 'Close chat' : 'Open chat'}\n >\n ${this.isOpen ? html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n ` : html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <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>\n </svg>\n `}\n </button>\n </div>\n `;\n }\n\n // Fullscreen mode\n return this.renderChatUI();\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ai-chat': AIChat;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/components/ai-chat.ts"],"names":["AIChat","LitElement","html","repeat","classMap","css","state","customElement"],"mappings":";;;;;;;;;;;;;;;;;AAKA,IAAM,OAAA,GAAU,OAAA;AA+BHA,cAAA,GAAN,qBAAqBC,cAAA,CAAW;AAAA,EAqarC,WAAA,GAAc;AACZ,IAAA,KAAA,EAAM;AACN,IAAA,IAAA,CAAK,MAAA,GAAS,EAAA;AACd,IAAA,IAAA,CAAK,SAAA,GAAY,iBAAA;AACjB,IAAA,IAAA,CAAK,SAAA,GAAY,aAAA;AACjB,IAAA,IAAA,CAAK,KAAA,GAAQ,OAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,YAAA;AACZ,IAAA,IAAA,CAAK,kBAAkB,EAAC;AACxB,IAAA,IAAA,CAAK,YAAA,GAAe,EAAA;AACpB,IAAA,IAAA,CAAK,kBAAA,GAAqB,EAAA;AAC1B,IAAA,IAAA,CAAK,WAAW,EAAC;AACjB,IAAA,IAAA,CAAK,KAAA,GAAQ,EAAA;AACb,IAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AACjB,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA;AAAA,EAChB;AAAA,EAEQ,YAAA,GAAe;AACrB,IAAA,IAAA,CAAK,MAAA,GAAS,CAAC,IAAA,CAAK,MAAA;AAAA,EACtB;AAAA,EAEA,iBAAA,GAAoB;AAClB,IAAA,KAAA,CAAM,iBAAA,EAAkB;AACxB,IAAA,IAAI,IAAA,CAAK,eAAA,IAAmB,IAAA,CAAK,eAAA,CAAgB,SAAS,CAAA,EAAG;AAC3D,MAAA,IAAA,CAAK,QAAA,GAAW,CAAC,GAAG,IAAA,CAAK,eAAe,CAAA;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,QAAQ,iBAAA,EAAmC;AACzC,IAAA,KAAA,CAAM,QAAQ,iBAAiB,CAAA;AAC/B,IAAA,IAAI,iBAAA,CAAkB,GAAA,CAAI,UAAU,CAAA,EAAG;AACrC,MAAA,IAAA,CAAK,cAAA,EAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,cAAA,GAAiB;AACvB,IAAA,qBAAA,CAAsB,MAAM;AAC1B,MAAA,IAAA,CAAK,cAAA,EAAgB,cAAA,CAAe,EAAE,QAAA,EAAU,UAAU,CAAA;AAAA,IAC5D,CAAC,CAAA;AAAA,EACH;AAAA,EAEQ,YAAY,CAAA,EAAU;AAC5B,IAAA,IAAA,CAAK,KAAA,GAAS,EAAE,MAAA,CAA4B,KAAA;AAAA,EAC9C;AAAA,EAEQ,eAAe,QAAA,EAAkB;AACvC,IAAA,IAAI,KAAK,SAAA,EAAW;AAGpB,IAAA,IAAA,CAAK,KAAA,GAAQ,QAAA;AAGb,IAAA,MAAM,cAAc,IAAI,KAAA,CAAM,UAAU,EAAE,UAAA,EAAY,MAAM,CAAA;AAC5D,IAAA,IAAA,CAAK,aAAa,WAAW,CAAA;AAAA,EAC/B;AAAA,EAEA,MAAc,aAAa,CAAA,EAAU;AACnC,IAAA,CAAA,CAAE,cAAA,EAAe;AAEjB,IAAA,IAAI,CAAC,KAAK,KAAA,CAAM,IAAA,MAAU,IAAA,CAAK,SAAA,IAAa,CAAC,IAAA,CAAK,MAAA,EAAQ;AAE1D,IAAA,MAAM,WAAA,GAAuB;AAAA,MAC3B,EAAA,EAAI,IAAA,CAAK,GAAA,EAAI,CAAE,QAAA,EAAS;AAAA,MACxB,IAAA,EAAM,MAAA;AAAA,MACN,OAAA,EAAS,IAAA,CAAK,KAAA,CAAM,IAAA;AAAK,KAC3B;AAEA,IAAA,IAAA,CAAK,QAAA,GAAW,CAAC,GAAG,IAAA,CAAK,UAAU,WAAW,CAAA;AAC9C,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,KAAA,CAAM,IAAA,EAAK;AACrC,IAAA,IAAA,CAAK,KAAA,GAAQ,EAAA;AACb,IAAA,IAAA,CAAK,SAAA,GAAY,IAAA;AAGjB,IAAA,IAAA,CAAK,aAAA,CAAc,IAAI,WAAA,CAAY,cAAA,EAAgB;AAAA,MACjD,MAAA,EAAQ,WAAA;AAAA,MACR,OAAA,EAAS,IAAA;AAAA,MACT,QAAA,EAAU;AAAA,KACX,CAAC,CAAA;AAEF,IAAA,IAAI;AACF,MAAA,MAAM,WAAW,MAAM,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,MAAM,CAAA,IAAA,CAAA,EAAQ;AAAA,QACjD,MAAA,EAAQ,MAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA,EAAmB;AAAA,QAC9C,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,UACnB,YAAY,IAAA,CAAK,SAAA;AAAA,UACjB,QAAA,EAAU;AAAA,SACX;AAAA,OACF,CAAA;AAED,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,SAAA,GAAY,MAAM,QAAA,CAAS,IAAA,EAAK;AACtC,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,eAAA,EAAkB,SAAS,MAAM,CAAA,CAAA,EAAI,SAAS,CAAA,CAAE,CAAA;AAAA,MAClE;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,EAAK;AACjC,MAAA,OAAA,CAAQ,GAAA,CAAI,+BAAwB,IAAI,CAAA;AAGxC,MAAA,IAAI,YAAA,GAAe,wBAAA;AACnB,MAAA,IAAI,IAAA,GAA0B,KAAA,CAAA;AAE9B,MAAA,IAAI,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,IAAY,KAAK,QAAA,IAAY,OAAO,IAAA,CAAK,QAAA,KAAa,QAAA,EAAU;AAC1F,QAAA,OAAA,CAAQ,GAAA,CAAI,+BAAA,EAA0B,OAAO,IAAA,CAAK,QAAQ,CAAA;AAC1D,QAAA,OAAA,CAAQ,IAAI,kCAAA,EAA6B,IAAA,CAAK,SAAS,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA;AAGxE,QAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,QAAA,CAAS,IAAA,EAAK;AAC3C,QAAA,IAAI,gBAAgB,UAAA,CAAW,GAAG,KAAK,eAAA,CAAgB,UAAA,CAAW,GAAG,CAAA,EAAG;AACtE,UAAA,OAAA,CAAQ,IAAI,iDAA0C,CAAA;AAEtD,UAAA,IAAI;AAEF,YAAA,IAAI,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,QAAQ,CAAA;AACxC,YAAA,OAAA,CAAQ,IAAI,0CAAqC,CAAA;AAEjD,YAAA,IAAI,aAAa,SAAA,CAAU,QAAA,IAAY,OAAO,SAAA,CAAU,aAAa,QAAA,EAAU;AAC7E,cAAA,YAAA,GAAe,SAAA,CAAU,QAAA;AACzB,cAAA,IAAA,GAAO,UAAU,SAAA,IAAa,KAAA,CAAA;AAC9B,cAAA,OAAA,CAAQ,GAAA,CAAI,+BAAA,EAA4B,YAAA,CAAa,MAAM,CAAA;AAC3D,cAAA,OAAA,CAAQ,GAAA,CAAI,8BAAA,EAA2B,IAAA,EAAM,MAAA,IAAU,CAAC,CAAA;AAAA,YAC1D,CAAA,MAAO;AACL,cAAA,YAAA,GAAe,IAAA,CAAK,QAAA;AACpB,cAAA,IAAA,GAAO,KAAK,SAAA,IAAa,KAAA,CAAA;AAAA,YAC3B;AAAA,UACF,SAAS,UAAA,EAAY;AACnB,YAAA,OAAA,CAAQ,IAAA,CAAK,6DAAmD,UAAU,CAAA;AAG1E,YAAA,MAAM,eAAA,GAAkB,0CAAA;AACxB,YAAA,MAAM,aAAA,GAAgB,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,eAAe,CAAA;AAEzD,YAAA,IAAI,aAAA,EAAe;AACjB,cAAA,YAAA,GAAe,aAAA,CAAc,CAAC,CAAA,CAC3B,OAAA,CAAQ,QAAQ,IAAI,CAAA,CACpB,QAAQ,MAAA,EAAQ,GAAI,EACpB,OAAA,CAAQ,MAAA,EAAQ,IAAI,CAAA,CACpB,OAAA,CAAQ,QAAQ,GAAG,CAAA,CACnB,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA;AACxB,cAAA,OAAA,CAAQ,GAAA,CAAI,yCAAA,EAAsC,YAAA,CAAa,MAAM,CAAA;AAAA,YACvE,CAAA,MAAO;AACL,cAAA,OAAA,CAAQ,MAAM,mCAA8B,CAAA;AAC5C,cAAA,YAAA,GAAe,iCAAA;AAAA,YACjB;AAGA,YAAA,MAAM,WAAA,GAAc,iCAAA;AACpB,YAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,WAAW,CAAA;AAEjD,YAAA,IAAI,SAAA,EAAW;AACb,cAAA,IAAI;AACF,gBAAA,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,SAAA,CAAU,CAAC,CAAC,CAAA;AAC9B,gBAAA,OAAA,CAAQ,GAAA,CAAI,+BAAA,EAA4B,IAAA,EAAM,MAAA,IAAU,CAAC,CAAA;AAAA,cAC3D,CAAA,CAAA,MAAQ;AACN,gBAAA,OAAA,CAAQ,IAAI,wDAA8C,CAAA;AAE1D,gBAAA,MAAM,gBAAA,GAAmB,uCAAA;AACzB,gBAAA,MAAM,cAAA,GAAiB,IAAA,CAAK,QAAA,CAAS,KAAA,CAAM,gBAAgB,CAAA;AAC3D,gBAAA,IAAI,cAAA,EAAgB;AAClB,kBAAA,IAAI;AACF,oBAAA,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,cAAA,CAAe,CAAC,CAAC,CAAA;AACnC,oBAAA,OAAA,CAAQ,GAAA,CAAI,0CAAA,EAAuC,IAAA,EAAM,MAAA,IAAU,CAAC,CAAA;AAAA,kBACtE,CAAA,CAAA,MAAQ;AACN,oBAAA,IAAA,GAAO,KAAA,CAAA;AAAA,kBACT;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF,CAAA,MAAO;AAEL,UAAA,OAAA,CAAQ,IAAI,2CAAoC,CAAA;AAChD,UAAA,YAAA,GAAe,IAAA,CAAK,QAAA;AACpB,UAAA,IAAA,GAAO,KAAK,SAAA,IAAa,KAAA,CAAA;AAAA,QAC3B;AAAA,MACF,CAAA,MAAA,IAAW,OAAO,IAAA,KAAS,QAAA,EAAU;AACnC,QAAA,OAAA,CAAQ,IAAI,sCAA+B,CAAA;AAC3C,QAAA,YAAA,GAAe,IAAA;AAAA,MACjB,CAAA,MAAA,IAAW,IAAA,IAAQ,OAAO,IAAA,KAAS,QAAA,EAAU;AAE3C,QAAA,OAAA,CAAQ,KAAK,gDAAsC,CAAA;AACnD,QAAA,YAAA,GAAe,IAAA,CAAK,OAAA,IAAW,IAAA,CAAK,MAAA,IAAU,mCAAA;AAAA,MAChD;AAEA,MAAA,OAAA,CAAQ,GAAA,CAAI,sCAAA,EAAiC,YAAA,CAAa,MAAM,CAAA;AAChE,MAAA,OAAA,CAAQ,IAAI,uCAAA,EAAkC,YAAA,CAAa,SAAA,CAAU,CAAA,EAAG,GAAG,CAAC,CAAA;AAC5E,MAAA,OAAA,CAAQ,GAAA,CAAI,yBAAkB,IAAI,CAAA;AAElC,MAAA,MAAM,gBAAA,GAA4B;AAAA,QAChC,EAAA,EAAA,CAAK,IAAA,CAAK,GAAA,EAAI,GAAI,GAAG,QAAA,EAAS;AAAA,QAC9B,IAAA,EAAM,WAAA;AAAA,QACN,OAAA,EAAS,YAAA;AAAA,QACT;AAAA,OACF;AAEA,MAAA,IAAA,CAAK,QAAA,GAAW,CAAC,GAAG,IAAA,CAAK,UAAU,gBAAgB,CAAA;AAGnD,MAAA,IAAA,CAAK,aAAA,CAAc,IAAI,WAAA,CAAY,mBAAA,EAAqB;AAAA,QACtD,MAAA,EAAQ,gBAAA;AAAA,QACR,OAAA,EAAS,IAAA;AAAA,QACT,QAAA,EAAU;AAAA,OACX,CAAC,CAAA;AAAA,IACJ,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,8BAA8B,GAAG,CAAA;AAE/C,MAAA,MAAM,YAAA,GAAwB;AAAA,QAC5B,EAAA,EAAA,CAAK,IAAA,CAAK,GAAA,EAAI,GAAI,GAAG,QAAA,EAAS;AAAA,QAC9B,IAAA,EAAM,WAAA;AAAA,QACN,SAAS,CAAA,OAAA,EAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,UAAU,eAAe;;AAAA,6CAAA;AAAA,OACzE;AAEA,MAAA,IAAA,CAAK,QAAA,GAAW,CAAC,GAAG,IAAA,CAAK,UAAU,YAAY,CAAA;AAG/C,MAAA,IAAA,CAAK,aAAA,CAAc,IAAI,WAAA,CAAY,OAAA,EAAS;AAAA,QAC1C,MAAA,EAAQ,GAAA;AAAA,QACR,OAAA,EAAS,IAAA;AAAA,QACT,QAAA,EAAU;AAAA,OACX,CAAC,CAAA;AAAA,IACJ,CAAA,SAAE;AACA,MAAA,IAAA,CAAK,SAAA,GAAY,KAAA;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,YAAA,GAAe;AACrB,IAAA,OAAOC,QAAA;AAAA;AAAA;AAAA;AAAA,4BAAA,EAImB,KAAK,SAAS,CAAA;AAAA;AAAA;;AAAA;AAAA,wCAAA,EAKF,KAAK,kBAAA,GAAqB,CAAA,6BAAA,EAAgC,IAAA,CAAK,kBAAkB,OAAO,EAAE,CAAA;AAAA;AAAA,UAAA,EAExH,IAAA,CAAK,QAAA,CAAS,MAAA,KAAW,CAAA,GAAIA,QAAA;AAAA;AAAA;AAAA;AAAA,UAAA,CAAA,GAI3B,EAAE;;AAAA,UAAA,EAEJC,gBAAA,CAAO,KAAK,QAAA,EAAU,CAAC,QAAQ,GAAA,CAAI,EAAA,EAAI,CAAC,GAAA,KAAQD,QAAA;AAAA,uBAAA,EACnCE,oBAAA,CAAS;AAAA,MACpB,OAAA,EAAS,IAAA;AAAA,MACT,IAAA,EAAM,IAAI,IAAA,KAAS,MAAA;AAAA,MACnB,SAAA,EAAW,IAAI,IAAA,KAAS;AAAA,KACzB,CAAC,CAAA;AAAA;AAAA,gBAAA,EAEI,GAAA,CAAI,IAAA,KAAS,MAAA,GACX,GAAA,GACA,IAAA,CAAK,eACHF,QAAA,CAAA,UAAA,EAAiB,IAAA,CAAK,YAAY,CAAA,kCAAA,CAAA,GAClC,IAAI;AAAA;AAAA;AAAA,wCAAA,EAGgB,IAAI,OAAO,CAAA;AAAA,gBAAA,EACnC,GAAA,CAAI,SAAS,WAAA,IAAe,GAAA,CAAI,QAAQ,GAAA,CAAI,IAAA,CAAK,SAAS,CAAA,GAAIA,QAAA;AAAA;AAAA;AAAA;AAAA,sBAAA,EAIxD,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAA,KAAOA,QAAA;AAAA,oDAAA,EACU,MAAM,IAAA,CAAK,cAAA,CAAe,GAAA,CAAI,QAAQ,CAAC,CAAA;AAAA,0BAAA,EACjE,IAAI,QAAQ;AAAA;AAAA,sBAAA,CAEjB,CAAC;AAAA;AAAA;AAAA,gBAAA,CAAA,GAGJ,EAAE;AAAA;AAAA;AAAA,UAAA,CAGX,CAAC;;AAAA,UAAA,EAEA,KAAK,SAAA,GAAYA,QAAA;AAAA;AAAA;AAAA,gBAAA,EAGX,KAAK,YAAA,GACHA,QAAA,CAAA,UAAA,EAAiB,IAAA,CAAK,YAAY,uCAClC,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,UAAA,CAAA,GAMV,EAAE;;AAAA,eAAA,EAEC,CAAC,EAAA,KAAgB,IAAA,CAAK,cAAA,GAAiB,EAAoB,CAAA;AAAA;AAAA;;AAAA;AAAA;AAAA,yCAAA,EAMjC,KAAK,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAA,EAKvC,KAAK,KAAK;AAAA,mBAAA,EACV,KAAK,WAAW;AAAA,sBAAA,EACb,KAAK,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,sBAAA,EAKd,KAAK,SAAA,IAAa,CAAC,IAAA,CAAK,KAAA,CAAM,MAAM;AAAA;AAAA;AAAA,YAAA,EAG9C,KAAK,SAAA,GAAYA,QAAA;AAAA;AAAA,YAAA,CAAA,GAEfA,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAKH;AAAA;AAAA;AAAA;;AAAA;AAAA,gCAAA,EAMqB,OAAO,CAAA;AAAA,IAAA,CAAA;AAAA,EAEvC;AAAA,EAEA,MAAA,GAAS;AACP,IAAA,IAAI,IAAA,CAAK,SAAS,QAAA,EAAU;AAC1B,MAAA,OAAOA,QAAA;AAAA;AAAA;AAAA,qBAAA,EAGUE,oBAAA,CAAS,EAAE,eAAA,EAAiB,IAAA,EAAM,QAAQ,IAAA,CAAK,MAAA,EAAQ,CAAC,CAAA;AAAA,YAAA,EACjE,IAAA,CAAK,cAAc;AAAA;;AAAA;AAAA;AAAA;AAAA,mBAAA,EAMZ,KAAK,YAAY;AAAA,uBAAA,EACb,IAAA,CAAK,MAAA,GAAS,YAAA,GAAe,WAAW;AAAA;AAAA,YAAA,EAEnD,KAAK,MAAA,GAASF,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAAA,GAKZA,QAAA;AAAA;AAAA;AAAA;AAAA,YAAA,CAIH;AAAA;AAAA;AAAA,MAAA,CAAA;AAAA,IAIT;AAGA,IAAA,OAAO,KAAK,YAAA,EAAa;AAAA,EAC3B;AACF;AAzwBaF,cAAA,CACJ,MAAA,GAASK,OAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA,EAAA,CAAA;AADLL,cAAA,CA0ZK,UAAA,GAAa;AAAA,EAC3B,MAAA,EAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,WAAW,SAAA,EAAU;AAAA,EAC7C,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA,EAAQ,WAAW,YAAA,EAAa;AAAA,EACnD,SAAA,EAAW,EAAE,IAAA,EAAM,MAAA,EAAQ,WAAW,OAAA,EAAQ;AAAA,EAC9C,KAAA,EAAO,EAAE,IAAA,EAAM,MAAA,EAAO;AAAA,EACtB,IAAA,EAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAS,IAAA,EAAK;AAAA,EACpC,eAAA,EAAiB,EAAE,IAAA,EAAM,KAAA,EAAM;AAAA,EAC/B,YAAA,EAAc,EAAE,IAAA,EAAM,MAAA,EAAQ,WAAW,gBAAA,EAAiB;AAAA,EAC1D,kBAAA,EAAoB,EAAE,IAAA,EAAM,MAAA,EAAQ,WAAW,sBAAA;AACjD,CAAA;AAtBgB,eAAA,CAAA;AAAA,EADfM,mBAAA;AAAM,CAAA,EA5YIN,cAAA,CA6YK,SAAA,EAAA,UAAA,EAAA,CAAA,CAAA;AAGA,eAAA,CAAA;AAAA,EADfM,mBAAA;AAAM,CAAA,EA/YIN,cAAA,CAgZK,SAAA,EAAA,OAAA,EAAA,CAAA,CAAA;AAGA,eAAA,CAAA;AAAA,EADfM,mBAAA;AAAM,CAAA,EAlZIN,cAAA,CAmZK,SAAA,EAAA,WAAA,EAAA,CAAA,CAAA;AAGA,eAAA,CAAA;AAAA,EADfM,mBAAA;AAAM,CAAA,EArZIN,cAAA,CAsZK,SAAA,EAAA,QAAA,EAAA,CAAA,CAAA;AAtZLA,cAAA,GAAN,eAAA,CAAA;AAAA,EADNO,4BAAc,SAAS;AAAA,CAAA,EACXP,cAAA,CAAA","file":"index.js","sourcesContent":["import { LitElement, html, css, PropertyValues } from 'lit';\r\nimport { customElement, state } from 'lit/decorators.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport { classMap } from 'lit/directives/class-map.js';\r\n\r\nconst VERSION = '0.2.4';\r\n\r\nexport interface FAQ {\r\n \"no.\": string;\r\n question: string;\r\n}\r\n\r\nexport interface Message {\r\n id: string;\r\n role: 'user' | 'assistant';\r\n content: string;\r\n faqs?: FAQ[];\r\n}\r\n\r\n/**\r\n * AI Chat Web Component\r\n *\r\n * @fires message-sent - Fired when user sends a message\r\n * @fires response-received - Fired when AI responds\r\n * @fires error - Fired when an error occurs\r\n *\r\n * @example\r\n * ```html\r\n * <ai-chat\r\n * api-url=\"https://api.example.com\"\r\n * session-id=\"user-123\"\r\n * title=\"My AI Assistant\">\r\n * </ai-chat>\r\n * ```\r\n */\r\n@customElement('ai-chat')\r\nexport class AIChat extends LitElement {\r\n static styles = css`\r\n :host {\r\n font-family: system-ui, -apple-system, sans-serif;\r\n color: #09090b;\r\n }\r\n\r\n /* Fullscreen mode (default) */\r\n :host([mode=\"fullscreen\"]) {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100vh;\r\n background: #fafafa;\r\n }\r\n\r\n :host([mode=\"fullscreen\"][theme=\"dark\"]) {\r\n background: #000;\r\n color: #fafafa;\r\n }\r\n\r\n /* Widget mode */\r\n :host([mode=\"widget\"]) {\r\n position: fixed;\r\n bottom: 20px;\r\n right: 20px;\r\n z-index: 9999;\r\n }\r\n\r\n .widget-container {\r\n position: relative;\r\n }\r\n\r\n .widget-button {\r\n width: 60px;\r\n height: 60px;\r\n border-radius: 50%;\r\n background: #2563eb;\r\n border: none;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n transition: transform 0.2s, box-shadow 0.2s;\r\n }\r\n\r\n .widget-button:hover {\r\n transform: scale(1.05);\r\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\r\n }\r\n\r\n .widget-button svg {\r\n width: 28px;\r\n height: 28px;\r\n color: white;\r\n }\r\n\r\n .widget-window {\r\n position: absolute;\r\n bottom: 80px;\r\n right: 0;\r\n width: 380px;\r\n height: 600px;\r\n background: #fff;\r\n border-radius: 12px;\r\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n opacity: 0;\r\n transform: scale(0.9) translateY(20px);\r\n pointer-events: none;\r\n transition: opacity 0.2s, transform 0.2s;\r\n }\r\n\r\n .widget-window.open {\r\n opacity: 1;\r\n transform: scale(1) translateY(0);\r\n pointer-events: all;\r\n }\r\n\r\n :host([theme=\"dark\"]) .widget-window {\r\n background: #18181b;\r\n color: #fafafa;\r\n }\r\n\r\n @media (max-width: 480px) {\r\n .widget-window {\r\n width: calc(100vw - 40px);\r\n height: calc(100vh - 100px);\r\n bottom: 80px;\r\n right: 0;\r\n }\r\n }\r\n\r\n .header {\r\n border-bottom: 1px solid #e4e4e7;\r\n background: #fff;\r\n padding: 1rem;\r\n }\r\n\r\n :host([theme=\"dark\"]) .header {\r\n border-bottom-color: #27272a;\r\n background: #18181b;\r\n }\r\n\r\n .header-content {\r\n max-width: 56rem;\r\n margin: 0 auto;\r\n }\r\n\r\n .title {\r\n font-size: 1.25rem;\r\n font-weight: 600;\r\n margin: 0;\r\n }\r\n\r\n .messages-area {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 1.5rem 1rem;\r\n position: relative;\r\n }\r\n\r\n .messages-area::before {\r\n content: '';\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-image: var(--background-image-url);\r\n background-size: 200px auto 60%;\r\n background-position: center center;\r\n background-repeat: no-repeat;\r\n opacity: 0.5;\r\n pointer-events: none;\r\n z-index: 0;\r\n }\r\n\r\n .messages-container {\r\n max-width: 56rem;\r\n margin: 0 auto;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 1.5rem;\r\n position: relative;\r\n z-index: 1;\r\n }\r\n\r\n .empty-state {\r\n text-align: center;\r\n color: #71717a;\r\n margin-top: 5rem;\r\n }\r\n\r\n :host([theme=\"dark\"]) .empty-state {\r\n color: #a1a1aa;\r\n }\r\n\r\n .empty-state p {\r\n font-size: 1.5rem;\r\n font-weight: 500;\r\n margin: 0;\r\n }\r\n\r\n .message {\r\n display: flex;\r\n gap: 1rem;\r\n }\r\n\r\n .message.user {\r\n flex-direction: row-reverse;\r\n }\r\n\r\n .avatar {\r\n width: 2.5rem;\r\n height: 2.5rem;\r\n border-radius: 9999px;\r\n background: #e4e4e7;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n font-weight: 500;\r\n font-size: 0.875rem;\r\n overflow: hidden;\r\n }\r\n\r\n :host([theme=\"dark\"]) .avatar {\r\n background: #3f3f46;\r\n }\r\n\r\n .avatar-image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n }\r\n\r\n .message-content {\r\n max-width: 36rem;\r\n padding: 0.75rem 1rem;\r\n border-radius: 1rem;\r\n }\r\n\r\n .message.user .message-content {\r\n background: #2563eb;\r\n color: #fff;\r\n }\r\n\r\n .message.assistant .message-content {\r\n background: #fff;\r\n border: 1px solid #e4e4e7;\r\n color: #09090b;\r\n }\r\n\r\n :host([theme=\"dark\"]) .message.assistant .message-content {\r\n background: #27272a;\r\n border-color: #3f3f46;\r\n color: #fafafa;\r\n }\r\n\r\n .message-text {\r\n white-space: pre-wrap;\r\n margin: 0;\r\n }\r\n\r\n .faq-section {\r\n margin-top: 1rem;\r\n padding-top: 1rem;\r\n border-top: 1px solid #e4e4e7;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-section {\r\n border-top-color: #3f3f46;\r\n }\r\n\r\n .faq-title {\r\n font-size: 0.875rem;\r\n font-weight: 500;\r\n color: #3f3f46;\r\n margin: 0 0 0.5rem 0;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-title {\r\n color: #d4d4d8;\r\n }\r\n\r\n .faq-list {\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0.5rem;\r\n }\r\n\r\n .faq-item {\r\n font-size: 0.875rem;\r\n color: #52525b;\r\n padding: 0.5rem;\r\n border-radius: 0.375rem;\r\n cursor: pointer;\r\n transition: background-color 0.2s, color 0.2s;\r\n }\r\n\r\n .faq-item:hover {\r\n background-color: #f4f4f5;\r\n color: #18181b;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-item {\r\n color: #a1a1aa;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-item:hover {\r\n background-color: #27272a;\r\n color: #fafafa;\r\n }\r\n\r\n .loading {\r\n display: flex;\r\n gap: 1rem;\r\n }\r\n\r\n .spinner {\r\n display: inline-block;\r\n width: 1.25rem;\r\n height: 1.25rem;\r\n border: 2px solid #e4e4e7;\r\n border-top-color: #71717a;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n\r\n @keyframes spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n\r\n .input-area {\r\n border-top: 1px solid #e4e4e7;\r\n background: #fff;\r\n padding: 1rem;\r\n }\r\n\r\n :host([theme=\"dark\"]) .input-area {\r\n border-top-color: #27272a;\r\n background: #000;\r\n }\r\n\r\n .input-form {\r\n max-width: 56rem;\r\n margin: 0 auto;\r\n display: flex;\r\n gap: 0.75rem;\r\n }\r\n\r\n .input-field {\r\n flex: 1;\r\n height: 3rem;\r\n padding: 0 1rem;\r\n border: 1px solid #e4e4e7;\r\n border-radius: 0.5rem;\r\n font-size: 1rem;\r\n font-family: inherit;\r\n background: #fff;\r\n color: #09090b;\r\n }\r\n\r\n :host([theme=\"dark\"]) .input-field {\r\n border-color: #3f3f46;\r\n background: #18181b;\r\n color: #fafafa;\r\n }\r\n\r\n .input-field:focus {\r\n outline: 2px solid #2563eb;\r\n outline-offset: 2px;\r\n }\r\n\r\n .input-field:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .send-button {\r\n width: 3rem;\r\n height: 3rem;\r\n border-radius: 9999px;\r\n border: none;\r\n background: #2563eb;\r\n color: #fff;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: background 0.2s;\r\n }\r\n\r\n .send-button:hover:not(:disabled) {\r\n background: #1d4ed8;\r\n }\r\n\r\n .send-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .send-icon {\r\n width: 1.25rem;\r\n height: 1.25rem;\r\n }\r\n\r\n .version-tag {\r\n text-align: center;\r\n padding: 0.5rem;\r\n font-size: 0.75rem;\r\n color: #71717a;\r\n border-top: 1px solid #e4e4e7;\r\n }\r\n\r\n :host([theme=\"dark\"]) .version-tag {\r\n color: #a1a1aa;\r\n border-top-color: #27272a;\r\n }\r\n `;\r\n\r\n declare apiUrl: string;\r\n declare sessionId: string;\r\n declare chatTitle: string;\r\n declare theme: 'light' | 'dark';\r\n declare mode: 'fullscreen' | 'widget';\r\n declare initialMessages: Message[];\r\n declare botAvatarUrl: string;\r\n declare backgroundImageUrl: string;\r\n\r\n @state()\r\n private declare messages: Message[];\r\n\r\n @state()\r\n private declare input: string;\r\n\r\n @state()\r\n private declare isLoading: boolean;\r\n\r\n @state()\r\n private declare isOpen: boolean;\r\n\r\n private messagesEndRef?: HTMLDivElement;\r\n\r\n static override properties = {\r\n apiUrl: { type: String, attribute: 'api-url' },\r\n sessionId: { type: String, attribute: 'session-id' },\r\n chatTitle: { type: String, attribute: 'title' },\r\n theme: { type: String },\r\n mode: { type: String, reflect: true },\r\n initialMessages: { type: Array },\r\n botAvatarUrl: { type: String, attribute: 'bot-avatar-url' },\r\n backgroundImageUrl: { type: String, attribute: 'background-image-url' },\r\n };\r\n\r\n constructor() {\r\n super();\r\n this.apiUrl = '';\r\n this.sessionId = 'default-session';\r\n this.chatTitle = 'My AI Agent';\r\n this.theme = 'light';\r\n this.mode = 'fullscreen';\r\n this.initialMessages = [];\r\n this.botAvatarUrl = '';\r\n this.backgroundImageUrl = '';\r\n this.messages = [];\r\n this.input = '';\r\n this.isLoading = false;\r\n this.isOpen = false;\r\n }\r\n\r\n private toggleWidget() {\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n connectedCallback() {\r\n super.connectedCallback();\r\n if (this.initialMessages && this.initialMessages.length > 0) {\r\n this.messages = [...this.initialMessages];\r\n }\r\n }\r\n\r\n updated(changedProperties: PropertyValues) {\r\n super.updated(changedProperties);\r\n if (changedProperties.has('messages')) {\r\n this.scrollToBottom();\r\n }\r\n }\r\n\r\n private scrollToBottom() {\r\n requestAnimationFrame(() => {\r\n this.messagesEndRef?.scrollIntoView({ behavior: 'smooth' });\r\n });\r\n }\r\n\r\n private handleInput(e: Event) {\r\n this.input = (e.target as HTMLInputElement).value;\r\n }\r\n\r\n private handleFAQClick(question: string) {\r\n if (this.isLoading) return;\r\n\r\n // Set the input and trigger submit\r\n this.input = question;\r\n\r\n // Create a synthetic submit event\r\n const submitEvent = new Event('submit', { cancelable: true });\r\n this.handleSubmit(submitEvent);\r\n }\r\n\r\n private async handleSubmit(e: Event) {\r\n e.preventDefault();\r\n\r\n if (!this.input.trim() || this.isLoading || !this.apiUrl) return;\r\n\r\n const userMessage: Message = {\r\n id: Date.now().toString(),\r\n role: 'user',\r\n content: this.input.trim(),\r\n };\r\n\r\n this.messages = [...this.messages, userMessage];\r\n const questionText = this.input.trim();\r\n this.input = '';\r\n this.isLoading = true;\r\n\r\n // Dispatch message-sent event\r\n this.dispatchEvent(new CustomEvent('message-sent', {\r\n detail: userMessage,\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n\r\n try {\r\n const response = await fetch(`${this.apiUrl}/ask`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n session_id: this.sessionId,\r\n question: questionText,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n throw new Error(`Backend error: ${response.status} ${errorText}`);\r\n }\r\n\r\n const data = await response.json();\r\n console.log('🔍 Raw API response:', data);\r\n\r\n // Extract the response text and FAQs properly\r\n let responseText = 'No response from agent';\r\n let faqs: FAQ[] | undefined = undefined;\r\n\r\n if (data && typeof data === 'object' && data.response && typeof data.response === 'string') {\r\n console.log('📝 data.response type:', typeof data.response);\r\n console.log('📝 data.response preview:', data.response.substring(0, 100));\r\n\r\n // Check if data.response contains stringified JSON\r\n const trimmedResponse = data.response.trim();\r\n if (trimmedResponse.startsWith('{') || trimmedResponse.startsWith('[')) {\r\n console.log('🔄 Detected stringified JSON, parsing...');\r\n\r\n try {\r\n // First attempt: standard JSON.parse\r\n let innerData = JSON.parse(data.response);\r\n console.log('✅ Parsed inner data with JSON.parse');\r\n\r\n if (innerData && innerData.response && typeof innerData.response === 'string') {\r\n responseText = innerData.response;\r\n faqs = innerData.faqs_used || undefined;\r\n console.log('✅ Extracted text length:', responseText.length);\r\n console.log('✅ Extracted FAQs count:', faqs?.length || 0);\r\n } else {\r\n responseText = data.response;\r\n faqs = data.faqs_used || undefined;\r\n }\r\n } catch (parseError) {\r\n console.warn('⚠️ JSON.parse failed, using regex extraction...', parseError);\r\n\r\n // Backend has malformed JSON - extract response text\r\n const responsePattern = /\"response\"\\s*:\\s*\"([^\"]*(?:\\\\.[^\"]*)*)\"/s;\r\n const responseMatch = data.response.match(responsePattern);\r\n\r\n if (responseMatch) {\r\n responseText = responseMatch[1]\r\n .replace(/\\\\n/g, '\\n')\r\n .replace(/\\\\t/g, '\\t')\r\n .replace(/\\\\r/g, '\\r')\r\n .replace(/\\\\\"/g, '\"')\r\n .replace(/\\\\\\\\/g, '\\\\');\r\n console.log('✅ Extracted response text, length:', responseText.length);\r\n } else {\r\n console.error('❌ Could not extract response');\r\n responseText = 'Error: Could not parse response';\r\n }\r\n\r\n // Extract FAQs array\r\n const faqsPattern = /\"faqs_used\"\\s*:\\s*(\\[[^\\]]*\\])/s;\r\n const faqsMatch = data.response.match(faqsPattern);\r\n\r\n if (faqsMatch) {\r\n try {\r\n faqs = JSON.parse(faqsMatch[1]);\r\n console.log('✅ Extracted FAQs, count:', faqs?.length || 0);\r\n } catch {\r\n console.log('⚠️ Could not parse FAQs, trying multiline...');\r\n // FAQs might span multiple lines\r\n const faqsMultiPattern = /\"faqs_used\"\\s*:\\s*(\\[[\\s\\S]*?\\n\\s*\\])/;\r\n const faqsMultiMatch = data.response.match(faqsMultiPattern);\r\n if (faqsMultiMatch) {\r\n try {\r\n faqs = JSON.parse(faqsMultiMatch[1]);\r\n console.log('✅ Extracted multi-line FAQs, count:', faqs?.length || 0);\r\n } catch {\r\n faqs = undefined;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Not JSON, direct text response\r\n console.log('📄 Direct text response (not JSON)');\r\n responseText = data.response;\r\n faqs = data.faqs_used || undefined;\r\n }\r\n } else if (typeof data === 'string') {\r\n console.log('📄 Response is a plain string');\r\n responseText = data;\r\n } else if (data && typeof data === 'object') {\r\n // Fallback for other formats\r\n console.warn('⚠️ Unexpected format, using fallback');\r\n responseText = data.message || data.answer || 'Error: Unexpected response format';\r\n }\r\n\r\n console.log('🎯 Final responseText length:', responseText.length);\r\n console.log('🎯 Final responseText preview:', responseText.substring(0, 100));\r\n console.log('🎯 Final FAQs:', faqs);\r\n\r\n const assistantMessage: Message = {\r\n id: (Date.now() + 1).toString(),\r\n role: 'assistant',\r\n content: responseText,\r\n faqs: faqs,\r\n };\r\n\r\n this.messages = [...this.messages, assistantMessage];\r\n\r\n // Dispatch response-received event\r\n this.dispatchEvent(new CustomEvent('response-received', {\r\n detail: assistantMessage,\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n } catch (err) {\r\n console.error('Backend connection failed:', err);\r\n\r\n const errorMessage: Message = {\r\n id: (Date.now() + 1).toString(),\r\n role: 'assistant',\r\n content: `Error: ${err instanceof Error ? err.message : 'Unknown error'}\\n\\nPlease check your API endpoint configuration.`,\r\n };\r\n\r\n this.messages = [...this.messages, errorMessage];\r\n\r\n // Dispatch error event\r\n this.dispatchEvent(new CustomEvent('error', {\r\n detail: err,\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n } finally {\r\n this.isLoading = false;\r\n }\r\n }\r\n\r\n private renderChatUI() {\r\n return html`\r\n <!-- Header -->\r\n <div class=\"header\">\r\n <div class=\"header-content\">\r\n <h1 class=\"title\">${this.chatTitle}</h1>\r\n </div>\r\n </div>\r\n\r\n <!-- Messages Area -->\r\n <div class=\"messages-area\" style=\"${this.backgroundImageUrl ? `--background-image-url: url('${this.backgroundImageUrl}')` : ''}\">\r\n <div class=\"messages-container\">\r\n ${this.messages.length === 0 ? html`\r\n <div class=\"empty-state\">\r\n <p>How can I help you today?</p>\r\n </div>\r\n ` : ''}\r\n\r\n ${repeat(this.messages, (msg) => msg.id, (msg) => html`\r\n <div class=${classMap({\r\n message: true,\r\n user: msg.role === 'user',\r\n assistant: msg.role === 'assistant'\r\n })}>\r\n <div class=\"avatar\">\r\n ${msg.role === 'user'\r\n ? 'U'\r\n : this.botAvatarUrl\r\n ? html`<img src=\"${this.botAvatarUrl}\" alt=\"AI\" class=\"avatar-image\" />`\r\n : 'AI'}\r\n </div>\r\n <div class=\"message-content\">\r\n <p class=\"message-text\">${msg.content}</p>\r\n ${msg.role === 'assistant' && msg.faqs && msg.faqs.length > 0 ? html`\r\n <div class=\"faq-section\">\r\n <p class=\"faq-title\">Related FAQs:</p>\r\n <ul class=\"faq-list\">\r\n ${msg.faqs.map(faq => html`\r\n <li class=\"faq-item\" @click=${() => this.handleFAQClick(faq.question)}>\r\n ${faq.question}\r\n </li>\r\n `)}\r\n </ul>\r\n </div>\r\n ` : ''}\r\n </div>\r\n </div>\r\n `)}\r\n\r\n ${this.isLoading ? html`\r\n <div class=\"loading\">\r\n <div class=\"avatar\">\r\n ${this.botAvatarUrl\r\n ? html`<img src=\"${this.botAvatarUrl}\" alt=\"AI\" class=\"avatar-image\" />`\r\n : 'AI'}\r\n </div>\r\n <div class=\"message-content\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n </div>\r\n ` : ''}\r\n\r\n <div ${(el: Element) => this.messagesEndRef = el as HTMLDivElement}></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Input Area -->\r\n <div class=\"input-area\">\r\n <form class=\"input-form\" @submit=${this.handleSubmit}>\r\n <input\r\n type=\"text\"\r\n class=\"input-field\"\r\n placeholder=\"Type your message...\"\r\n .value=${this.input}\r\n @input=${this.handleInput}\r\n ?disabled=${this.isLoading}\r\n />\r\n <button\r\n type=\"submit\"\r\n class=\"send-button\"\r\n ?disabled=${this.isLoading || !this.input.trim()}\r\n aria-label=\"Send message\"\r\n >\r\n ${this.isLoading ? html`\r\n <div class=\"spinner\" style=\"border-color: #fff; border-top-color: transparent;\"></div>\r\n ` : html`\r\n <svg class=\"send-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\r\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\r\n </svg>\r\n `}\r\n </button>\r\n </form>\r\n </div>\r\n\r\n <!-- Version -->\r\n <div class=\"version-tag\">v${VERSION}</div>\r\n `;\r\n }\r\n\r\n render() {\r\n if (this.mode === 'widget') {\r\n return html`\r\n <div class=\"widget-container\">\r\n <!-- Chat Window -->\r\n <div class=${classMap({ 'widget-window': true, 'open': this.isOpen })}>\r\n ${this.renderChatUI()}\r\n </div>\r\n\r\n <!-- Toggle Button -->\r\n <button\r\n class=\"widget-button\"\r\n @click=${this.toggleWidget}\r\n aria-label=${this.isOpen ? 'Close chat' : 'Open chat'}\r\n >\r\n ${this.isOpen ? html`\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n ` : html`\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <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>\r\n </svg>\r\n `}\r\n </button>\r\n </div>\r\n `;\r\n }\r\n\r\n // Fullscreen mode\r\n return this.renderChatUI();\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'ai-chat': AIChat;\r\n }\r\n}\r\n"]}
package/dist/index.mjs CHANGED
@@ -13,7 +13,7 @@ var __decorateClass = (decorators, target, key, kind) => {
13
13
  if (kind && result) __defProp(target, key, result);
14
14
  return result;
15
15
  };
16
- var VERSION = "0.2.2";
16
+ var VERSION = "0.2.4";
17
17
  var AIChat = class extends LitElement {
18
18
  constructor() {
19
19
  super();
@@ -23,6 +23,8 @@ var AIChat = class extends LitElement {
23
23
  this.theme = "light";
24
24
  this.mode = "fullscreen";
25
25
  this.initialMessages = [];
26
+ this.botAvatarUrl = "";
27
+ this.backgroundImageUrl = "";
26
28
  this.messages = [];
27
29
  this.input = "";
28
30
  this.isLoading = false;
@@ -51,6 +53,12 @@ var AIChat = class extends LitElement {
51
53
  handleInput(e) {
52
54
  this.input = e.target.value;
53
55
  }
56
+ handleFAQClick(question) {
57
+ if (this.isLoading) return;
58
+ this.input = question;
59
+ const submitEvent = new Event("submit", { cancelable: true });
60
+ this.handleSubmit(submitEvent);
61
+ }
54
62
  async handleSubmit(e) {
55
63
  e.preventDefault();
56
64
  if (!this.input.trim() || this.isLoading || !this.apiUrl) return;
@@ -82,16 +90,79 @@ var AIChat = class extends LitElement {
82
90
  throw new Error(`Backend error: ${response.status} ${errorText}`);
83
91
  }
84
92
  const data = await response.json();
93
+ console.log("\u{1F50D} Raw API response:", data);
85
94
  let responseText = "No response from agent";
86
- if (typeof data === "string") {
95
+ let faqs = void 0;
96
+ if (data && typeof data === "object" && data.response && typeof data.response === "string") {
97
+ console.log("\u{1F4DD} data.response type:", typeof data.response);
98
+ console.log("\u{1F4DD} data.response preview:", data.response.substring(0, 100));
99
+ const trimmedResponse = data.response.trim();
100
+ if (trimmedResponse.startsWith("{") || trimmedResponse.startsWith("[")) {
101
+ console.log("\u{1F504} Detected stringified JSON, parsing...");
102
+ try {
103
+ let innerData = JSON.parse(data.response);
104
+ console.log("\u2705 Parsed inner data with JSON.parse");
105
+ if (innerData && innerData.response && typeof innerData.response === "string") {
106
+ responseText = innerData.response;
107
+ faqs = innerData.faqs_used || void 0;
108
+ console.log("\u2705 Extracted text length:", responseText.length);
109
+ console.log("\u2705 Extracted FAQs count:", faqs?.length || 0);
110
+ } else {
111
+ responseText = data.response;
112
+ faqs = data.faqs_used || void 0;
113
+ }
114
+ } catch (parseError) {
115
+ console.warn("\u26A0\uFE0F JSON.parse failed, using regex extraction...", parseError);
116
+ const responsePattern = /"response"\s*:\s*"([^"]*(?:\\.[^"]*)*)"/s;
117
+ const responseMatch = data.response.match(responsePattern);
118
+ if (responseMatch) {
119
+ responseText = responseMatch[1].replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\r/g, "\r").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
120
+ console.log("\u2705 Extracted response text, length:", responseText.length);
121
+ } else {
122
+ console.error("\u274C Could not extract response");
123
+ responseText = "Error: Could not parse response";
124
+ }
125
+ const faqsPattern = /"faqs_used"\s*:\s*(\[[^\]]*\])/s;
126
+ const faqsMatch = data.response.match(faqsPattern);
127
+ if (faqsMatch) {
128
+ try {
129
+ faqs = JSON.parse(faqsMatch[1]);
130
+ console.log("\u2705 Extracted FAQs, count:", faqs?.length || 0);
131
+ } catch {
132
+ console.log("\u26A0\uFE0F Could not parse FAQs, trying multiline...");
133
+ const faqsMultiPattern = /"faqs_used"\s*:\s*(\[[\s\S]*?\n\s*\])/;
134
+ const faqsMultiMatch = data.response.match(faqsMultiPattern);
135
+ if (faqsMultiMatch) {
136
+ try {
137
+ faqs = JSON.parse(faqsMultiMatch[1]);
138
+ console.log("\u2705 Extracted multi-line FAQs, count:", faqs?.length || 0);
139
+ } catch {
140
+ faqs = void 0;
141
+ }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ } else {
147
+ console.log("\u{1F4C4} Direct text response (not JSON)");
148
+ responseText = data.response;
149
+ faqs = data.faqs_used || void 0;
150
+ }
151
+ } else if (typeof data === "string") {
152
+ console.log("\u{1F4C4} Response is a plain string");
87
153
  responseText = data;
88
154
  } else if (data && typeof data === "object") {
89
- responseText = data.response || data.message || data.answer || JSON.stringify(data);
155
+ console.warn("\u26A0\uFE0F Unexpected format, using fallback");
156
+ responseText = data.message || data.answer || "Error: Unexpected response format";
90
157
  }
158
+ console.log("\u{1F3AF} Final responseText length:", responseText.length);
159
+ console.log("\u{1F3AF} Final responseText preview:", responseText.substring(0, 100));
160
+ console.log("\u{1F3AF} Final FAQs:", faqs);
91
161
  const assistantMessage = {
92
162
  id: (Date.now() + 1).toString(),
93
163
  role: "assistant",
94
- content: responseText
164
+ content: responseText,
165
+ faqs
95
166
  };
96
167
  this.messages = [...this.messages, assistantMessage];
97
168
  this.dispatchEvent(new CustomEvent("response-received", {
@@ -104,7 +175,7 @@ var AIChat = class extends LitElement {
104
175
  const errorMessage = {
105
176
  id: (Date.now() + 1).toString(),
106
177
  role: "assistant",
107
- content: `Error: ${err.message}
178
+ content: `Error: ${err instanceof Error ? err.message : "Unknown error"}
108
179
 
109
180
  Please check your API endpoint configuration.`
110
181
  };
@@ -128,7 +199,7 @@ Please check your API endpoint configuration.`
128
199
  </div>
129
200
 
130
201
  <!-- Messages Area -->
131
- <div class="messages-area">
202
+ <div class="messages-area" style="${this.backgroundImageUrl ? `--background-image-url: url('${this.backgroundImageUrl}')` : ""}">
132
203
  <div class="messages-container">
133
204
  ${this.messages.length === 0 ? html`
134
205
  <div class="empty-state">
@@ -143,17 +214,31 @@ Please check your API endpoint configuration.`
143
214
  assistant: msg.role === "assistant"
144
215
  })}>
145
216
  <div class="avatar">
146
- ${msg.role === "user" ? "U" : "AI"}
217
+ ${msg.role === "user" ? "U" : this.botAvatarUrl ? html`<img src="${this.botAvatarUrl}" alt="AI" class="avatar-image" />` : "AI"}
147
218
  </div>
148
219
  <div class="message-content">
149
220
  <p class="message-text">${msg.content}</p>
221
+ ${msg.role === "assistant" && msg.faqs && msg.faqs.length > 0 ? html`
222
+ <div class="faq-section">
223
+ <p class="faq-title">Related FAQs:</p>
224
+ <ul class="faq-list">
225
+ ${msg.faqs.map((faq) => html`
226
+ <li class="faq-item" @click=${() => this.handleFAQClick(faq.question)}>
227
+ ${faq.question}
228
+ </li>
229
+ `)}
230
+ </ul>
231
+ </div>
232
+ ` : ""}
150
233
  </div>
151
234
  </div>
152
235
  `)}
153
236
 
154
237
  ${this.isLoading ? html`
155
238
  <div class="loading">
156
- <div class="avatar">AI</div>
239
+ <div class="avatar">
240
+ ${this.botAvatarUrl ? html`<img src="${this.botAvatarUrl}" alt="AI" class="avatar-image" />` : "AI"}
241
+ </div>
157
242
  <div class="message-content">
158
243
  <div class="spinner"></div>
159
244
  </div>
@@ -349,6 +434,23 @@ AIChat.styles = css`
349
434
  flex: 1;
350
435
  overflow-y: auto;
351
436
  padding: 1.5rem 1rem;
437
+ position: relative;
438
+ }
439
+
440
+ .messages-area::before {
441
+ content: '';
442
+ position: absolute;
443
+ top: 0;
444
+ left: 0;
445
+ right: 0;
446
+ bottom: 0;
447
+ background-image: var(--background-image-url);
448
+ background-size: 200px auto 60%;
449
+ background-position: center center;
450
+ background-repeat: no-repeat;
451
+ opacity: 0.5;
452
+ pointer-events: none;
453
+ z-index: 0;
352
454
  }
353
455
 
354
456
  .messages-container {
@@ -357,6 +459,8 @@ AIChat.styles = css`
357
459
  display: flex;
358
460
  flex-direction: column;
359
461
  gap: 1.5rem;
462
+ position: relative;
463
+ z-index: 1;
360
464
  }
361
465
 
362
466
  .empty-state {
@@ -395,12 +499,19 @@ AIChat.styles = css`
395
499
  flex-shrink: 0;
396
500
  font-weight: 500;
397
501
  font-size: 0.875rem;
502
+ overflow: hidden;
398
503
  }
399
504
 
400
505
  :host([theme="dark"]) .avatar {
401
506
  background: #3f3f46;
402
507
  }
403
508
 
509
+ .avatar-image {
510
+ width: 100%;
511
+ height: 100%;
512
+ object-fit: cover;
513
+ }
514
+
404
515
  .message-content {
405
516
  max-width: 36rem;
406
517
  padding: 0.75rem 1rem;
@@ -429,6 +540,59 @@ AIChat.styles = css`
429
540
  margin: 0;
430
541
  }
431
542
 
543
+ .faq-section {
544
+ margin-top: 1rem;
545
+ padding-top: 1rem;
546
+ border-top: 1px solid #e4e4e7;
547
+ }
548
+
549
+ :host([theme="dark"]) .faq-section {
550
+ border-top-color: #3f3f46;
551
+ }
552
+
553
+ .faq-title {
554
+ font-size: 0.875rem;
555
+ font-weight: 500;
556
+ color: #3f3f46;
557
+ margin: 0 0 0.5rem 0;
558
+ }
559
+
560
+ :host([theme="dark"]) .faq-title {
561
+ color: #d4d4d8;
562
+ }
563
+
564
+ .faq-list {
565
+ list-style: none;
566
+ padding: 0;
567
+ margin: 0;
568
+ display: flex;
569
+ flex-direction: column;
570
+ gap: 0.5rem;
571
+ }
572
+
573
+ .faq-item {
574
+ font-size: 0.875rem;
575
+ color: #52525b;
576
+ padding: 0.5rem;
577
+ border-radius: 0.375rem;
578
+ cursor: pointer;
579
+ transition: background-color 0.2s, color 0.2s;
580
+ }
581
+
582
+ .faq-item:hover {
583
+ background-color: #f4f4f5;
584
+ color: #18181b;
585
+ }
586
+
587
+ :host([theme="dark"]) .faq-item {
588
+ color: #a1a1aa;
589
+ }
590
+
591
+ :host([theme="dark"]) .faq-item:hover {
592
+ background-color: #27272a;
593
+ color: #fafafa;
594
+ }
595
+
432
596
  .loading {
433
597
  display: flex;
434
598
  gap: 1rem;
@@ -541,7 +705,9 @@ AIChat.properties = {
541
705
  chatTitle: { type: String, attribute: "title" },
542
706
  theme: { type: String },
543
707
  mode: { type: String, reflect: true },
544
- initialMessages: { type: Array }
708
+ initialMessages: { type: Array },
709
+ botAvatarUrl: { type: String, attribute: "bot-avatar-url" },
710
+ backgroundImageUrl: { type: String, attribute: "background-image-url" }
545
711
  };
546
712
  __decorateClass([
547
713
  state()
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/ai-chat.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { LitElement, html, css, PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { classMap } from 'lit/directives/class-map.js';\n\nconst VERSION = '0.2.2';\n\nexport interface Message {\n id: string;\n role: 'user' | 'assistant';\n content: string;\n}\n\n/**\n * AI Chat Web Component\n *\n * @fires message-sent - Fired when user sends a message\n * @fires response-received - Fired when AI responds\n * @fires error - Fired when an error occurs\n *\n * @example\n * ```html\n * <ai-chat\n * api-url=\"https://api.example.com\"\n * session-id=\"user-123\"\n * title=\"My AI Assistant\">\n * </ai-chat>\n * ```\n */\n@customElement('ai-chat')\nexport class AIChat extends LitElement {\n static styles = css`\n :host {\n font-family: system-ui, -apple-system, sans-serif;\n color: #09090b;\n }\n\n /* Fullscreen mode (default) */\n :host([mode=\"fullscreen\"]) {\n display: flex;\n flex-direction: column;\n height: 100vh;\n background: #fafafa;\n }\n\n :host([mode=\"fullscreen\"][theme=\"dark\"]) {\n background: #000;\n color: #fafafa;\n }\n\n /* Widget mode */\n :host([mode=\"widget\"]) {\n position: fixed;\n bottom: 20px;\n right: 20px;\n z-index: 9999;\n }\n\n .widget-container {\n position: relative;\n }\n\n .widget-button {\n width: 60px;\n height: 60px;\n border-radius: 50%;\n background: #2563eb;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n transition: transform 0.2s, box-shadow 0.2s;\n }\n\n .widget-button:hover {\n transform: scale(1.05);\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\n }\n\n .widget-button svg {\n width: 28px;\n height: 28px;\n color: white;\n }\n\n .widget-window {\n position: absolute;\n bottom: 80px;\n right: 0;\n width: 380px;\n height: 600px;\n background: #fff;\n border-radius: 12px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);\n display: flex;\n flex-direction: column;\n overflow: hidden;\n opacity: 0;\n transform: scale(0.9) translateY(20px);\n pointer-events: none;\n transition: opacity 0.2s, transform 0.2s;\n }\n\n .widget-window.open {\n opacity: 1;\n transform: scale(1) translateY(0);\n pointer-events: all;\n }\n\n :host([theme=\"dark\"]) .widget-window {\n background: #18181b;\n color: #fafafa;\n }\n\n @media (max-width: 480px) {\n .widget-window {\n width: calc(100vw - 40px);\n height: calc(100vh - 100px);\n bottom: 80px;\n right: 0;\n }\n }\n\n .header {\n border-bottom: 1px solid #e4e4e7;\n background: #fff;\n padding: 1rem;\n }\n\n :host([theme=\"dark\"]) .header {\n border-bottom-color: #27272a;\n background: #18181b;\n }\n\n .header-content {\n max-width: 56rem;\n margin: 0 auto;\n }\n\n .title {\n font-size: 1.25rem;\n font-weight: 600;\n margin: 0;\n }\n\n .messages-area {\n flex: 1;\n overflow-y: auto;\n padding: 1.5rem 1rem;\n }\n\n .messages-container {\n max-width: 56rem;\n margin: 0 auto;\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n }\n\n .empty-state {\n text-align: center;\n color: #71717a;\n margin-top: 5rem;\n }\n\n :host([theme=\"dark\"]) .empty-state {\n color: #a1a1aa;\n }\n\n .empty-state p {\n font-size: 1.5rem;\n font-weight: 500;\n margin: 0;\n }\n\n .message {\n display: flex;\n gap: 1rem;\n }\n\n .message.user {\n flex-direction: row-reverse;\n }\n\n .avatar {\n width: 2.5rem;\n height: 2.5rem;\n border-radius: 9999px;\n background: #e4e4e7;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n font-weight: 500;\n font-size: 0.875rem;\n }\n\n :host([theme=\"dark\"]) .avatar {\n background: #3f3f46;\n }\n\n .message-content {\n max-width: 36rem;\n padding: 0.75rem 1rem;\n border-radius: 1rem;\n }\n\n .message.user .message-content {\n background: #2563eb;\n color: #fff;\n }\n\n .message.assistant .message-content {\n background: #fff;\n border: 1px solid #e4e4e7;\n color: #09090b;\n }\n\n :host([theme=\"dark\"]) .message.assistant .message-content {\n background: #27272a;\n border-color: #3f3f46;\n color: #fafafa;\n }\n\n .message-text {\n white-space: pre-wrap;\n margin: 0;\n }\n\n .loading {\n display: flex;\n gap: 1rem;\n }\n\n .spinner {\n display: inline-block;\n width: 1.25rem;\n height: 1.25rem;\n border: 2px solid #e4e4e7;\n border-top-color: #71717a;\n border-radius: 50%;\n animation: spin 1s linear infinite;\n }\n\n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n\n .input-area {\n border-top: 1px solid #e4e4e7;\n background: #fff;\n padding: 1rem;\n }\n\n :host([theme=\"dark\"]) .input-area {\n border-top-color: #27272a;\n background: #000;\n }\n\n .input-form {\n max-width: 56rem;\n margin: 0 auto;\n display: flex;\n gap: 0.75rem;\n }\n\n .input-field {\n flex: 1;\n height: 3rem;\n padding: 0 1rem;\n border: 1px solid #e4e4e7;\n border-radius: 0.5rem;\n font-size: 1rem;\n font-family: inherit;\n background: #fff;\n color: #09090b;\n }\n\n :host([theme=\"dark\"]) .input-field {\n border-color: #3f3f46;\n background: #18181b;\n color: #fafafa;\n }\n\n .input-field:focus {\n outline: 2px solid #2563eb;\n outline-offset: 2px;\n }\n\n .input-field:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .send-button {\n width: 3rem;\n height: 3rem;\n border-radius: 9999px;\n border: none;\n background: #2563eb;\n color: #fff;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background 0.2s;\n }\n\n .send-button:hover:not(:disabled) {\n background: #1d4ed8;\n }\n\n .send-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .send-icon {\n width: 1.25rem;\n height: 1.25rem;\n }\n\n .version-tag {\n text-align: center;\n padding: 0.5rem;\n font-size: 0.75rem;\n color: #71717a;\n border-top: 1px solid #e4e4e7;\n }\n\n :host([theme=\"dark\"]) .version-tag {\n color: #a1a1aa;\n border-top-color: #27272a;\n }\n `;\n\n declare apiUrl: string;\n declare sessionId: string;\n declare chatTitle: string;\n declare theme: 'light' | 'dark';\n declare mode: 'fullscreen' | 'widget';\n declare initialMessages: Message[];\n\n @state()\n private declare messages: Message[];\n\n @state()\n private declare input: string;\n\n @state()\n private declare isLoading: boolean;\n\n @state()\n private declare isOpen: boolean;\n\n private messagesEndRef?: HTMLDivElement;\n\n static override properties = {\n apiUrl: { type: String, attribute: 'api-url' },\n sessionId: { type: String, attribute: 'session-id' },\n chatTitle: { type: String, attribute: 'title' },\n theme: { type: String },\n mode: { type: String, reflect: true },\n initialMessages: { type: Array },\n };\n\n constructor() {\n super();\n this.apiUrl = '';\n this.sessionId = 'default-session';\n this.chatTitle = 'My AI Agent';\n this.theme = 'light';\n this.mode = 'fullscreen';\n this.initialMessages = [];\n this.messages = [];\n this.input = '';\n this.isLoading = false;\n this.isOpen = false;\n }\n\n private toggleWidget() {\n this.isOpen = !this.isOpen;\n }\n\n connectedCallback() {\n super.connectedCallback();\n if (this.initialMessages && this.initialMessages.length > 0) {\n this.messages = [...this.initialMessages];\n }\n }\n\n updated(changedProperties: PropertyValues) {\n super.updated(changedProperties);\n if (changedProperties.has('messages')) {\n this.scrollToBottom();\n }\n }\n\n private scrollToBottom() {\n requestAnimationFrame(() => {\n this.messagesEndRef?.scrollIntoView({ behavior: 'smooth' });\n });\n }\n\n private handleInput(e: Event) {\n this.input = (e.target as HTMLInputElement).value;\n }\n\n private async handleSubmit(e: Event) {\n e.preventDefault();\n\n if (!this.input.trim() || this.isLoading || !this.apiUrl) return;\n\n const userMessage: Message = {\n id: Date.now().toString(),\n role: 'user',\n content: this.input.trim(),\n };\n\n this.messages = [...this.messages, userMessage];\n const questionText = this.input.trim();\n this.input = '';\n this.isLoading = true;\n\n // Dispatch message-sent event\n this.dispatchEvent(new CustomEvent('message-sent', {\n detail: userMessage,\n bubbles: true,\n composed: true,\n }));\n\n try {\n const response = await fetch(`${this.apiUrl}/ask`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n session_id: this.sessionId,\n question: questionText,\n }),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n throw new Error(`Backend error: ${response.status} ${errorText}`);\n }\n\n const data = await response.json();\n\n // Extract the response text properly\n let responseText = 'No response from agent';\n\n if (typeof data === 'string') {\n responseText = data;\n } else if (data && typeof data === 'object') {\n // Handle the server response format: { response: \"text\", tags_used: [] }\n responseText = data.response || data.message || data.answer || JSON.stringify(data);\n }\n\n const assistantMessage: Message = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: responseText,\n };\n\n this.messages = [...this.messages, assistantMessage];\n\n // Dispatch response-received event\n this.dispatchEvent(new CustomEvent('response-received', {\n detail: assistantMessage,\n bubbles: true,\n composed: true,\n }));\n } catch (err: any) {\n console.error('Backend connection failed:', err);\n\n const errorMessage: Message = {\n id: (Date.now() + 1).toString(),\n role: 'assistant',\n content: `Error: ${err.message}\\n\\nPlease check your API endpoint configuration.`,\n };\n\n this.messages = [...this.messages, errorMessage];\n\n // Dispatch error event\n this.dispatchEvent(new CustomEvent('error', {\n detail: err,\n bubbles: true,\n composed: true,\n }));\n } finally {\n this.isLoading = false;\n }\n }\n\n private renderChatUI() {\n return html`\n <!-- Header -->\n <div class=\"header\">\n <div class=\"header-content\">\n <h1 class=\"title\">${this.chatTitle}</h1>\n </div>\n </div>\n\n <!-- Messages Area -->\n <div class=\"messages-area\">\n <div class=\"messages-container\">\n ${this.messages.length === 0 ? html`\n <div class=\"empty-state\">\n <p>How can I help you today?</p>\n </div>\n ` : ''}\n\n ${repeat(this.messages, (msg) => msg.id, (msg) => html`\n <div class=${classMap({\n message: true,\n user: msg.role === 'user',\n assistant: msg.role === 'assistant'\n })}>\n <div class=\"avatar\">\n ${msg.role === 'user' ? 'U' : 'AI'}\n </div>\n <div class=\"message-content\">\n <p class=\"message-text\">${msg.content}</p>\n </div>\n </div>\n `)}\n\n ${this.isLoading ? html`\n <div class=\"loading\">\n <div class=\"avatar\">AI</div>\n <div class=\"message-content\">\n <div class=\"spinner\"></div>\n </div>\n </div>\n ` : ''}\n\n <div ${(el: Element) => this.messagesEndRef = el as HTMLDivElement}></div>\n </div>\n </div>\n\n <!-- Input Area -->\n <div class=\"input-area\">\n <form class=\"input-form\" @submit=${this.handleSubmit}>\n <input\n type=\"text\"\n class=\"input-field\"\n placeholder=\"Type your message...\"\n .value=${this.input}\n @input=${this.handleInput}\n ?disabled=${this.isLoading}\n />\n <button\n type=\"submit\"\n class=\"send-button\"\n ?disabled=${this.isLoading || !this.input.trim()}\n aria-label=\"Send message\"\n >\n ${this.isLoading ? html`\n <div class=\"spinner\" style=\"border-color: #fff; border-top-color: transparent;\"></div>\n ` : html`\n <svg class=\"send-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\n </svg>\n `}\n </button>\n </form>\n </div>\n\n <!-- Version -->\n <div class=\"version-tag\">v${VERSION}</div>\n `;\n }\n\n render() {\n if (this.mode === 'widget') {\n return html`\n <div class=\"widget-container\">\n <!-- Chat Window -->\n <div class=${classMap({ 'widget-window': true, 'open': this.isOpen })}>\n ${this.renderChatUI()}\n </div>\n\n <!-- Toggle Button -->\n <button\n class=\"widget-button\"\n @click=${this.toggleWidget}\n aria-label=${this.isOpen ? 'Close chat' : 'Open chat'}\n >\n ${this.isOpen ? html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n ` : html`\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <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>\n </svg>\n `}\n </button>\n </div>\n `;\n }\n\n // Fullscreen mode\n return this.renderChatUI();\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ai-chat': AIChat;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/components/ai-chat.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { LitElement, html, css, PropertyValues } from 'lit';\r\nimport { customElement, state } from 'lit/decorators.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport { classMap } from 'lit/directives/class-map.js';\r\n\r\nconst VERSION = '0.2.4';\r\n\r\nexport interface FAQ {\r\n \"no.\": string;\r\n question: string;\r\n}\r\n\r\nexport interface Message {\r\n id: string;\r\n role: 'user' | 'assistant';\r\n content: string;\r\n faqs?: FAQ[];\r\n}\r\n\r\n/**\r\n * AI Chat Web Component\r\n *\r\n * @fires message-sent - Fired when user sends a message\r\n * @fires response-received - Fired when AI responds\r\n * @fires error - Fired when an error occurs\r\n *\r\n * @example\r\n * ```html\r\n * <ai-chat\r\n * api-url=\"https://api.example.com\"\r\n * session-id=\"user-123\"\r\n * title=\"My AI Assistant\">\r\n * </ai-chat>\r\n * ```\r\n */\r\n@customElement('ai-chat')\r\nexport class AIChat extends LitElement {\r\n static styles = css`\r\n :host {\r\n font-family: system-ui, -apple-system, sans-serif;\r\n color: #09090b;\r\n }\r\n\r\n /* Fullscreen mode (default) */\r\n :host([mode=\"fullscreen\"]) {\r\n display: flex;\r\n flex-direction: column;\r\n height: 100vh;\r\n background: #fafafa;\r\n }\r\n\r\n :host([mode=\"fullscreen\"][theme=\"dark\"]) {\r\n background: #000;\r\n color: #fafafa;\r\n }\r\n\r\n /* Widget mode */\r\n :host([mode=\"widget\"]) {\r\n position: fixed;\r\n bottom: 20px;\r\n right: 20px;\r\n z-index: 9999;\r\n }\r\n\r\n .widget-container {\r\n position: relative;\r\n }\r\n\r\n .widget-button {\r\n width: 60px;\r\n height: 60px;\r\n border-radius: 50%;\r\n background: #2563eb;\r\n border: none;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\r\n transition: transform 0.2s, box-shadow 0.2s;\r\n }\r\n\r\n .widget-button:hover {\r\n transform: scale(1.05);\r\n box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);\r\n }\r\n\r\n .widget-button svg {\r\n width: 28px;\r\n height: 28px;\r\n color: white;\r\n }\r\n\r\n .widget-window {\r\n position: absolute;\r\n bottom: 80px;\r\n right: 0;\r\n width: 380px;\r\n height: 600px;\r\n background: #fff;\r\n border-radius: 12px;\r\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.12);\r\n display: flex;\r\n flex-direction: column;\r\n overflow: hidden;\r\n opacity: 0;\r\n transform: scale(0.9) translateY(20px);\r\n pointer-events: none;\r\n transition: opacity 0.2s, transform 0.2s;\r\n }\r\n\r\n .widget-window.open {\r\n opacity: 1;\r\n transform: scale(1) translateY(0);\r\n pointer-events: all;\r\n }\r\n\r\n :host([theme=\"dark\"]) .widget-window {\r\n background: #18181b;\r\n color: #fafafa;\r\n }\r\n\r\n @media (max-width: 480px) {\r\n .widget-window {\r\n width: calc(100vw - 40px);\r\n height: calc(100vh - 100px);\r\n bottom: 80px;\r\n right: 0;\r\n }\r\n }\r\n\r\n .header {\r\n border-bottom: 1px solid #e4e4e7;\r\n background: #fff;\r\n padding: 1rem;\r\n }\r\n\r\n :host([theme=\"dark\"]) .header {\r\n border-bottom-color: #27272a;\r\n background: #18181b;\r\n }\r\n\r\n .header-content {\r\n max-width: 56rem;\r\n margin: 0 auto;\r\n }\r\n\r\n .title {\r\n font-size: 1.25rem;\r\n font-weight: 600;\r\n margin: 0;\r\n }\r\n\r\n .messages-area {\r\n flex: 1;\r\n overflow-y: auto;\r\n padding: 1.5rem 1rem;\r\n position: relative;\r\n }\r\n\r\n .messages-area::before {\r\n content: '';\r\n position: absolute;\r\n top: 0;\r\n left: 0;\r\n right: 0;\r\n bottom: 0;\r\n background-image: var(--background-image-url);\r\n background-size: 200px auto 60%;\r\n background-position: center center;\r\n background-repeat: no-repeat;\r\n opacity: 0.5;\r\n pointer-events: none;\r\n z-index: 0;\r\n }\r\n\r\n .messages-container {\r\n max-width: 56rem;\r\n margin: 0 auto;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 1.5rem;\r\n position: relative;\r\n z-index: 1;\r\n }\r\n\r\n .empty-state {\r\n text-align: center;\r\n color: #71717a;\r\n margin-top: 5rem;\r\n }\r\n\r\n :host([theme=\"dark\"]) .empty-state {\r\n color: #a1a1aa;\r\n }\r\n\r\n .empty-state p {\r\n font-size: 1.5rem;\r\n font-weight: 500;\r\n margin: 0;\r\n }\r\n\r\n .message {\r\n display: flex;\r\n gap: 1rem;\r\n }\r\n\r\n .message.user {\r\n flex-direction: row-reverse;\r\n }\r\n\r\n .avatar {\r\n width: 2.5rem;\r\n height: 2.5rem;\r\n border-radius: 9999px;\r\n background: #e4e4e7;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n font-weight: 500;\r\n font-size: 0.875rem;\r\n overflow: hidden;\r\n }\r\n\r\n :host([theme=\"dark\"]) .avatar {\r\n background: #3f3f46;\r\n }\r\n\r\n .avatar-image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: cover;\r\n }\r\n\r\n .message-content {\r\n max-width: 36rem;\r\n padding: 0.75rem 1rem;\r\n border-radius: 1rem;\r\n }\r\n\r\n .message.user .message-content {\r\n background: #2563eb;\r\n color: #fff;\r\n }\r\n\r\n .message.assistant .message-content {\r\n background: #fff;\r\n border: 1px solid #e4e4e7;\r\n color: #09090b;\r\n }\r\n\r\n :host([theme=\"dark\"]) .message.assistant .message-content {\r\n background: #27272a;\r\n border-color: #3f3f46;\r\n color: #fafafa;\r\n }\r\n\r\n .message-text {\r\n white-space: pre-wrap;\r\n margin: 0;\r\n }\r\n\r\n .faq-section {\r\n margin-top: 1rem;\r\n padding-top: 1rem;\r\n border-top: 1px solid #e4e4e7;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-section {\r\n border-top-color: #3f3f46;\r\n }\r\n\r\n .faq-title {\r\n font-size: 0.875rem;\r\n font-weight: 500;\r\n color: #3f3f46;\r\n margin: 0 0 0.5rem 0;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-title {\r\n color: #d4d4d8;\r\n }\r\n\r\n .faq-list {\r\n list-style: none;\r\n padding: 0;\r\n margin: 0;\r\n display: flex;\r\n flex-direction: column;\r\n gap: 0.5rem;\r\n }\r\n\r\n .faq-item {\r\n font-size: 0.875rem;\r\n color: #52525b;\r\n padding: 0.5rem;\r\n border-radius: 0.375rem;\r\n cursor: pointer;\r\n transition: background-color 0.2s, color 0.2s;\r\n }\r\n\r\n .faq-item:hover {\r\n background-color: #f4f4f5;\r\n color: #18181b;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-item {\r\n color: #a1a1aa;\r\n }\r\n\r\n :host([theme=\"dark\"]) .faq-item:hover {\r\n background-color: #27272a;\r\n color: #fafafa;\r\n }\r\n\r\n .loading {\r\n display: flex;\r\n gap: 1rem;\r\n }\r\n\r\n .spinner {\r\n display: inline-block;\r\n width: 1.25rem;\r\n height: 1.25rem;\r\n border: 2px solid #e4e4e7;\r\n border-top-color: #71717a;\r\n border-radius: 50%;\r\n animation: spin 1s linear infinite;\r\n }\r\n\r\n @keyframes spin {\r\n to { transform: rotate(360deg); }\r\n }\r\n\r\n .input-area {\r\n border-top: 1px solid #e4e4e7;\r\n background: #fff;\r\n padding: 1rem;\r\n }\r\n\r\n :host([theme=\"dark\"]) .input-area {\r\n border-top-color: #27272a;\r\n background: #000;\r\n }\r\n\r\n .input-form {\r\n max-width: 56rem;\r\n margin: 0 auto;\r\n display: flex;\r\n gap: 0.75rem;\r\n }\r\n\r\n .input-field {\r\n flex: 1;\r\n height: 3rem;\r\n padding: 0 1rem;\r\n border: 1px solid #e4e4e7;\r\n border-radius: 0.5rem;\r\n font-size: 1rem;\r\n font-family: inherit;\r\n background: #fff;\r\n color: #09090b;\r\n }\r\n\r\n :host([theme=\"dark\"]) .input-field {\r\n border-color: #3f3f46;\r\n background: #18181b;\r\n color: #fafafa;\r\n }\r\n\r\n .input-field:focus {\r\n outline: 2px solid #2563eb;\r\n outline-offset: 2px;\r\n }\r\n\r\n .input-field:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .send-button {\r\n width: 3rem;\r\n height: 3rem;\r\n border-radius: 9999px;\r\n border: none;\r\n background: #2563eb;\r\n color: #fff;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: background 0.2s;\r\n }\r\n\r\n .send-button:hover:not(:disabled) {\r\n background: #1d4ed8;\r\n }\r\n\r\n .send-button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .send-icon {\r\n width: 1.25rem;\r\n height: 1.25rem;\r\n }\r\n\r\n .version-tag {\r\n text-align: center;\r\n padding: 0.5rem;\r\n font-size: 0.75rem;\r\n color: #71717a;\r\n border-top: 1px solid #e4e4e7;\r\n }\r\n\r\n :host([theme=\"dark\"]) .version-tag {\r\n color: #a1a1aa;\r\n border-top-color: #27272a;\r\n }\r\n `;\r\n\r\n declare apiUrl: string;\r\n declare sessionId: string;\r\n declare chatTitle: string;\r\n declare theme: 'light' | 'dark';\r\n declare mode: 'fullscreen' | 'widget';\r\n declare initialMessages: Message[];\r\n declare botAvatarUrl: string;\r\n declare backgroundImageUrl: string;\r\n\r\n @state()\r\n private declare messages: Message[];\r\n\r\n @state()\r\n private declare input: string;\r\n\r\n @state()\r\n private declare isLoading: boolean;\r\n\r\n @state()\r\n private declare isOpen: boolean;\r\n\r\n private messagesEndRef?: HTMLDivElement;\r\n\r\n static override properties = {\r\n apiUrl: { type: String, attribute: 'api-url' },\r\n sessionId: { type: String, attribute: 'session-id' },\r\n chatTitle: { type: String, attribute: 'title' },\r\n theme: { type: String },\r\n mode: { type: String, reflect: true },\r\n initialMessages: { type: Array },\r\n botAvatarUrl: { type: String, attribute: 'bot-avatar-url' },\r\n backgroundImageUrl: { type: String, attribute: 'background-image-url' },\r\n };\r\n\r\n constructor() {\r\n super();\r\n this.apiUrl = '';\r\n this.sessionId = 'default-session';\r\n this.chatTitle = 'My AI Agent';\r\n this.theme = 'light';\r\n this.mode = 'fullscreen';\r\n this.initialMessages = [];\r\n this.botAvatarUrl = '';\r\n this.backgroundImageUrl = '';\r\n this.messages = [];\r\n this.input = '';\r\n this.isLoading = false;\r\n this.isOpen = false;\r\n }\r\n\r\n private toggleWidget() {\r\n this.isOpen = !this.isOpen;\r\n }\r\n\r\n connectedCallback() {\r\n super.connectedCallback();\r\n if (this.initialMessages && this.initialMessages.length > 0) {\r\n this.messages = [...this.initialMessages];\r\n }\r\n }\r\n\r\n updated(changedProperties: PropertyValues) {\r\n super.updated(changedProperties);\r\n if (changedProperties.has('messages')) {\r\n this.scrollToBottom();\r\n }\r\n }\r\n\r\n private scrollToBottom() {\r\n requestAnimationFrame(() => {\r\n this.messagesEndRef?.scrollIntoView({ behavior: 'smooth' });\r\n });\r\n }\r\n\r\n private handleInput(e: Event) {\r\n this.input = (e.target as HTMLInputElement).value;\r\n }\r\n\r\n private handleFAQClick(question: string) {\r\n if (this.isLoading) return;\r\n\r\n // Set the input and trigger submit\r\n this.input = question;\r\n\r\n // Create a synthetic submit event\r\n const submitEvent = new Event('submit', { cancelable: true });\r\n this.handleSubmit(submitEvent);\r\n }\r\n\r\n private async handleSubmit(e: Event) {\r\n e.preventDefault();\r\n\r\n if (!this.input.trim() || this.isLoading || !this.apiUrl) return;\r\n\r\n const userMessage: Message = {\r\n id: Date.now().toString(),\r\n role: 'user',\r\n content: this.input.trim(),\r\n };\r\n\r\n this.messages = [...this.messages, userMessage];\r\n const questionText = this.input.trim();\r\n this.input = '';\r\n this.isLoading = true;\r\n\r\n // Dispatch message-sent event\r\n this.dispatchEvent(new CustomEvent('message-sent', {\r\n detail: userMessage,\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n\r\n try {\r\n const response = await fetch(`${this.apiUrl}/ask`, {\r\n method: 'POST',\r\n headers: { 'Content-Type': 'application/json' },\r\n body: JSON.stringify({\r\n session_id: this.sessionId,\r\n question: questionText,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorText = await response.text();\r\n throw new Error(`Backend error: ${response.status} ${errorText}`);\r\n }\r\n\r\n const data = await response.json();\r\n console.log('🔍 Raw API response:', data);\r\n\r\n // Extract the response text and FAQs properly\r\n let responseText = 'No response from agent';\r\n let faqs: FAQ[] | undefined = undefined;\r\n\r\n if (data && typeof data === 'object' && data.response && typeof data.response === 'string') {\r\n console.log('📝 data.response type:', typeof data.response);\r\n console.log('📝 data.response preview:', data.response.substring(0, 100));\r\n\r\n // Check if data.response contains stringified JSON\r\n const trimmedResponse = data.response.trim();\r\n if (trimmedResponse.startsWith('{') || trimmedResponse.startsWith('[')) {\r\n console.log('🔄 Detected stringified JSON, parsing...');\r\n\r\n try {\r\n // First attempt: standard JSON.parse\r\n let innerData = JSON.parse(data.response);\r\n console.log('✅ Parsed inner data with JSON.parse');\r\n\r\n if (innerData && innerData.response && typeof innerData.response === 'string') {\r\n responseText = innerData.response;\r\n faqs = innerData.faqs_used || undefined;\r\n console.log('✅ Extracted text length:', responseText.length);\r\n console.log('✅ Extracted FAQs count:', faqs?.length || 0);\r\n } else {\r\n responseText = data.response;\r\n faqs = data.faqs_used || undefined;\r\n }\r\n } catch (parseError) {\r\n console.warn('⚠️ JSON.parse failed, using regex extraction...', parseError);\r\n\r\n // Backend has malformed JSON - extract response text\r\n const responsePattern = /\"response\"\\s*:\\s*\"([^\"]*(?:\\\\.[^\"]*)*)\"/s;\r\n const responseMatch = data.response.match(responsePattern);\r\n\r\n if (responseMatch) {\r\n responseText = responseMatch[1]\r\n .replace(/\\\\n/g, '\\n')\r\n .replace(/\\\\t/g, '\\t')\r\n .replace(/\\\\r/g, '\\r')\r\n .replace(/\\\\\"/g, '\"')\r\n .replace(/\\\\\\\\/g, '\\\\');\r\n console.log('✅ Extracted response text, length:', responseText.length);\r\n } else {\r\n console.error('❌ Could not extract response');\r\n responseText = 'Error: Could not parse response';\r\n }\r\n\r\n // Extract FAQs array\r\n const faqsPattern = /\"faqs_used\"\\s*:\\s*(\\[[^\\]]*\\])/s;\r\n const faqsMatch = data.response.match(faqsPattern);\r\n\r\n if (faqsMatch) {\r\n try {\r\n faqs = JSON.parse(faqsMatch[1]);\r\n console.log('✅ Extracted FAQs, count:', faqs?.length || 0);\r\n } catch {\r\n console.log('⚠️ Could not parse FAQs, trying multiline...');\r\n // FAQs might span multiple lines\r\n const faqsMultiPattern = /\"faqs_used\"\\s*:\\s*(\\[[\\s\\S]*?\\n\\s*\\])/;\r\n const faqsMultiMatch = data.response.match(faqsMultiPattern);\r\n if (faqsMultiMatch) {\r\n try {\r\n faqs = JSON.parse(faqsMultiMatch[1]);\r\n console.log('✅ Extracted multi-line FAQs, count:', faqs?.length || 0);\r\n } catch {\r\n faqs = undefined;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n // Not JSON, direct text response\r\n console.log('📄 Direct text response (not JSON)');\r\n responseText = data.response;\r\n faqs = data.faqs_used || undefined;\r\n }\r\n } else if (typeof data === 'string') {\r\n console.log('📄 Response is a plain string');\r\n responseText = data;\r\n } else if (data && typeof data === 'object') {\r\n // Fallback for other formats\r\n console.warn('⚠️ Unexpected format, using fallback');\r\n responseText = data.message || data.answer || 'Error: Unexpected response format';\r\n }\r\n\r\n console.log('🎯 Final responseText length:', responseText.length);\r\n console.log('🎯 Final responseText preview:', responseText.substring(0, 100));\r\n console.log('🎯 Final FAQs:', faqs);\r\n\r\n const assistantMessage: Message = {\r\n id: (Date.now() + 1).toString(),\r\n role: 'assistant',\r\n content: responseText,\r\n faqs: faqs,\r\n };\r\n\r\n this.messages = [...this.messages, assistantMessage];\r\n\r\n // Dispatch response-received event\r\n this.dispatchEvent(new CustomEvent('response-received', {\r\n detail: assistantMessage,\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n } catch (err) {\r\n console.error('Backend connection failed:', err);\r\n\r\n const errorMessage: Message = {\r\n id: (Date.now() + 1).toString(),\r\n role: 'assistant',\r\n content: `Error: ${err instanceof Error ? err.message : 'Unknown error'}\\n\\nPlease check your API endpoint configuration.`,\r\n };\r\n\r\n this.messages = [...this.messages, errorMessage];\r\n\r\n // Dispatch error event\r\n this.dispatchEvent(new CustomEvent('error', {\r\n detail: err,\r\n bubbles: true,\r\n composed: true,\r\n }));\r\n } finally {\r\n this.isLoading = false;\r\n }\r\n }\r\n\r\n private renderChatUI() {\r\n return html`\r\n <!-- Header -->\r\n <div class=\"header\">\r\n <div class=\"header-content\">\r\n <h1 class=\"title\">${this.chatTitle}</h1>\r\n </div>\r\n </div>\r\n\r\n <!-- Messages Area -->\r\n <div class=\"messages-area\" style=\"${this.backgroundImageUrl ? `--background-image-url: url('${this.backgroundImageUrl}')` : ''}\">\r\n <div class=\"messages-container\">\r\n ${this.messages.length === 0 ? html`\r\n <div class=\"empty-state\">\r\n <p>How can I help you today?</p>\r\n </div>\r\n ` : ''}\r\n\r\n ${repeat(this.messages, (msg) => msg.id, (msg) => html`\r\n <div class=${classMap({\r\n message: true,\r\n user: msg.role === 'user',\r\n assistant: msg.role === 'assistant'\r\n })}>\r\n <div class=\"avatar\">\r\n ${msg.role === 'user'\r\n ? 'U'\r\n : this.botAvatarUrl\r\n ? html`<img src=\"${this.botAvatarUrl}\" alt=\"AI\" class=\"avatar-image\" />`\r\n : 'AI'}\r\n </div>\r\n <div class=\"message-content\">\r\n <p class=\"message-text\">${msg.content}</p>\r\n ${msg.role === 'assistant' && msg.faqs && msg.faqs.length > 0 ? html`\r\n <div class=\"faq-section\">\r\n <p class=\"faq-title\">Related FAQs:</p>\r\n <ul class=\"faq-list\">\r\n ${msg.faqs.map(faq => html`\r\n <li class=\"faq-item\" @click=${() => this.handleFAQClick(faq.question)}>\r\n ${faq.question}\r\n </li>\r\n `)}\r\n </ul>\r\n </div>\r\n ` : ''}\r\n </div>\r\n </div>\r\n `)}\r\n\r\n ${this.isLoading ? html`\r\n <div class=\"loading\">\r\n <div class=\"avatar\">\r\n ${this.botAvatarUrl\r\n ? html`<img src=\"${this.botAvatarUrl}\" alt=\"AI\" class=\"avatar-image\" />`\r\n : 'AI'}\r\n </div>\r\n <div class=\"message-content\">\r\n <div class=\"spinner\"></div>\r\n </div>\r\n </div>\r\n ` : ''}\r\n\r\n <div ${(el: Element) => this.messagesEndRef = el as HTMLDivElement}></div>\r\n </div>\r\n </div>\r\n\r\n <!-- Input Area -->\r\n <div class=\"input-area\">\r\n <form class=\"input-form\" @submit=${this.handleSubmit}>\r\n <input\r\n type=\"text\"\r\n class=\"input-field\"\r\n placeholder=\"Type your message...\"\r\n .value=${this.input}\r\n @input=${this.handleInput}\r\n ?disabled=${this.isLoading}\r\n />\r\n <button\r\n type=\"submit\"\r\n class=\"send-button\"\r\n ?disabled=${this.isLoading || !this.input.trim()}\r\n aria-label=\"Send message\"\r\n >\r\n ${this.isLoading ? html`\r\n <div class=\"spinner\" style=\"border-color: #fff; border-top-color: transparent;\"></div>\r\n ` : html`\r\n <svg class=\"send-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\"></line>\r\n <polygon points=\"22 2 15 22 11 13 2 9 22 2\"></polygon>\r\n </svg>\r\n `}\r\n </button>\r\n </form>\r\n </div>\r\n\r\n <!-- Version -->\r\n <div class=\"version-tag\">v${VERSION}</div>\r\n `;\r\n }\r\n\r\n render() {\r\n if (this.mode === 'widget') {\r\n return html`\r\n <div class=\"widget-container\">\r\n <!-- Chat Window -->\r\n <div class=${classMap({ 'widget-window': true, 'open': this.isOpen })}>\r\n ${this.renderChatUI()}\r\n </div>\r\n\r\n <!-- Toggle Button -->\r\n <button\r\n class=\"widget-button\"\r\n @click=${this.toggleWidget}\r\n aria-label=${this.isOpen ? 'Close chat' : 'Open chat'}\r\n >\r\n ${this.isOpen ? html`\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\r\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\r\n </svg>\r\n ` : html`\r\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\r\n <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>\r\n </svg>\r\n `}\r\n </button>\r\n </div>\r\n `;\r\n }\r\n\r\n // Fullscreen mode\r\n return this.renderChatUI();\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'ai-chat': AIChat;\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a.izzuddin/ai-chat",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "A framework-agnostic AI chat web component. Works with React, Vue, Svelte, Angular, and vanilla JavaScript.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",