@exotel-npm-dev/exotel-ai-assist 1.2.6 → 1.2.7
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/dist/components/key-components/SuggestionTab.d.ts +2 -1
- package/dist/controller/index.d.ts +1 -0
- package/dist/controller/index.js +27 -5
- package/dist/hooks/useExotelAIAssist.d.ts +1 -0
- package/dist/index.js +182 -45
- package/dist/react/index.js +182 -45
- package/dist/types/index.d.ts +18 -9
- package/package.json +1 -1
- package/src/components/ExotelAIAssistApp.tsx +2 -2
- package/src/components/key-components/SuggestionTab.tsx +100 -15
- package/src/controller/index.ts +29 -3
- package/src/hooks/useExotelAIAssist.ts +13 -2
- package/src/styles/index.css +62 -3
- package/src/types/index.ts +24 -11
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Suggestion, BotConfig } from "../../types";
|
|
2
2
|
import "../../styles/index.css";
|
|
3
|
-
export declare function SuggestionsTab({ suggestions, connected, botConfig, }: {
|
|
3
|
+
export declare function SuggestionsTab({ suggestions, connected, botConfig, sendSuggestionFeedback, }: {
|
|
4
4
|
suggestions: Suggestion[];
|
|
5
5
|
connected: boolean;
|
|
6
6
|
botConfig: BotConfig | null;
|
|
7
|
+
sendSuggestionFeedback: (sequence: number, feedbackType: "good" | "bad" | null, badFeedbackReason?: string | null) => boolean;
|
|
7
8
|
}): JSX.Element;
|
|
@@ -19,6 +19,7 @@ export declare class ExotelAIAssistController extends EventEmitter<ControllerEve
|
|
|
19
19
|
destroy(): void;
|
|
20
20
|
getStatus(): ConnectionStatus;
|
|
21
21
|
getStreamState(): StreamState | null;
|
|
22
|
+
sendSuggestionFeedback(sequence: number, feedbackType: "good" | "bad" | null, badFeedbackReason?: string | null): boolean;
|
|
22
23
|
private _ensureTransport;
|
|
23
24
|
private _handleTransportMessage;
|
|
24
25
|
private _scheduleReconnect;
|
package/dist/controller/index.js
CHANGED
|
@@ -1667,6 +1667,25 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
1667
1667
|
getStreamState() {
|
|
1668
1668
|
return this._streamState;
|
|
1669
1669
|
}
|
|
1670
|
+
sendSuggestionFeedback(sequence, feedbackType, badFeedbackReason = null) {
|
|
1671
|
+
if (!this.transport || this.status !== "connected") {
|
|
1672
|
+
console.warn("[ExotelAIAssist] Cannot send feedback: not connected");
|
|
1673
|
+
return false;
|
|
1674
|
+
}
|
|
1675
|
+
const message = {
|
|
1676
|
+
type: "suggestion_feedback",
|
|
1677
|
+
sequence,
|
|
1678
|
+
feedback_type: feedbackType,
|
|
1679
|
+
bad_feedback_reason: badFeedbackReason
|
|
1680
|
+
};
|
|
1681
|
+
try {
|
|
1682
|
+
this.transport.send(JSON.stringify(message));
|
|
1683
|
+
return true;
|
|
1684
|
+
} catch (error) {
|
|
1685
|
+
console.error("[ExotelAIAssist] Failed to send feedback:", error);
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1670
1689
|
_ensureTransport() {
|
|
1671
1690
|
if (this.transport) return;
|
|
1672
1691
|
this.transport = createTransport(Utils.hash(this.params));
|
|
@@ -1737,11 +1756,11 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
1737
1756
|
this.emit("onReady", true);
|
|
1738
1757
|
}
|
|
1739
1758
|
_handleServerPayload(raw) {
|
|
1740
|
-
var _a, _b
|
|
1759
|
+
var _a, _b;
|
|
1741
1760
|
let parsed;
|
|
1742
1761
|
try {
|
|
1743
1762
|
parsed = JSON.parse(raw);
|
|
1744
|
-
} catch (
|
|
1763
|
+
} catch (_c) {
|
|
1745
1764
|
this.emit("error", new Error(`Failed to parse server message: ${raw}`));
|
|
1746
1765
|
return;
|
|
1747
1766
|
}
|
|
@@ -1774,7 +1793,7 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
1774
1793
|
for (const event of events) {
|
|
1775
1794
|
if (!event) continue;
|
|
1776
1795
|
if (event.event_type === "transcript" && event.value) {
|
|
1777
|
-
const transcripts =
|
|
1796
|
+
const transcripts = event.value;
|
|
1778
1797
|
const lines = transcripts.map(msg => {
|
|
1779
1798
|
var _a, _b, _c;
|
|
1780
1799
|
const first = (_a = msg.transcript_segments) === null || _a === void 0 ? void 0 : _a[0];
|
|
@@ -1791,9 +1810,12 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
1791
1810
|
}
|
|
1792
1811
|
if (event.event_type === "suggestion" && event.value) {
|
|
1793
1812
|
const suggestion = {
|
|
1794
|
-
id:
|
|
1813
|
+
id: String(event.value.sequence),
|
|
1795
1814
|
value: event.value.text,
|
|
1796
|
-
timestamp: now
|
|
1815
|
+
timestamp: now,
|
|
1816
|
+
sequence: event.value.sequence,
|
|
1817
|
+
feedbackType: null,
|
|
1818
|
+
badFeedbackReason: null
|
|
1797
1819
|
};
|
|
1798
1820
|
this.emit("suggestion", suggestion);
|
|
1799
1821
|
}
|
|
@@ -25,6 +25,7 @@ export interface UseExotelAIAssistReturn {
|
|
|
25
25
|
connect: () => void;
|
|
26
26
|
disconnect: () => void;
|
|
27
27
|
setParams: (patch: Partial<ExotelAIAssistParams>) => void;
|
|
28
|
+
sendSuggestionFeedback: (sequence: number, feedbackType: "good" | "bad" | null, badFeedbackReason?: string | null) => boolean;
|
|
28
29
|
}
|
|
29
30
|
/** Internal extended return — adds botConfig for the UI component only. */
|
|
30
31
|
export interface UseExotelAIAssistInternalReturn extends UseExotelAIAssistReturn {
|
package/dist/index.js
CHANGED
|
@@ -19294,6 +19294,30 @@ const Smile = createLucideIcon$1("Smile", [["circle", {
|
|
|
19294
19294
|
key: "1p4y9e"
|
|
19295
19295
|
}]]);
|
|
19296
19296
|
|
|
19297
|
+
/**
|
|
19298
|
+
* lucide-react v0.0.1 - ISC
|
|
19299
|
+
*/
|
|
19300
|
+
|
|
19301
|
+
const ThumbsDown = createLucideIcon$1("ThumbsDown", [["path", {
|
|
19302
|
+
d: "M17 14V2",
|
|
19303
|
+
key: "8ymqnk"
|
|
19304
|
+
}], ["path", {
|
|
19305
|
+
d: "M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H20a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.76a2 2 0 0 0-1.79 1.11L12 22h0a3.13 3.13 0 0 1-3-3.88Z",
|
|
19306
|
+
key: "s6e0r"
|
|
19307
|
+
}]]);
|
|
19308
|
+
|
|
19309
|
+
/**
|
|
19310
|
+
* lucide-react v0.0.1 - ISC
|
|
19311
|
+
*/
|
|
19312
|
+
|
|
19313
|
+
const ThumbsUp = createLucideIcon$1("ThumbsUp", [["path", {
|
|
19314
|
+
d: "M7 10v12",
|
|
19315
|
+
key: "1qc93n"
|
|
19316
|
+
}], ["path", {
|
|
19317
|
+
d: "M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2h0a3.13 3.13 0 0 1 3 3.88Z",
|
|
19318
|
+
key: "y3tblf"
|
|
19319
|
+
}]]);
|
|
19320
|
+
|
|
19297
19321
|
const MAX_VISIBLE_TOASTS = 5;
|
|
19298
19322
|
const AUTO_DISMISS_MS = 3000;
|
|
19299
19323
|
const ToastContext = reactExports.createContext(null);
|
|
@@ -21085,6 +21109,25 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
21085
21109
|
getStreamState() {
|
|
21086
21110
|
return this._streamState;
|
|
21087
21111
|
}
|
|
21112
|
+
sendSuggestionFeedback(sequence, feedbackType, badFeedbackReason = null) {
|
|
21113
|
+
if (!this.transport || this.status !== "connected") {
|
|
21114
|
+
console.warn("[ExotelAIAssist] Cannot send feedback: not connected");
|
|
21115
|
+
return false;
|
|
21116
|
+
}
|
|
21117
|
+
const message = {
|
|
21118
|
+
type: "suggestion_feedback",
|
|
21119
|
+
sequence,
|
|
21120
|
+
feedback_type: feedbackType,
|
|
21121
|
+
bad_feedback_reason: badFeedbackReason
|
|
21122
|
+
};
|
|
21123
|
+
try {
|
|
21124
|
+
this.transport.send(JSON.stringify(message));
|
|
21125
|
+
return true;
|
|
21126
|
+
} catch (error) {
|
|
21127
|
+
console.error("[ExotelAIAssist] Failed to send feedback:", error);
|
|
21128
|
+
return false;
|
|
21129
|
+
}
|
|
21130
|
+
}
|
|
21088
21131
|
_ensureTransport() {
|
|
21089
21132
|
if (this.transport) return;
|
|
21090
21133
|
this.transport = createTransport(Utils.hash(this.params));
|
|
@@ -21155,11 +21198,11 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
21155
21198
|
this.emit("onReady", true);
|
|
21156
21199
|
}
|
|
21157
21200
|
_handleServerPayload(raw) {
|
|
21158
|
-
var _a, _b
|
|
21201
|
+
var _a, _b;
|
|
21159
21202
|
let parsed;
|
|
21160
21203
|
try {
|
|
21161
21204
|
parsed = JSON.parse(raw);
|
|
21162
|
-
} catch (
|
|
21205
|
+
} catch (_c) {
|
|
21163
21206
|
this.emit("error", new Error(`Failed to parse server message: ${raw}`));
|
|
21164
21207
|
return;
|
|
21165
21208
|
}
|
|
@@ -21192,7 +21235,7 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
21192
21235
|
for (const event of events) {
|
|
21193
21236
|
if (!event) continue;
|
|
21194
21237
|
if (event.event_type === "transcript" && event.value) {
|
|
21195
|
-
const transcripts =
|
|
21238
|
+
const transcripts = event.value;
|
|
21196
21239
|
const lines = transcripts.map(msg => {
|
|
21197
21240
|
var _a, _b, _c;
|
|
21198
21241
|
const first = (_a = msg.transcript_segments) === null || _a === void 0 ? void 0 : _a[0];
|
|
@@ -21209,9 +21252,12 @@ class ExotelAIAssistController extends EventEmitter {
|
|
|
21209
21252
|
}
|
|
21210
21253
|
if (event.event_type === "suggestion" && event.value) {
|
|
21211
21254
|
const suggestion = {
|
|
21212
|
-
id:
|
|
21255
|
+
id: String(event.value.sequence),
|
|
21213
21256
|
value: event.value.text,
|
|
21214
|
-
timestamp: now
|
|
21257
|
+
timestamp: now,
|
|
21258
|
+
sequence: event.value.sequence,
|
|
21259
|
+
feedbackType: null,
|
|
21260
|
+
badFeedbackReason: null
|
|
21215
21261
|
};
|
|
21216
21262
|
this.emit("suggestion", suggestion);
|
|
21217
21263
|
}
|
|
@@ -21293,9 +21339,20 @@ function useExotelAIAssist(params) {
|
|
|
21293
21339
|
var _a;
|
|
21294
21340
|
return (_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.setParams(patch);
|
|
21295
21341
|
}, []);
|
|
21342
|
+
const sendSuggestionFeedback = reactExports.useCallback((sequence, feedbackType, badFeedbackReason = null) => {
|
|
21343
|
+
var _a, _b;
|
|
21344
|
+
const sent = (_b = (_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.sendSuggestionFeedback(sequence, feedbackType, badFeedbackReason)) !== null && _b !== void 0 ? _b : false;
|
|
21345
|
+
if (sent) {
|
|
21346
|
+
setSuggestions(prev => prev.map(s => s.sequence === sequence ? Object.assign(Object.assign({}, s), {
|
|
21347
|
+
feedbackType,
|
|
21348
|
+
badFeedbackReason
|
|
21349
|
+
}) : s));
|
|
21350
|
+
}
|
|
21351
|
+
return sent;
|
|
21352
|
+
}, []);
|
|
21296
21353
|
return {
|
|
21297
|
-
isReady,
|
|
21298
21354
|
streamState,
|
|
21355
|
+
isReady,
|
|
21299
21356
|
suggestions,
|
|
21300
21357
|
transcripts,
|
|
21301
21358
|
sentiment,
|
|
@@ -21303,7 +21360,8 @@ function useExotelAIAssist(params) {
|
|
|
21303
21360
|
lastError,
|
|
21304
21361
|
connect,
|
|
21305
21362
|
disconnect,
|
|
21306
|
-
setParams
|
|
21363
|
+
setParams,
|
|
21364
|
+
sendSuggestionFeedback
|
|
21307
21365
|
};
|
|
21308
21366
|
}
|
|
21309
21367
|
|
|
@@ -21332,7 +21390,7 @@ function styleInject(css, ref) {
|
|
|
21332
21390
|
}
|
|
21333
21391
|
}
|
|
21334
21392
|
|
|
21335
|
-
var css_248z = ".oa-panel{background:#fff;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif}.oa-panel,.oa-theme-root{display:flex;flex-direction:column;height:100%;min-height:0;width:100%}.oa-theme-root{position:relative}.oa-header-title{color:#111827;font-size:16px;font-weight:600;line-height:20px;margin:0}.oa-tabs{width:100%}.oa-tabs-content{flex:1;min-height:0;overflow:hidden}.oa-tabs-content[data-state=inactive]{display:none!important}.oa-tabs-content[data-state=active]{display:flex;flex-direction:column}.oa-tabs-list{border-bottom:1px solid #e5e7eb;display:flex;gap:20px;padding:0}.oa-tabs-trigger{align-items:center;background:transparent;border:none;border-radius:0;color:#6b7280;cursor:pointer;display:inline-flex;font-size:15px;font-weight:500;gap:6px;outline:none;padding:10px 0;position:relative}.oa-tabs-trigger:hover{color:#374151}.oa-tabs-trigger[data-state=active]{color:#2563eb}.oa-tabs-trigger[data-state=active]:after{background:#2563eb;border-radius:2px;bottom:-1px;content:\"\";height:2px;left:0;position:absolute;right:0}.oa-suggestion-card{border:1px solid rgba(17,24,39,.04);border-radius:12px;padding:12px;text-align:left}.oa-suggestion-card--recent-wrapper{animation:oa-suggestion-enter .4s ease-out,oa-border-shimmer 3s ease-in-out .4s infinite;background:linear-gradient(90deg,#7c3aed,#e11d48,#7c3aed);background-size:200% 100%;border-radius:12px;padding:2px;text-align:left}.oa-suggestion-card--recent-wrapper .oa-suggestion-card--recent{border:none}.oa-suggestion-card--recent{animation:none;background:linear-gradient(90deg,#f5f3ff 0,#fef3f2 50%,#fff7ed);border-radius:9px}.oa-suggestion-card--older{background:#f5f5f5;border:1px solid #e5e7eb}.oa-suggestion-card--older .oa-suggestion-text{color:#252525}@keyframes oa-suggestion-enter{0%{opacity:.3;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@keyframes oa-border-shimmer{0%,to{background-position:0 50%}50%{background-position:100% 50%}}.oa-suggestion-text{color:#111827;font-size:13px;line-height:18px;white-space:pre-wrap}.oa-copy-icon{align-items:center;background:#fff;border:1px solid #e5e7eb;border-radius:8px;color:#6b7280;cursor:pointer;display:inline-flex;height:32px;justify-content:center;min-height:32px;min-width:32px;padding:0;width:32px}.oa-copy-icon:hover{background:#f9fafb;color:#374151}@keyframes oa-toast-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.oa-stream-overlay{display:flex;flex:1;flex-direction:column;min-height:0}.oa-stream-banner{align-items:flex-start;background:#fef3c7;border:1px solid #fde68a;border-radius:8px;color:#92400e;display:flex;font-size:13px;gap:8px;line-height:1.4;padding:10px 12px}.oa-stream-banner-icon{align-items:center;display:inline-flex;flex-shrink:0;margin-top:1px}.oa-stream-banner-text{flex:1}.oa-stream-empty{flex:1;gap:16px;justify-content:center;min-height:0}.oa-stream-empty,.oa-stream-empty-text{align-items:center;display:flex;flex-direction:column}.oa-stream-empty-text{gap:6px;text-align:center}.oa-stream-empty-title{color:#111827;font-size:16px;font-weight:700;line-height:20px}.oa-stream-empty-subtitle{color:#6b7280;font-size:14px;line-height:20px}.oa-throttle-banner{align-items:flex-start;background:#fcefee;border:1px solid #e8cecb;border-radius:8px;color:#833d09;display:flex;font-size:13px;gap:8px;line-height:1.4;padding:10px 12px}.oa-throttle-banner-icon{align-items:center;display:inline-flex;flex-shrink:0;margin-top:1px}.oa-throttle-banner-text{flex:1}.oa-starting-loader{align-items:center;display:flex;flex:1;flex-direction:column;gap:16px;height:100%;justify-content:center;min-height:0}.oa-starting-spinner{animation:oa-spinner-rotate 1.4s linear infinite;height:48px;width:48px}.oa-starting-spinner-track{stroke:#e5e7eb}.oa-starting-spinner-arc{stroke:#2563eb;stroke-dasharray:80,126;stroke-dashoffset:0;animation:oa-spinner-dash 1.4s ease-in-out infinite}@keyframes oa-spinner-rotate{to{transform:rotate(1turn)}}@keyframes oa-spinner-dash{0%{stroke-dasharray:1,126;stroke-dashoffset:0}50%{stroke-dasharray:80,126;stroke-dashoffset:-35}to{stroke-dasharray:80,126;stroke-dashoffset:-124}}.oa-starting-loader-text{color:#111827;font-size:16px;font-weight:600;line-height:20px}.oa-muted{color:#6b7280}";
|
|
21393
|
+
var css_248z = ".oa-panel{background:#fff;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif}.oa-panel,.oa-theme-root{display:flex;flex-direction:column;height:100%;min-height:0;width:100%}.oa-theme-root{position:relative}.oa-header-title{color:#111827;font-size:16px;font-weight:600;line-height:20px;margin:0}.oa-tabs{width:100%}.oa-tabs-content{flex:1;min-height:0;overflow:hidden}.oa-tabs-content[data-state=inactive]{display:none!important}.oa-tabs-content[data-state=active]{display:flex;flex-direction:column}.oa-tabs-list{border-bottom:1px solid #e5e7eb;display:flex;gap:20px;padding:0}.oa-tabs-trigger{align-items:center;background:transparent;border:none;border-radius:0;color:#6b7280;cursor:pointer;display:inline-flex;font-size:15px;font-weight:500;gap:6px;outline:none;padding:10px 0;position:relative}.oa-tabs-trigger:hover{color:#374151}.oa-tabs-trigger[data-state=active]{color:#2563eb}.oa-tabs-trigger[data-state=active]:after{background:#2563eb;border-radius:2px;bottom:-1px;content:\"\";height:2px;left:0;position:absolute;right:0}.oa-suggestion-card{border:1px solid rgba(17,24,39,.04);border-radius:12px;padding:12px;text-align:left}.oa-suggestion-card--recent-wrapper{animation:oa-suggestion-enter .4s ease-out,oa-border-shimmer 3s ease-in-out .4s infinite;background:linear-gradient(90deg,#7c3aed,#e11d48,#7c3aed);background-size:200% 100%;border-radius:12px;padding:2px;text-align:left}.oa-suggestion-card--recent-wrapper .oa-suggestion-card--recent{border:none}.oa-suggestion-card--recent{animation:none;background:linear-gradient(90deg,#f5f3ff 0,#fef3f2 50%,#fff7ed);border-radius:9px}.oa-suggestion-card--older{background:#f5f5f5;border:1px solid #e5e7eb}.oa-suggestion-card--older .oa-suggestion-text{color:#252525}@keyframes oa-suggestion-enter{0%{opacity:.3;transform:scale(.97)}to{opacity:1;transform:scale(1)}}@keyframes oa-border-shimmer{0%,to{background-position:0 50%}50%{background-position:100% 50%}}.oa-suggestion-text{color:#111827;font-size:13px;line-height:18px;white-space:pre-wrap}.oa-copy-icon,.oa-feedback-icon{align-items:center;background:#fff;border:1px solid #e5e7eb;border-radius:8px;color:#6b7280;cursor:pointer;display:inline-flex;height:32px;justify-content:center;min-height:32px;min-width:32px;padding:0;width:32px}.oa-copy-icon:hover,.oa-feedback-icon:hover{background:#f9fafb;color:#374151}.oa-feedback-icon--positive{background:#dcfce7!important;border-color:#86efac!important;color:#16a34a!important}.oa-feedback-icon--negative{background:#fee2e2!important;border-color:#fca5a5!important;color:#dc2626!important}.oa-feedback-icon:disabled{cursor:default;opacity:.5}.oa-feedback-icon--negative:disabled,.oa-feedback-icon--positive:disabled{opacity:1}.oa-feedback-reason-btn{align-items:center;background:#fef2f2;border:1px solid #fecaca;border-radius:16px;color:#991b1b;cursor:pointer;display:inline-flex;font-family:inherit;font-size:12px;font-weight:500;line-height:18px;padding:4px 12px;transition:background .15s,border-color .15s}.oa-feedback-reason-btn:hover:not(:disabled){background:#fee2e2;border-color:#f87171}.oa-feedback-reason-btn--selected{background:#dc2626!important;border-color:#dc2626!important;color:#fff!important}.oa-feedback-reason-btn:disabled{cursor:default;opacity:.45}@keyframes oa-toast-in{0%{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}}.oa-stream-overlay{display:flex;flex:1;flex-direction:column;min-height:0}.oa-stream-banner{align-items:flex-start;background:#fef3c7;border:1px solid #fde68a;border-radius:8px;color:#92400e;display:flex;font-size:13px;gap:8px;line-height:1.4;padding:10px 12px}.oa-stream-banner-icon{align-items:center;display:inline-flex;flex-shrink:0;margin-top:1px}.oa-stream-banner-text{flex:1}.oa-stream-empty{flex:1;gap:16px;justify-content:center;min-height:0}.oa-stream-empty,.oa-stream-empty-text{align-items:center;display:flex;flex-direction:column}.oa-stream-empty-text{gap:6px;text-align:center}.oa-stream-empty-title{color:#111827;font-size:16px;font-weight:700;line-height:20px}.oa-stream-empty-subtitle{color:#6b7280;font-size:14px;line-height:20px}.oa-throttle-banner{align-items:flex-start;background:#fcefee;border:1px solid #e8cecb;border-radius:8px;color:#833d09;display:flex;font-size:13px;gap:8px;line-height:1.4;padding:10px 12px}.oa-throttle-banner-icon{align-items:center;display:inline-flex;flex-shrink:0;margin-top:1px}.oa-throttle-banner-text{flex:1}.oa-starting-loader{align-items:center;display:flex;flex:1;flex-direction:column;gap:16px;height:100%;justify-content:center;min-height:0}.oa-starting-spinner{animation:oa-spinner-rotate 1.4s linear infinite;height:48px;width:48px}.oa-starting-spinner-track{stroke:#e5e7eb}.oa-starting-spinner-arc{stroke:#2563eb;stroke-dasharray:80,126;stroke-dashoffset:0;animation:oa-spinner-dash 1.4s ease-in-out infinite}@keyframes oa-spinner-rotate{to{transform:rotate(1turn)}}@keyframes oa-spinner-dash{0%{stroke-dasharray:1,126;stroke-dashoffset:0}50%{stroke-dasharray:80,126;stroke-dashoffset:-35}to{stroke-dasharray:80,126;stroke-dashoffset:-124}}.oa-starting-loader-text{color:#111827;font-size:16px;font-weight:600;line-height:20px}.oa-muted{color:#6b7280}";
|
|
21336
21394
|
styleInject(css_248z);
|
|
21337
21395
|
|
|
21338
21396
|
function Sparkle() {
|
|
@@ -21680,9 +21738,17 @@ const EmptyState = ({
|
|
|
21680
21738
|
function SuggestionsTab({
|
|
21681
21739
|
suggestions,
|
|
21682
21740
|
connected,
|
|
21683
|
-
botConfig
|
|
21741
|
+
botConfig,
|
|
21742
|
+
sendSuggestionFeedback
|
|
21684
21743
|
}) {
|
|
21744
|
+
var _a, _b, _c;
|
|
21685
21745
|
const toast = useToast();
|
|
21746
|
+
const [expandedSequence, setExpandedSequence] = reactExports.useState(null);
|
|
21747
|
+
const feedbackEnabled = ((_a = botConfig === null || botConfig === void 0 ? void 0 : botConfig.suggestion) === null || _a === void 0 ? void 0 : _a.feedback_enabled) === true;
|
|
21748
|
+
const badFeedbackOptions = reactExports.useMemo(() => {
|
|
21749
|
+
var _a, _b;
|
|
21750
|
+
return (_b = (_a = botConfig === null || botConfig === void 0 ? void 0 : botConfig.suggestion) === null || _a === void 0 ? void 0 : _a.bad_feedback_options) !== null && _b !== void 0 ? _b : [];
|
|
21751
|
+
}, [(_b = botConfig === null || botConfig === void 0 ? void 0 : botConfig.suggestion) === null || _b === void 0 ? void 0 : _b.bad_feedback_options]);
|
|
21686
21752
|
const handleCopy = async text => {
|
|
21687
21753
|
try {
|
|
21688
21754
|
await navigator.clipboard.writeText(text);
|
|
@@ -21691,13 +21757,33 @@ function SuggestionsTab({
|
|
|
21691
21757
|
toast.error("Failed to copy");
|
|
21692
21758
|
}
|
|
21693
21759
|
};
|
|
21760
|
+
const handleThumbsUp = reactExports.useCallback((sequence, currentFeedback) => {
|
|
21761
|
+
const newType = currentFeedback === "good" ? null : "good";
|
|
21762
|
+
sendSuggestionFeedback(sequence, newType, null);
|
|
21763
|
+
setExpandedSequence(null);
|
|
21764
|
+
}, [sendSuggestionFeedback]);
|
|
21765
|
+
const handleThumbsDown = reactExports.useCallback((sequence, currentFeedback) => {
|
|
21766
|
+
if (currentFeedback === "bad") {
|
|
21767
|
+
sendSuggestionFeedback(sequence, null, null);
|
|
21768
|
+
setExpandedSequence(null);
|
|
21769
|
+
return;
|
|
21770
|
+
}
|
|
21771
|
+
sendSuggestionFeedback(sequence, "bad", null);
|
|
21772
|
+
if (badFeedbackOptions.length > 0) {
|
|
21773
|
+
setExpandedSequence(sequence);
|
|
21774
|
+
}
|
|
21775
|
+
}, [sendSuggestionFeedback, badFeedbackOptions]);
|
|
21776
|
+
const handleBadFeedbackReason = reactExports.useCallback((sequence, reason) => {
|
|
21777
|
+
sendSuggestionFeedback(sequence, "bad", reason);
|
|
21778
|
+
setExpandedSequence(null);
|
|
21779
|
+
}, [sendSuggestionFeedback]);
|
|
21694
21780
|
if (!connected) {
|
|
21695
21781
|
return jsxRuntimeExports.jsx(EmptyState, {
|
|
21696
21782
|
title: "Assistant is inactive",
|
|
21697
21783
|
subtitle: "Start a call to receive real-time suggestions."
|
|
21698
21784
|
});
|
|
21699
21785
|
}
|
|
21700
|
-
if ((botConfig === null || botConfig === void 0 ? void 0 : botConfig.
|
|
21786
|
+
if (((_c = botConfig === null || botConfig === void 0 ? void 0 : botConfig.suggestion) === null || _c === void 0 ? void 0 : _c.enabled) === false) {
|
|
21701
21787
|
return jsxRuntimeExports.jsx(EmptyState, {
|
|
21702
21788
|
title: "Suggestions are disabled",
|
|
21703
21789
|
subtitle: "Suggestions are disabled in the bot configuration. Please contact the administrator to enable it."
|
|
@@ -21731,21 +21817,44 @@ function SuggestionsTab({
|
|
|
21731
21817
|
children: displayed.map((suggestion, index) => {
|
|
21732
21818
|
const isRecent = index === 0;
|
|
21733
21819
|
const cardClass = isRecent ? "oa-suggestion-card oa-suggestion-card--recent" : "oa-suggestion-card oa-suggestion-card--older";
|
|
21820
|
+
const showReasons = suggestion.feedbackType === "bad" || expandedSequence === suggestion.sequence;
|
|
21821
|
+
const cardMinHeight = feedbackEnabled ? "108px" : undefined;
|
|
21734
21822
|
return jsxRuntimeExports.jsxs("div", {
|
|
21735
|
-
|
|
21736
|
-
display: "flex",
|
|
21737
|
-
flexDirection: "row",
|
|
21738
|
-
alignItems: "flex-start",
|
|
21739
|
-
gap: "8px"
|
|
21740
|
-
},
|
|
21741
|
-
children: [isRecent ? jsxRuntimeExports.jsx("div", {
|
|
21742
|
-
className: "oa-suggestion-card--recent-wrapper",
|
|
21823
|
+
children: [jsxRuntimeExports.jsxs("div", {
|
|
21743
21824
|
style: {
|
|
21744
|
-
|
|
21745
|
-
|
|
21825
|
+
display: "flex",
|
|
21826
|
+
flexDirection: "row",
|
|
21827
|
+
alignItems: "flex-start",
|
|
21828
|
+
gap: "8px"
|
|
21746
21829
|
},
|
|
21747
|
-
children: jsxRuntimeExports.jsx("div", {
|
|
21830
|
+
children: [isRecent ? jsxRuntimeExports.jsx("div", {
|
|
21831
|
+
className: "oa-suggestion-card--recent-wrapper",
|
|
21832
|
+
style: {
|
|
21833
|
+
flex: "1 1 auto",
|
|
21834
|
+
maxWidth: "72%",
|
|
21835
|
+
minHeight: cardMinHeight
|
|
21836
|
+
},
|
|
21837
|
+
children: jsxRuntimeExports.jsx("div", {
|
|
21838
|
+
className: cardClass,
|
|
21839
|
+
style: {
|
|
21840
|
+
minHeight: cardMinHeight ? `calc(${cardMinHeight} - 4px)` : undefined,
|
|
21841
|
+
height: "100%"
|
|
21842
|
+
},
|
|
21843
|
+
children: jsxRuntimeExports.jsx("span", {
|
|
21844
|
+
className: "oa-suggestion-text",
|
|
21845
|
+
style: {
|
|
21846
|
+
fontSize: "15px"
|
|
21847
|
+
},
|
|
21848
|
+
children: suggestion.value
|
|
21849
|
+
})
|
|
21850
|
+
})
|
|
21851
|
+
}) : jsxRuntimeExports.jsx("div", {
|
|
21748
21852
|
className: cardClass,
|
|
21853
|
+
style: {
|
|
21854
|
+
flex: "1 1 auto",
|
|
21855
|
+
maxWidth: "72%",
|
|
21856
|
+
minHeight: cardMinHeight
|
|
21857
|
+
},
|
|
21749
21858
|
children: jsxRuntimeExports.jsx("span", {
|
|
21750
21859
|
className: "oa-suggestion-text",
|
|
21751
21860
|
style: {
|
|
@@ -21753,31 +21862,57 @@ function SuggestionsTab({
|
|
|
21753
21862
|
},
|
|
21754
21863
|
children: suggestion.value
|
|
21755
21864
|
})
|
|
21756
|
-
})
|
|
21757
|
-
}) : jsxRuntimeExports.jsx("div", {
|
|
21758
|
-
className: cardClass,
|
|
21759
|
-
style: {
|
|
21760
|
-
flex: "1 1 auto",
|
|
21761
|
-
maxWidth: "80%"
|
|
21762
|
-
},
|
|
21763
|
-
children: jsxRuntimeExports.jsx("span", {
|
|
21764
|
-
className: "oa-suggestion-text",
|
|
21865
|
+
}), jsxRuntimeExports.jsxs("div", {
|
|
21765
21866
|
style: {
|
|
21766
|
-
|
|
21867
|
+
display: "flex",
|
|
21868
|
+
flexDirection: "column",
|
|
21869
|
+
gap: "4px",
|
|
21870
|
+
flexShrink: 0,
|
|
21871
|
+
marginTop: "10px"
|
|
21767
21872
|
},
|
|
21768
|
-
children:
|
|
21769
|
-
|
|
21770
|
-
|
|
21771
|
-
|
|
21772
|
-
|
|
21773
|
-
|
|
21873
|
+
children: [jsxRuntimeExports.jsx("button", {
|
|
21874
|
+
className: "oa-copy-icon",
|
|
21875
|
+
"aria-label": "Copy suggestion",
|
|
21876
|
+
onClick: () => handleCopy(suggestion.value),
|
|
21877
|
+
children: jsxRuntimeExports.jsx(Copy, {
|
|
21878
|
+
size: 14
|
|
21879
|
+
})
|
|
21880
|
+
}), feedbackEnabled && jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, {
|
|
21881
|
+
children: [jsxRuntimeExports.jsx("button", {
|
|
21882
|
+
className: `oa-feedback-icon ${suggestion.feedbackType === "good" ? "oa-feedback-icon--positive" : ""}`,
|
|
21883
|
+
"aria-label": "Mark as helpful",
|
|
21884
|
+
onClick: () => handleThumbsUp(suggestion.sequence, suggestion.feedbackType),
|
|
21885
|
+
style: {
|
|
21886
|
+
color: suggestion.feedbackType === "good" ? "#16a34a" : undefined
|
|
21887
|
+
},
|
|
21888
|
+
children: jsxRuntimeExports.jsx(ThumbsUp, {
|
|
21889
|
+
size: 14
|
|
21890
|
+
})
|
|
21891
|
+
}), jsxRuntimeExports.jsx("button", {
|
|
21892
|
+
className: `oa-feedback-icon ${suggestion.feedbackType === "bad" ? "oa-feedback-icon--negative" : ""}`,
|
|
21893
|
+
"aria-label": "Mark as not helpful",
|
|
21894
|
+
onClick: () => handleThumbsDown(suggestion.sequence, suggestion.feedbackType),
|
|
21895
|
+
style: {
|
|
21896
|
+
color: suggestion.feedbackType === "bad" ? "#dc2626" : undefined
|
|
21897
|
+
},
|
|
21898
|
+
children: jsxRuntimeExports.jsx(ThumbsDown, {
|
|
21899
|
+
size: 14
|
|
21900
|
+
})
|
|
21901
|
+
})]
|
|
21902
|
+
})]
|
|
21903
|
+
})]
|
|
21904
|
+
}), showReasons && badFeedbackOptions.length > 0 && jsxRuntimeExports.jsx("div", {
|
|
21774
21905
|
style: {
|
|
21775
|
-
|
|
21776
|
-
|
|
21906
|
+
display: "flex",
|
|
21907
|
+
gap: "8px",
|
|
21908
|
+
flexWrap: "wrap",
|
|
21909
|
+
marginTop: "8px"
|
|
21777
21910
|
},
|
|
21778
|
-
children: jsxRuntimeExports.jsx(
|
|
21779
|
-
|
|
21780
|
-
|
|
21911
|
+
children: badFeedbackOptions.map(reason => jsxRuntimeExports.jsx("button", {
|
|
21912
|
+
className: `oa-feedback-reason-btn ${suggestion.badFeedbackReason === reason ? "oa-feedback-reason-btn--selected" : ""}`,
|
|
21913
|
+
onClick: () => handleBadFeedbackReason(suggestion.sequence, reason),
|
|
21914
|
+
children: reason
|
|
21915
|
+
}, reason))
|
|
21781
21916
|
})]
|
|
21782
21917
|
}, suggestion.id);
|
|
21783
21918
|
})
|
|
@@ -21876,12 +22011,13 @@ function ExotelAIAssist(_a) {
|
|
|
21876
22011
|
} = _a,
|
|
21877
22012
|
params = __rest(_a, ["className", "onReady"]);
|
|
21878
22013
|
const {
|
|
21879
|
-
isReady,
|
|
21880
22014
|
streamState,
|
|
22015
|
+
isReady,
|
|
21881
22016
|
suggestions,
|
|
21882
22017
|
transcripts,
|
|
21883
22018
|
sentiment,
|
|
21884
|
-
botConfig
|
|
22019
|
+
botConfig,
|
|
22020
|
+
sendSuggestionFeedback
|
|
21885
22021
|
} = useExotelAIAssist(params);
|
|
21886
22022
|
const onReadyRef = reactExports.useRef(onReady);
|
|
21887
22023
|
onReadyRef.current = onReady;
|
|
@@ -21959,7 +22095,8 @@ function ExotelAIAssist(_a) {
|
|
|
21959
22095
|
children: jsxRuntimeExports.jsx(SuggestionsTab, {
|
|
21960
22096
|
suggestions: suggestions,
|
|
21961
22097
|
connected: connected,
|
|
21962
|
-
botConfig: botConfig
|
|
22098
|
+
botConfig: botConfig,
|
|
22099
|
+
sendSuggestionFeedback: sendSuggestionFeedback
|
|
21963
22100
|
})
|
|
21964
22101
|
}), jsxRuntimeExports.jsx(Content$1, {
|
|
21965
22102
|
value: "transcript",
|