@exotel-npm-dev/exotel-ai-assist 1.2.5 → 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/README.md +35 -32
- package/dist/components/key-components/SuggestionTab.d.ts +2 -1
- package/dist/controller/index.d.ts +1 -0
- package/dist/controller/index.js +30 -8
- package/dist/hooks/useExotelAIAssist.d.ts +1 -0
- package/dist/index.js +186 -49
- package/dist/react/index.js +186 -49
- package/dist/types/index.d.ts +32 -6
- package/package.json +1 -1
- package/src/components/ExotelAIAssistApp.tsx +3 -3
- package/src/components/key-components/SuggestionTab.tsx +100 -15
- package/src/controller/index.ts +32 -6
- package/src/hooks/useExotelAIAssist.ts +13 -2
- package/src/styles/index.css +62 -3
- package/src/types/index.ts +42 -7
package/README.md
CHANGED
|
@@ -123,11 +123,12 @@ function MyCustomUI({ call_sid }: { call_sid: string }) {
|
|
|
123
123
|
|
|
124
124
|
if (streamState === "throttled") return <p>AI Assist is at capacity — available on your next call.</p>;
|
|
125
125
|
if (streamState === "disconnected") return <p>AI Assist disconnected.</p>;
|
|
126
|
+
if (streamState === "connection_timeout") return <p>Connection timed out.</p>;
|
|
126
127
|
|
|
127
128
|
return (
|
|
128
129
|
<div>
|
|
129
130
|
{suggestions.map((s) => (
|
|
130
|
-
<p key={s.id}>{s.
|
|
131
|
+
<p key={s.id}>{s.value}</p>
|
|
131
132
|
))}
|
|
132
133
|
</div>
|
|
133
134
|
);
|
|
@@ -153,7 +154,7 @@ function SuggestionsPanel() {
|
|
|
153
154
|
return (
|
|
154
155
|
<ul>
|
|
155
156
|
{suggestions.map((s) => (
|
|
156
|
-
<li key={s.id}>{s.
|
|
157
|
+
<li key={s.id}>{s.value}</li>
|
|
157
158
|
))}
|
|
158
159
|
</ul>
|
|
159
160
|
);
|
|
@@ -188,7 +189,7 @@ ctrl.on("suggestion", (s) => console.log("Suggestion:", s));
|
|
|
188
189
|
ctrl.on("transcript", (t) => console.log("Transcript:", t));
|
|
189
190
|
ctrl.on("streamState", (state) => {
|
|
190
191
|
console.log("Stream state:", state);
|
|
191
|
-
// state: "connected" | "throttled" | "disconnected"
|
|
192
|
+
// state: "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout"
|
|
192
193
|
});
|
|
193
194
|
ctrl.on("error", (err) => console.error("Error:", err));
|
|
194
195
|
|
|
@@ -238,14 +239,14 @@ Extends `EventEmitter`.
|
|
|
238
239
|
|
|
239
240
|
#### Methods
|
|
240
241
|
|
|
241
|
-
| Method
|
|
242
|
-
|
|
|
243
|
-
| `connect()`
|
|
244
|
-
| `disconnect()`
|
|
245
|
-
| `setParams(patch)`
|
|
246
|
-
| `destroy()`
|
|
247
|
-
| `getStatus()`
|
|
248
|
-
| `getStreamState()`
|
|
242
|
+
| Method | Description |
|
|
243
|
+
| --------------------------------------- | ---------------------------------------------- |
|
|
244
|
+
| `connect()` | Open the WebSocket |
|
|
245
|
+
| `disconnect()` | Close cleanly |
|
|
246
|
+
| `setParams(patch)` | Merge params; reconnects if `call_sid` changes |
|
|
247
|
+
| `destroy()` | Dispose controller and remove all listeners |
|
|
248
|
+
| `getStatus()` | Returns current `ConnectionStatus` |
|
|
249
|
+
| `getStreamState()` | Returns current `StreamState \| null` |
|
|
249
250
|
|
|
250
251
|
#### Events
|
|
251
252
|
|
|
@@ -255,7 +256,7 @@ Extends `EventEmitter`.
|
|
|
255
256
|
| `suggestion` | `Suggestion` | New AI suggestion (capped at last 50) |
|
|
256
257
|
| `transcript` | `TranscriptLine[]` | Live transcript update |
|
|
257
258
|
| `sentiment` | `Sentiment` | Sentiment label update |
|
|
258
|
-
| `streamState` | `StreamState` | Server stream state change (`connected`, `throttled`, `disconnected`)
|
|
259
|
+
| `streamState` | `StreamState` | Server stream state change (`connected`, `throttled`, `pending`, `disconnected`, `connection_timeout`) |
|
|
259
260
|
| `onCallStart` | — | Connection opened |
|
|
260
261
|
| `onCallEnd` | — | Connection closed |
|
|
261
262
|
| `statusChange` | `ConnectionStatus` | WebSocket-level status transition (internal) |
|
|
@@ -266,36 +267,36 @@ Extends `EventEmitter`.
|
|
|
266
267
|
|
|
267
268
|
### `useExotelAIAssist(params)` — Hook return values
|
|
268
269
|
|
|
269
|
-
| Field
|
|
270
|
-
|
|
|
271
|
-
| `isReady`
|
|
272
|
-
| `streamState`
|
|
273
|
-
| `suggestions`
|
|
274
|
-
| `transcripts`
|
|
275
|
-
| `sentiment`
|
|
276
|
-
| `lastError`
|
|
277
|
-
| `connect()`
|
|
278
|
-
| `disconnect()`
|
|
279
|
-
| `setParams()`
|
|
270
|
+
| Field | Type | Description |
|
|
271
|
+
| -------------------------- | ----------------------- | ---------------------------------------------------------------------------- |
|
|
272
|
+
| `isReady` | `boolean` | `true` after connected + server ack. Multi-tab safe. `false` on disconnect |
|
|
273
|
+
| `streamState` | `StreamState \| null` | Server stream state: `"connected"`, `"throttled"`, `"pending"`, `"disconnected"`, or `"connection_timeout"`. `null` until the first `stream_status` message |
|
|
274
|
+
| `suggestions` | `Suggestion[]` | AI suggestions, oldest first, capped at 50 |
|
|
275
|
+
| `transcripts` | `TranscriptLine[]` | Live transcript lines, ordered by start time |
|
|
276
|
+
| `sentiment` | `Sentiment \| null` | Latest sentiment reading |
|
|
277
|
+
| `lastError` | `Error \| null` | Most recent error |
|
|
278
|
+
| `connect()` | `() => void` | Manually open the connection |
|
|
279
|
+
| `disconnect()` | `() => void` | Manually close the connection |
|
|
280
|
+
| `setParams()` | `(patch) => void` | Merge params; reconnects if connection params change |
|
|
280
281
|
|
|
281
282
|
---
|
|
282
283
|
|
|
283
284
|
### TypeScript Types
|
|
284
285
|
|
|
285
286
|
```ts
|
|
286
|
-
type StreamState = "connected" | "throttled" | "disconnected";
|
|
287
|
+
type StreamState = "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout";
|
|
287
288
|
|
|
288
289
|
type ConnectionStatus = "idle" | "connecting" | "connected" | "disconnected" | "error";
|
|
289
290
|
|
|
290
291
|
interface Suggestion {
|
|
291
292
|
id: string;
|
|
292
|
-
|
|
293
|
+
value: string;
|
|
293
294
|
timestamp: number;
|
|
294
295
|
}
|
|
295
296
|
|
|
296
297
|
interface TranscriptLine {
|
|
297
298
|
id: string;
|
|
298
|
-
|
|
299
|
+
value: string;
|
|
299
300
|
startTime: number;
|
|
300
301
|
endTime: number;
|
|
301
302
|
isFinal: boolean;
|
|
@@ -330,15 +331,17 @@ wss://<wssBaseUrl>?[customParam1=value1&customParam2=value2&...]
|
|
|
330
331
|
"type": "stream_status",
|
|
331
332
|
"config": { /* bot config, populated on connected, null otherwise */ },
|
|
332
333
|
"events": [ /* accumulated events since last message, usually [] */ ],
|
|
333
|
-
"stream_state": "connected" | "throttled" | "disconnected"
|
|
334
|
+
"stream_state": "connected" | "throttled" | "pending" | "disconnected" | "connection_timeout"
|
|
334
335
|
}
|
|
335
336
|
```
|
|
336
337
|
|
|
337
|
-
| `stream_state`
|
|
338
|
-
|
|
|
339
|
-
| `connected`
|
|
340
|
-
| `throttled`
|
|
341
|
-
| `
|
|
338
|
+
| `stream_state` | Meaning |
|
|
339
|
+
| -------------------- | --------------------------------------------------------- |
|
|
340
|
+
| `connected` | Stream is active — suggestions, transcript, and sentiment flow normally |
|
|
341
|
+
| `throttled` | Capacity full — AI Assist cannot join this call; available on the next call |
|
|
342
|
+
| `pending` | Stream is pending — waiting for a definitive state |
|
|
343
|
+
| `disconnected` | Stream ended or dropped |
|
|
344
|
+
| `connection_timeout` | Connection timeout occurred |
|
|
342
345
|
|
|
343
346
|
### Reconnection
|
|
344
347
|
|
|
@@ -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,14 +1793,14 @@ 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
|
-
var _a, _b, _c
|
|
1798
|
+
var _a, _b, _c;
|
|
1780
1799
|
const first = (_a = msg.transcript_segments) === null || _a === void 0 ? void 0 : _a[0];
|
|
1781
1800
|
const last = (_b = msg.transcript_segments) === null || _b === void 0 ? void 0 : _b[msg.transcript_segments.length - 1];
|
|
1782
1801
|
return {
|
|
1783
1802
|
id: String(msg.sequence),
|
|
1784
|
-
value: (
|
|
1803
|
+
value: (_c = first === null || first === void 0 ? void 0 : first.text) !== null && _c !== void 0 ? _c : "",
|
|
1785
1804
|
startTime: (first === null || first === void 0 ? void 0 : first.start_timestamp) ? Date.parse(first.start_timestamp) : now,
|
|
1786
1805
|
endTime: (last === null || last === void 0 ? void 0 : last.end_timestamp) ? Date.parse(last.end_timestamp) : now,
|
|
1787
1806
|
isFinal: msg.transcript_segments.every(s => s.is_final)
|
|
@@ -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:
|
|
1795
|
-
value: event.value,
|
|
1796
|
-
timestamp: now
|
|
1813
|
+
id: String(event.value.sequence),
|
|
1814
|
+
value: event.value.text,
|
|
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,14 +21235,14 @@ 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
|
-
var _a, _b, _c
|
|
21240
|
+
var _a, _b, _c;
|
|
21198
21241
|
const first = (_a = msg.transcript_segments) === null || _a === void 0 ? void 0 : _a[0];
|
|
21199
21242
|
const last = (_b = msg.transcript_segments) === null || _b === void 0 ? void 0 : _b[msg.transcript_segments.length - 1];
|
|
21200
21243
|
return {
|
|
21201
21244
|
id: String(msg.sequence),
|
|
21202
|
-
value: (
|
|
21245
|
+
value: (_c = first === null || first === void 0 ? void 0 : first.text) !== null && _c !== void 0 ? _c : "",
|
|
21203
21246
|
startTime: (first === null || first === void 0 ? void 0 : first.start_timestamp) ? Date.parse(first.start_timestamp) : now,
|
|
21204
21247
|
endTime: (last === null || last === void 0 ? void 0 : last.end_timestamp) ? Date.parse(last.end_timestamp) : now,
|
|
21205
21248
|
isFinal: msg.transcript_segments.every(s => s.is_final)
|
|
@@ -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:
|
|
21213
|
-
value: event.value,
|
|
21214
|
-
timestamp: now
|
|
21255
|
+
id: String(event.value.sequence),
|
|
21256
|
+
value: event.value.text,
|
|
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;
|
|
@@ -21902,7 +22038,7 @@ function ExotelAIAssist(_a) {
|
|
|
21902
22038
|
if (streamState === "connection_timeout") {
|
|
21903
22039
|
return jsxRuntimeExports.jsx(EmptyState, {
|
|
21904
22040
|
title: "AI Assist is currently inactive",
|
|
21905
|
-
subtitle: "
|
|
22041
|
+
subtitle: "We were unable to establish a connection."
|
|
21906
22042
|
});
|
|
21907
22043
|
}
|
|
21908
22044
|
return null;
|
|
@@ -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",
|