@a.izzuddin/ai-chat 0.2.10 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +87 -6
- package/dist/index.d.mts +30 -4
- package/dist/index.d.ts +30 -4
- package/dist/index.js +196 -32
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +196 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -2
package/dist/index.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
14
14
|
if (kind && result) __defProp(target, key, result);
|
|
15
15
|
return result;
|
|
16
16
|
};
|
|
17
|
-
var VERSION = "0.2.
|
|
17
|
+
var VERSION = "0.2.13";
|
|
18
18
|
var AIChat = class extends LitElement {
|
|
19
19
|
constructor() {
|
|
20
20
|
super();
|
|
@@ -35,6 +35,9 @@ var AIChat = class extends LitElement {
|
|
|
35
35
|
this.botMessageBg = "#F5F5F5";
|
|
36
36
|
this.welcomeMessage = "How can I help you today?";
|
|
37
37
|
this.welcomeSubtitle = "";
|
|
38
|
+
this.initialQuestionsUrl = "";
|
|
39
|
+
this.language = "en";
|
|
40
|
+
this.showRelatedFaqs = true;
|
|
38
41
|
this.messages = [];
|
|
39
42
|
this.input = "";
|
|
40
43
|
this.isLoading = false;
|
|
@@ -78,29 +81,38 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
78
81
|
saveMessagesToStorage() {
|
|
79
82
|
try {
|
|
80
83
|
const storageKey = this.getStorageKey();
|
|
81
|
-
|
|
84
|
+
sessionStorage.setItem(storageKey, JSON.stringify(this.messages));
|
|
85
|
+
sessionStorage.setItem("ai-chat-last-session-id", this.sessionId);
|
|
82
86
|
} catch (error) {
|
|
83
|
-
console.warn("Failed to save messages to
|
|
87
|
+
console.warn("Failed to save messages to sessionStorage:", error);
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
loadMessagesFromStorage() {
|
|
87
91
|
try {
|
|
92
|
+
const lastSessionId = sessionStorage.getItem("ai-chat-last-session-id");
|
|
93
|
+
if (lastSessionId && lastSessionId !== this.sessionId) {
|
|
94
|
+
console.log(`\u{1F504} Session changed from "${lastSessionId}" to "${this.sessionId}", clearing old messages`);
|
|
95
|
+
const oldStorageKey = `ai-chat-messages-${lastSessionId}`;
|
|
96
|
+
sessionStorage.removeItem(oldStorageKey);
|
|
97
|
+
sessionStorage.setItem("ai-chat-last-session-id", this.sessionId);
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
88
100
|
const storageKey = this.getStorageKey();
|
|
89
|
-
const saved =
|
|
101
|
+
const saved = sessionStorage.getItem(storageKey);
|
|
90
102
|
if (saved) {
|
|
91
103
|
return JSON.parse(saved);
|
|
92
104
|
}
|
|
93
105
|
} catch (error) {
|
|
94
|
-
console.warn("Failed to load messages from
|
|
106
|
+
console.warn("Failed to load messages from sessionStorage:", error);
|
|
95
107
|
}
|
|
96
108
|
return null;
|
|
97
109
|
}
|
|
98
110
|
clearMessagesFromStorage() {
|
|
99
111
|
try {
|
|
100
112
|
const storageKey = this.getStorageKey();
|
|
101
|
-
|
|
113
|
+
sessionStorage.removeItem(storageKey);
|
|
102
114
|
} catch (error) {
|
|
103
|
-
console.warn("Failed to clear messages from
|
|
115
|
+
console.warn("Failed to clear messages from sessionStorage:", error);
|
|
104
116
|
}
|
|
105
117
|
}
|
|
106
118
|
formatMessageContent(content) {
|
|
@@ -184,22 +196,59 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
184
196
|
}
|
|
185
197
|
return formattedContent;
|
|
186
198
|
}
|
|
187
|
-
connectedCallback() {
|
|
199
|
+
async connectedCallback() {
|
|
188
200
|
super.connectedCallback();
|
|
189
201
|
const savedMessages = this.loadMessagesFromStorage();
|
|
190
202
|
if (this.initialMessages && this.initialMessages.length > 0) {
|
|
191
203
|
this.messages = [...this.initialMessages];
|
|
192
204
|
} else if (savedMessages && savedMessages.length > 0) {
|
|
193
205
|
this.messages = savedMessages;
|
|
194
|
-
} else
|
|
195
|
-
|
|
206
|
+
} else {
|
|
207
|
+
let suggestedQuestions = void 0;
|
|
208
|
+
if (this.initialQuestionsUrl) {
|
|
209
|
+
try {
|
|
210
|
+
let fetchUrl = this.initialQuestionsUrl;
|
|
211
|
+
if (this.language) {
|
|
212
|
+
const separator = fetchUrl.includes("?") ? "&" : "?";
|
|
213
|
+
fetchUrl = `${fetchUrl}${separator}language=${this.language}`;
|
|
214
|
+
}
|
|
215
|
+
console.log("\u{1F4E4} Fetching initial questions from:", fetchUrl);
|
|
216
|
+
const response = await fetch(fetchUrl);
|
|
217
|
+
if (response.ok) {
|
|
218
|
+
const data = await response.json();
|
|
219
|
+
console.log("\u{1F4E5} Fetched initial questions:", data);
|
|
220
|
+
let questionsArray = data.questions || data.suggested_questions || data;
|
|
221
|
+
if (Array.isArray(questionsArray) && questionsArray.length > 0) {
|
|
222
|
+
if (typeof questionsArray[0] === "object" && questionsArray[0].question_text) {
|
|
223
|
+
suggestedQuestions = questionsArray.map((q) => ({
|
|
224
|
+
id: q.id,
|
|
225
|
+
question_type: q.question_type,
|
|
226
|
+
question_text: q.question_text,
|
|
227
|
+
category: q.category
|
|
228
|
+
}));
|
|
229
|
+
} else if (typeof questionsArray[0] === "string") {
|
|
230
|
+
suggestedQuestions = questionsArray.map((q) => ({
|
|
231
|
+
question_text: q
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
console.log("\u2705 Processed suggested questions:", suggestedQuestions);
|
|
236
|
+
}
|
|
237
|
+
} catch (error) {
|
|
238
|
+
console.warn("Failed to fetch initial questions:", error);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (this.welcomeMessage) {
|
|
242
|
+
const welcomeText = this.welcomeSubtitle ? `${this.welcomeMessage}
|
|
196
243
|
|
|
197
244
|
${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
245
|
+
this.messages = [{
|
|
246
|
+
id: "welcome-" + Date.now(),
|
|
247
|
+
role: "assistant",
|
|
248
|
+
content: welcomeText,
|
|
249
|
+
suggestedQuestions
|
|
250
|
+
}];
|
|
251
|
+
}
|
|
203
252
|
}
|
|
204
253
|
}
|
|
205
254
|
updated(changedProperties) {
|
|
@@ -218,14 +267,121 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
218
267
|
}
|
|
219
268
|
}, 100);
|
|
220
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Normalize suggested questions - converts string arrays to SuggestedQuestion objects
|
|
272
|
+
*/
|
|
273
|
+
normalizeSuggestedQuestions(questions) {
|
|
274
|
+
if (!questions || !Array.isArray(questions) || questions.length === 0) {
|
|
275
|
+
return void 0;
|
|
276
|
+
}
|
|
277
|
+
if (typeof questions[0] === "object" && questions[0].question_text) {
|
|
278
|
+
return questions;
|
|
279
|
+
}
|
|
280
|
+
if (typeof questions[0] === "string") {
|
|
281
|
+
return questions.map((q) => ({
|
|
282
|
+
question_text: q
|
|
283
|
+
}));
|
|
284
|
+
}
|
|
285
|
+
return void 0;
|
|
286
|
+
}
|
|
221
287
|
handleInput(e) {
|
|
222
288
|
this.input = e.target.value;
|
|
223
289
|
}
|
|
224
|
-
handleFAQClick(question) {
|
|
290
|
+
async handleFAQClick(question) {
|
|
225
291
|
if (this.isLoading) return;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
292
|
+
if (question.id && question.question_type) {
|
|
293
|
+
await this.handleSuggestedQuestionClick(question);
|
|
294
|
+
} else {
|
|
295
|
+
this.input = question.question_text;
|
|
296
|
+
const submitEvent = new Event("submit", { cancelable: true });
|
|
297
|
+
this.handleSubmit(submitEvent);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async handleSuggestedQuestionClick(question) {
|
|
301
|
+
if (!question.id || !question.question_type) return;
|
|
302
|
+
const userMessage = {
|
|
303
|
+
id: Date.now().toString(),
|
|
304
|
+
role: "user",
|
|
305
|
+
content: question.question_text
|
|
306
|
+
};
|
|
307
|
+
this.messages = [...this.messages, userMessage];
|
|
308
|
+
this.isLoading = true;
|
|
309
|
+
this.dispatchEvent(new CustomEvent("message-sent", {
|
|
310
|
+
detail: userMessage,
|
|
311
|
+
bubbles: true,
|
|
312
|
+
composed: true
|
|
313
|
+
}));
|
|
314
|
+
try {
|
|
315
|
+
let baseUrl = "";
|
|
316
|
+
if (this.initialQuestionsUrl) {
|
|
317
|
+
try {
|
|
318
|
+
const urlObj = new URL(this.initialQuestionsUrl);
|
|
319
|
+
baseUrl = `${urlObj.protocol}//${urlObj.host}`;
|
|
320
|
+
} catch {
|
|
321
|
+
baseUrl = "http://43.217.183.120:8080";
|
|
322
|
+
}
|
|
323
|
+
} else {
|
|
324
|
+
baseUrl = "http://43.217.183.120:8080";
|
|
325
|
+
}
|
|
326
|
+
const url = `${baseUrl}/api/questions/${question.id}?question_type=${question.question_type}`;
|
|
327
|
+
console.log("\u{1F4E4} Calling suggested question API:", url);
|
|
328
|
+
const response = await fetch(url, {
|
|
329
|
+
method: "GET",
|
|
330
|
+
headers: { "Content-Type": "application/json" }
|
|
331
|
+
});
|
|
332
|
+
if (!response.ok) {
|
|
333
|
+
const errorText = await response.text();
|
|
334
|
+
throw new Error(`Backend error: ${response.status} ${errorText}`);
|
|
335
|
+
}
|
|
336
|
+
const data = await response.json();
|
|
337
|
+
console.log("\u{1F50D} Suggested question API response:", data);
|
|
338
|
+
let responseText = "No response from agent";
|
|
339
|
+
let suggestedQuestions = void 0;
|
|
340
|
+
if (data && typeof data === "object") {
|
|
341
|
+
if (data.question && data.question.answer_text) {
|
|
342
|
+
responseText = data.question.answer_text;
|
|
343
|
+
}
|
|
344
|
+
if (data.related_questions && Array.isArray(data.related_questions) && data.related_questions.length > 0) {
|
|
345
|
+
if (typeof data.related_questions[0] === "object" && data.related_questions[0].question_text) {
|
|
346
|
+
suggestedQuestions = data.related_questions.map((q) => ({
|
|
347
|
+
id: q.id,
|
|
348
|
+
question_type: q.question_type,
|
|
349
|
+
question_text: q.question_text,
|
|
350
|
+
category: q.category
|
|
351
|
+
}));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
const assistantMessage = {
|
|
356
|
+
id: (Date.now() + 1).toString(),
|
|
357
|
+
role: "assistant",
|
|
358
|
+
content: responseText,
|
|
359
|
+
suggestedQuestions
|
|
360
|
+
};
|
|
361
|
+
this.messages = [...this.messages, assistantMessage];
|
|
362
|
+
this.dispatchEvent(new CustomEvent("response-received", {
|
|
363
|
+
detail: assistantMessage,
|
|
364
|
+
bubbles: true,
|
|
365
|
+
composed: true
|
|
366
|
+
}));
|
|
367
|
+
} catch (err) {
|
|
368
|
+
console.error("Suggested question API failed:", err);
|
|
369
|
+
const errorMessage = {
|
|
370
|
+
id: (Date.now() + 1).toString(),
|
|
371
|
+
role: "assistant",
|
|
372
|
+
content: `Error: ${err instanceof Error ? err.message : "Unknown error"}
|
|
373
|
+
|
|
374
|
+
Please check your API endpoint configuration.`
|
|
375
|
+
};
|
|
376
|
+
this.messages = [...this.messages, errorMessage];
|
|
377
|
+
this.dispatchEvent(new CustomEvent("error", {
|
|
378
|
+
detail: err,
|
|
379
|
+
bubbles: true,
|
|
380
|
+
composed: true
|
|
381
|
+
}));
|
|
382
|
+
} finally {
|
|
383
|
+
this.isLoading = false;
|
|
384
|
+
}
|
|
229
385
|
}
|
|
230
386
|
async handleSubmit(e) {
|
|
231
387
|
e.preventDefault();
|
|
@@ -274,14 +430,14 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
274
430
|
if (innerData && innerData.response && typeof innerData.response === "string") {
|
|
275
431
|
responseText = innerData.response;
|
|
276
432
|
faqs = innerData.faq_used || innerData.faqs_used || void 0;
|
|
277
|
-
suggestedQuestions = innerData.suggested_follow_ups || innerData.suggested_questions
|
|
433
|
+
suggestedQuestions = this.normalizeSuggestedQuestions(innerData.suggested_follow_ups || innerData.suggested_questions);
|
|
278
434
|
console.log("\u2705 Extracted text length:", responseText.length);
|
|
279
435
|
console.log("\u2705 Extracted FAQs count:", faqs?.length || 0);
|
|
280
436
|
console.log("\u2705 Extracted suggested questions count:", suggestedQuestions?.length || 0);
|
|
281
437
|
} else {
|
|
282
438
|
responseText = data.response;
|
|
283
439
|
faqs = data.faq_used || data.faqs_used || void 0;
|
|
284
|
-
suggestedQuestions = data.suggested_follow_ups || data.suggested_questions
|
|
440
|
+
suggestedQuestions = this.normalizeSuggestedQuestions(data.suggested_follow_ups || data.suggested_questions);
|
|
285
441
|
}
|
|
286
442
|
} catch (parseError) {
|
|
287
443
|
console.warn("\u26A0\uFE0F JSON.parse failed, using regex extraction...", parseError);
|
|
@@ -318,7 +474,8 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
318
474
|
const suggestedMatch = data.response.match(suggestedPattern);
|
|
319
475
|
if (suggestedMatch) {
|
|
320
476
|
try {
|
|
321
|
-
|
|
477
|
+
const parsedQuestions = JSON.parse(suggestedMatch[1]);
|
|
478
|
+
suggestedQuestions = this.normalizeSuggestedQuestions(parsedQuestions);
|
|
322
479
|
console.log("\u2705 Extracted suggested questions, count:", suggestedQuestions?.length || 0);
|
|
323
480
|
} catch {
|
|
324
481
|
console.log("\u26A0\uFE0F Could not parse suggested questions, trying multiline...");
|
|
@@ -326,7 +483,8 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
326
483
|
const suggestedMultiMatch = data.response.match(suggestedMultiPattern);
|
|
327
484
|
if (suggestedMultiMatch) {
|
|
328
485
|
try {
|
|
329
|
-
|
|
486
|
+
const parsedQuestions = JSON.parse(suggestedMultiMatch[1]);
|
|
487
|
+
suggestedQuestions = this.normalizeSuggestedQuestions(parsedQuestions);
|
|
330
488
|
console.log("\u2705 Extracted multi-line suggested questions, count:", suggestedQuestions?.length || 0);
|
|
331
489
|
} catch {
|
|
332
490
|
suggestedQuestions = void 0;
|
|
@@ -339,7 +497,7 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
339
497
|
console.log("\u{1F4C4} Direct text response (not JSON)");
|
|
340
498
|
responseText = data.response;
|
|
341
499
|
faqs = data.faq_used || data.faqs_used || void 0;
|
|
342
|
-
suggestedQuestions = data.suggested_follow_ups || data.suggested_questions
|
|
500
|
+
suggestedQuestions = this.normalizeSuggestedQuestions(data.suggested_follow_ups || data.suggested_questions);
|
|
343
501
|
}
|
|
344
502
|
} else if (typeof data === "string") {
|
|
345
503
|
console.log("\u{1F4C4} Response is a plain string");
|
|
@@ -348,7 +506,7 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
348
506
|
console.warn("\u26A0\uFE0F Unexpected format, using fallback");
|
|
349
507
|
responseText = data.message || data.answer || "Error: Unexpected response format";
|
|
350
508
|
faqs = data.faq_used || data.faqs_used || void 0;
|
|
351
|
-
suggestedQuestions = data.suggested_follow_ups || data.suggested_questions
|
|
509
|
+
suggestedQuestions = this.normalizeSuggestedQuestions(data.suggested_follow_ups || data.suggested_questions);
|
|
352
510
|
}
|
|
353
511
|
console.log("\u{1F3AF} Final responseText length:", responseText.length);
|
|
354
512
|
console.log("\u{1F3AF} Final responseText preview:", responseText.substring(0, 100));
|
|
@@ -417,13 +575,13 @@ Please check your API endpoint configuration.`
|
|
|
417
575
|
</div>
|
|
418
576
|
<div class="message-content">
|
|
419
577
|
<div class="message-text">${unsafeHTML(this.formatMessageContent(msg.content))}</div>
|
|
420
|
-
${msg.role === "assistant" && msg.faqs && msg.faqs.length > 0 ? html`
|
|
578
|
+
${msg.role === "assistant" && this.showRelatedFaqs && msg.faqs && msg.faqs.length > 0 ? html`
|
|
421
579
|
<div class="faq-section">
|
|
422
580
|
<p class="faq-title">Related FAQs:</p>
|
|
423
581
|
<ul class="faq-list">
|
|
424
582
|
${msg.faqs.map((faq) => html`
|
|
425
583
|
<li class="faq-item-static">
|
|
426
|
-
${faq.
|
|
584
|
+
${faq.Question}
|
|
427
585
|
</li>
|
|
428
586
|
`)}
|
|
429
587
|
</ul>
|
|
@@ -435,7 +593,7 @@ Please check your API endpoint configuration.`
|
|
|
435
593
|
<ul class="faq-list">
|
|
436
594
|
${msg.suggestedQuestions.map((question) => html`
|
|
437
595
|
<li class="faq-item" @click=${() => this.handleFAQClick(question)}>
|
|
438
|
-
${question}
|
|
596
|
+
${question.question_text}
|
|
439
597
|
</li>
|
|
440
598
|
`)}
|
|
441
599
|
</ul>
|
|
@@ -601,9 +759,12 @@ AIChat.styles = css`
|
|
|
601
759
|
}
|
|
602
760
|
|
|
603
761
|
.widget-button-icon {
|
|
604
|
-
width:
|
|
605
|
-
height:
|
|
606
|
-
|
|
762
|
+
width: 100%;
|
|
763
|
+
height: 100%;
|
|
764
|
+
max-width: 60px;
|
|
765
|
+
max-height: 60px;
|
|
766
|
+
object-fit: contain;
|
|
767
|
+
border-radius: 50%;
|
|
607
768
|
}
|
|
608
769
|
|
|
609
770
|
.widget-window {
|
|
@@ -1296,7 +1457,10 @@ AIChat.properties = {
|
|
|
1296
1457
|
userMessageBg: { type: String, attribute: "user-message-bg" },
|
|
1297
1458
|
botMessageBg: { type: String, attribute: "bot-message-bg" },
|
|
1298
1459
|
welcomeMessage: { type: String, attribute: "welcome-message" },
|
|
1299
|
-
welcomeSubtitle: { type: String, attribute: "welcome-subtitle" }
|
|
1460
|
+
welcomeSubtitle: { type: String, attribute: "welcome-subtitle" },
|
|
1461
|
+
initialQuestionsUrl: { type: String, attribute: "initial-questions-url" },
|
|
1462
|
+
language: { type: String, attribute: "language" },
|
|
1463
|
+
showRelatedFaqs: { type: Boolean, attribute: "show-related-faqs" }
|
|
1300
1464
|
};
|
|
1301
1465
|
__decorateClass([
|
|
1302
1466
|
state()
|