@a.izzuddin/ai-chat 0.2.16 → 0.2.18
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 +18 -0
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +14 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -33
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/custom-elements.json
CHANGED
|
@@ -601,6 +601,16 @@
|
|
|
601
601
|
"default": "''",
|
|
602
602
|
"attribute": "bot-avatar-url"
|
|
603
603
|
},
|
|
604
|
+
{
|
|
605
|
+
"kind": "field",
|
|
606
|
+
"name": "userAvatarUrl",
|
|
607
|
+
"privacy": "public",
|
|
608
|
+
"type": {
|
|
609
|
+
"text": "string"
|
|
610
|
+
},
|
|
611
|
+
"default": "''",
|
|
612
|
+
"attribute": "user-avatar-url"
|
|
613
|
+
},
|
|
604
614
|
{
|
|
605
615
|
"kind": "field",
|
|
606
616
|
"name": "widgetIconUrl",
|
|
@@ -1038,6 +1048,14 @@
|
|
|
1038
1048
|
"default": "''",
|
|
1039
1049
|
"fieldName": "botAvatarUrl"
|
|
1040
1050
|
},
|
|
1051
|
+
{
|
|
1052
|
+
"name": "user-avatar-url",
|
|
1053
|
+
"type": {
|
|
1054
|
+
"text": "string"
|
|
1055
|
+
},
|
|
1056
|
+
"default": "''",
|
|
1057
|
+
"fieldName": "userAvatarUrl"
|
|
1058
|
+
},
|
|
1041
1059
|
{
|
|
1042
1060
|
"name": "widget-icon-url",
|
|
1043
1061
|
"type": {
|
package/dist/index.d.mts
CHANGED
|
@@ -66,6 +66,7 @@ declare class AIChat extends LitElement {
|
|
|
66
66
|
mode: 'fullscreen' | 'widget';
|
|
67
67
|
initialMessages: Message[];
|
|
68
68
|
botAvatarUrl: string;
|
|
69
|
+
userAvatarUrl: string;
|
|
69
70
|
widgetIconUrl: string;
|
|
70
71
|
backgroundImageUrl: string;
|
|
71
72
|
widgetWidth: string;
|
|
@@ -111,6 +112,10 @@ declare class AIChat extends LitElement {
|
|
|
111
112
|
type: StringConstructor;
|
|
112
113
|
attribute: string;
|
|
113
114
|
};
|
|
115
|
+
userAvatarUrl: {
|
|
116
|
+
type: StringConstructor;
|
|
117
|
+
attribute: string;
|
|
118
|
+
};
|
|
114
119
|
widgetIconUrl: {
|
|
115
120
|
type: StringConstructor;
|
|
116
121
|
attribute: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -66,6 +66,7 @@ declare class AIChat extends LitElement {
|
|
|
66
66
|
mode: 'fullscreen' | 'widget';
|
|
67
67
|
initialMessages: Message[];
|
|
68
68
|
botAvatarUrl: string;
|
|
69
|
+
userAvatarUrl: string;
|
|
69
70
|
widgetIconUrl: string;
|
|
70
71
|
backgroundImageUrl: string;
|
|
71
72
|
widgetWidth: string;
|
|
@@ -111,6 +112,10 @@ declare class AIChat extends LitElement {
|
|
|
111
112
|
type: StringConstructor;
|
|
112
113
|
attribute: string;
|
|
113
114
|
};
|
|
115
|
+
userAvatarUrl: {
|
|
116
|
+
type: StringConstructor;
|
|
117
|
+
attribute: string;
|
|
118
|
+
};
|
|
114
119
|
widgetIconUrl: {
|
|
115
120
|
type: StringConstructor;
|
|
116
121
|
attribute: string;
|
package/dist/index.js
CHANGED
|
@@ -16,7 +16,7 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
16
16
|
if (kind && result) __defProp(target, key, result);
|
|
17
17
|
return result;
|
|
18
18
|
};
|
|
19
|
-
var VERSION = "0.2.
|
|
19
|
+
var VERSION = "0.2.18";
|
|
20
20
|
exports.AIChat = class AIChat extends lit.LitElement {
|
|
21
21
|
constructor() {
|
|
22
22
|
super();
|
|
@@ -27,6 +27,7 @@ exports.AIChat = class AIChat extends lit.LitElement {
|
|
|
27
27
|
this.mode = "fullscreen";
|
|
28
28
|
this.initialMessages = [];
|
|
29
29
|
this.botAvatarUrl = "";
|
|
30
|
+
this.userAvatarUrl = "";
|
|
30
31
|
this.widgetIconUrl = "";
|
|
31
32
|
this.backgroundImageUrl = "";
|
|
32
33
|
this.widgetWidth = "380px";
|
|
@@ -94,7 +95,6 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
94
95
|
try {
|
|
95
96
|
const lastSessionId = sessionStorage.getItem("ai-chat-last-session-id");
|
|
96
97
|
if (lastSessionId && lastSessionId !== this.sessionId) {
|
|
97
|
-
console.log(`\u{1F504} Session changed from "${lastSessionId}" to "${this.sessionId}", clearing old messages`);
|
|
98
98
|
const oldStorageKey = `ai-chat-messages-${lastSessionId}`;
|
|
99
99
|
sessionStorage.removeItem(oldStorageKey);
|
|
100
100
|
sessionStorage.setItem("ai-chat-last-session-id", this.sessionId);
|
|
@@ -208,6 +208,7 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
208
208
|
this.messages = savedMessages;
|
|
209
209
|
} else {
|
|
210
210
|
let suggestedQuestions = void 0;
|
|
211
|
+
let fetchFailed = false;
|
|
211
212
|
if (this.initialQuestionsUrl) {
|
|
212
213
|
try {
|
|
213
214
|
let fetchUrl = this.initialQuestionsUrl;
|
|
@@ -215,11 +216,9 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
215
216
|
const separator = fetchUrl.includes("?") ? "&" : "?";
|
|
216
217
|
fetchUrl = `${fetchUrl}${separator}language=${this.language}`;
|
|
217
218
|
}
|
|
218
|
-
console.log("\u{1F4E4} Fetching initial questions from:", fetchUrl);
|
|
219
219
|
const response = await fetch(fetchUrl);
|
|
220
220
|
if (response.ok) {
|
|
221
221
|
const data = await response.json();
|
|
222
|
-
console.log("\u{1F4E5} Fetched initial questions:", data);
|
|
223
222
|
let questionsArray = data.questions || data.suggested_questions || data;
|
|
224
223
|
if (Array.isArray(questionsArray) && questionsArray.length > 0) {
|
|
225
224
|
if (typeof questionsArray[0] === "object" && questionsArray[0].question_text) {
|
|
@@ -235,12 +234,17 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
235
234
|
}));
|
|
236
235
|
}
|
|
237
236
|
}
|
|
238
|
-
|
|
237
|
+
} else {
|
|
238
|
+
fetchFailed = true;
|
|
239
239
|
}
|
|
240
240
|
} catch (error) {
|
|
241
241
|
console.warn("Failed to fetch initial questions:", error);
|
|
242
|
+
fetchFailed = true;
|
|
242
243
|
}
|
|
243
244
|
}
|
|
245
|
+
if (fetchFailed) {
|
|
246
|
+
this.clearMessagesFromStorage();
|
|
247
|
+
}
|
|
244
248
|
if (this.welcomeMessage) {
|
|
245
249
|
const welcomeText = this.welcomeSubtitle ? `${this.welcomeMessage}
|
|
246
250
|
|
|
@@ -327,7 +331,6 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
327
331
|
baseUrl = "http://43.217.183.120:8080";
|
|
328
332
|
}
|
|
329
333
|
const url = `${baseUrl}/api/questions/${question.id}?question_type=${question.question_type}`;
|
|
330
|
-
console.log("\u{1F4E4} Calling suggested question API:", url);
|
|
331
334
|
const response = await fetch(url, {
|
|
332
335
|
method: "GET",
|
|
333
336
|
headers: { "Content-Type": "application/json" }
|
|
@@ -337,7 +340,6 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
337
340
|
throw new Error(`Backend error: ${response.status} ${errorText}`);
|
|
338
341
|
}
|
|
339
342
|
const data = await response.json();
|
|
340
|
-
console.log("\u{1F50D} Suggested question API response:", data);
|
|
341
343
|
let responseText = "No response from agent";
|
|
342
344
|
let suggestedQuestions = void 0;
|
|
343
345
|
if (data && typeof data === "object") {
|
|
@@ -415,40 +417,29 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
415
417
|
throw new Error(`Backend error: ${response.status} ${errorText}`);
|
|
416
418
|
}
|
|
417
419
|
const data = await response.json();
|
|
418
|
-
console.log("\u{1F50D} Raw API response:", data);
|
|
419
420
|
let responseText = "No response from agent";
|
|
420
421
|
let faqs = void 0;
|
|
421
422
|
let suggestedQuestions = void 0;
|
|
422
423
|
if (data && typeof data === "object" && data.response && typeof data.response === "string") {
|
|
423
|
-
console.log("\u{1F4DD} data.response type:", typeof data.response);
|
|
424
|
-
console.log("\u{1F4DD} data.response preview:", data.response.substring(0, 100));
|
|
425
424
|
const trimmedResponse = data.response.trim();
|
|
426
425
|
if (trimmedResponse.startsWith("{") || trimmedResponse.startsWith("[")) {
|
|
427
|
-
console.log("\u{1F504} Detected stringified JSON, parsing...");
|
|
428
426
|
try {
|
|
429
427
|
const innerData = JSON.parse(data.response);
|
|
430
|
-
console.log("\u2705 Parsed inner data with JSON.parse");
|
|
431
428
|
if (innerData && innerData.response && typeof innerData.response === "string") {
|
|
432
429
|
responseText = innerData.response;
|
|
433
430
|
faqs = innerData.faq_used || innerData.faqs_used || void 0;
|
|
434
431
|
suggestedQuestions = this.normalizeSuggestedQuestions(innerData.suggested_follow_ups || innerData.suggested_questions);
|
|
435
|
-
console.log("\u2705 Extracted text length:", responseText.length);
|
|
436
|
-
console.log("\u2705 Extracted FAQs count:", faqs?.length || 0);
|
|
437
|
-
console.log("\u2705 Extracted suggested questions count:", suggestedQuestions?.length || 0);
|
|
438
432
|
} else {
|
|
439
433
|
responseText = data.response;
|
|
440
434
|
faqs = data.faq_used || data.faqs_used || void 0;
|
|
441
435
|
suggestedQuestions = this.normalizeSuggestedQuestions(data.suggested_follow_ups || data.suggested_questions);
|
|
442
436
|
}
|
|
443
437
|
} catch (parseError) {
|
|
444
|
-
console.warn("\u26A0\uFE0F JSON.parse failed, using regex extraction...", parseError);
|
|
445
438
|
const responsePattern = /"response"\s*:\s*"([^"]*(?:\\.[^"]*)*)"/s;
|
|
446
439
|
const responseMatch = data.response.match(responsePattern);
|
|
447
440
|
if (responseMatch) {
|
|
448
441
|
responseText = responseMatch[1].replace(/\\n/g, "\n").replace(/\\t/g, " ").replace(/\\r/g, "\r").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
449
|
-
console.log("\u2705 Extracted response text, length:", responseText.length);
|
|
450
442
|
} else {
|
|
451
|
-
console.error("\u274C Could not extract response");
|
|
452
443
|
responseText = "Error: Could not parse response";
|
|
453
444
|
}
|
|
454
445
|
const faqsPattern = /"(?:faq_used|faqs_used)"\s*:\s*(\[[^\]]*\])/s;
|
|
@@ -456,15 +447,12 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
456
447
|
if (faqsMatch) {
|
|
457
448
|
try {
|
|
458
449
|
faqs = JSON.parse(faqsMatch[1]);
|
|
459
|
-
console.log("\u2705 Extracted FAQs, count:", faqs?.length || 0);
|
|
460
450
|
} catch {
|
|
461
|
-
console.log("\u26A0\uFE0F Could not parse FAQs, trying multiline...");
|
|
462
451
|
const faqsMultiPattern = /"(?:faq_used|faqs_used)"\s*:\s*(\[[\s\S]*?\n\s*\])/;
|
|
463
452
|
const faqsMultiMatch = data.response.match(faqsMultiPattern);
|
|
464
453
|
if (faqsMultiMatch) {
|
|
465
454
|
try {
|
|
466
455
|
faqs = JSON.parse(faqsMultiMatch[1]);
|
|
467
|
-
console.log("\u2705 Extracted multi-line FAQs, count:", faqs?.length || 0);
|
|
468
456
|
} catch {
|
|
469
457
|
faqs = void 0;
|
|
470
458
|
}
|
|
@@ -477,16 +465,13 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
477
465
|
try {
|
|
478
466
|
const parsedQuestions = JSON.parse(suggestedMatch[1]);
|
|
479
467
|
suggestedQuestions = this.normalizeSuggestedQuestions(parsedQuestions);
|
|
480
|
-
console.log("\u2705 Extracted suggested questions, count:", suggestedQuestions?.length || 0);
|
|
481
468
|
} catch {
|
|
482
|
-
console.log("\u26A0\uFE0F Could not parse suggested questions, trying multiline...");
|
|
483
469
|
const suggestedMultiPattern = /"(?:suggested_follow_ups|suggested_questions)"\s*:\s*(\[[\s\S]*?\n\s*\])/;
|
|
484
470
|
const suggestedMultiMatch = data.response.match(suggestedMultiPattern);
|
|
485
471
|
if (suggestedMultiMatch) {
|
|
486
472
|
try {
|
|
487
473
|
const parsedQuestions = JSON.parse(suggestedMultiMatch[1]);
|
|
488
474
|
suggestedQuestions = this.normalizeSuggestedQuestions(parsedQuestions);
|
|
489
|
-
console.log("\u2705 Extracted multi-line suggested questions, count:", suggestedQuestions?.length || 0);
|
|
490
475
|
} catch {
|
|
491
476
|
suggestedQuestions = void 0;
|
|
492
477
|
}
|
|
@@ -495,24 +480,17 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
495
480
|
}
|
|
496
481
|
}
|
|
497
482
|
} else {
|
|
498
|
-
console.log("\u{1F4C4} Direct text response (not JSON)");
|
|
499
483
|
responseText = data.response;
|
|
500
484
|
faqs = data.faq_used || data.faqs_used || void 0;
|
|
501
485
|
suggestedQuestions = this.normalizeSuggestedQuestions(data.suggested_follow_ups || data.suggested_questions);
|
|
502
486
|
}
|
|
503
487
|
} else if (typeof data === "string") {
|
|
504
|
-
console.log("\u{1F4C4} Response is a plain string");
|
|
505
488
|
responseText = data;
|
|
506
489
|
} else if (data && typeof data === "object") {
|
|
507
|
-
console.warn("\u26A0\uFE0F Unexpected format, using fallback");
|
|
508
490
|
responseText = data.message || data.answer || "Error: Unexpected response format";
|
|
509
491
|
faqs = data.faq_used || data.faqs_used || void 0;
|
|
510
492
|
suggestedQuestions = this.normalizeSuggestedQuestions(data.suggested_follow_ups || data.suggested_questions);
|
|
511
493
|
}
|
|
512
|
-
console.log("\u{1F3AF} Final responseText length:", responseText.length);
|
|
513
|
-
console.log("\u{1F3AF} Final responseText preview:", responseText.substring(0, 100));
|
|
514
|
-
console.log("\u{1F3AF} Final FAQs:", faqs);
|
|
515
|
-
console.log("\u{1F3AF} Final suggested questions:", suggestedQuestions);
|
|
516
494
|
const assistantMessage = {
|
|
517
495
|
id: (Date.now() + 1).toString(),
|
|
518
496
|
role: "assistant",
|
|
@@ -570,7 +548,9 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
570
548
|
})}
|
|
571
549
|
>
|
|
572
550
|
<div class="avatar">
|
|
573
|
-
${msg.role === "user" ?
|
|
551
|
+
${msg.role === "user" ? this.userAvatarUrl ? lit.html`<img src="${this.userAvatarUrl}" alt="User" class="avatar-image" />` : lit.html`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" style="width: 20px; height: 20px;">
|
|
552
|
+
<path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"/>
|
|
553
|
+
</svg>` : this.botAvatarUrl ? lit.html`<img src="${this.botAvatarUrl}" alt="AI" class="avatar-image" />` : "AI"}
|
|
574
554
|
</div>
|
|
575
555
|
<div class="message-content">
|
|
576
556
|
<div class="message-text">${unsafeHtml_js.unsafeHTML(this.formatMessageContent(msg.content))}</div>
|
|
@@ -588,7 +568,7 @@ ${this.welcomeSubtitle}` : this.welcomeMessage;
|
|
|
588
568
|
` : ""}
|
|
589
569
|
${msg.role === "assistant" && msg.suggestedQuestions && msg.suggestedQuestions.length > 0 ? lit.html`
|
|
590
570
|
<div class="faq-section">
|
|
591
|
-
<p class="faq-title">
|
|
571
|
+
<p class="faq-title">Cadangan Soalan:</p>
|
|
592
572
|
<ul class="faq-list">
|
|
593
573
|
${msg.suggestedQuestions.map((question) => lit.html`
|
|
594
574
|
<li class="faq-item" @click=${() => this.handleFAQClick(question)}>
|
|
@@ -1452,6 +1432,7 @@ exports.AIChat.properties = {
|
|
|
1452
1432
|
mode: { type: String, reflect: true },
|
|
1453
1433
|
initialMessages: { type: Array },
|
|
1454
1434
|
botAvatarUrl: { type: String, attribute: "bot-avatar-url" },
|
|
1435
|
+
userAvatarUrl: { type: String, attribute: "user-avatar-url" },
|
|
1455
1436
|
widgetIconUrl: { type: String, attribute: "widget-icon-url" },
|
|
1456
1437
|
backgroundImageUrl: { type: String, attribute: "background-image-url" },
|
|
1457
1438
|
widgetWidth: { type: String, attribute: "widget-width" },
|