polymorph-sdk 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +1 -1
- package/dist/index.d.ts +56 -19
- package/dist/index.js +6338 -5937
- package/package.json +1 -1
- package/src/ChatThread.tsx +42 -9
- package/src/IdentityForm.tsx +135 -0
- package/src/PolymorphWidget.tsx +68 -32
- package/src/RoomHandler.tsx +22 -2
- package/src/VoiceOverlay.tsx +60 -11
- package/src/WidgetPanel.tsx +103 -74
- package/src/__tests__/IdentityForm.test.tsx +146 -0
- package/src/__tests__/PolymorphWidget.test.tsx +173 -0
- package/src/__tests__/integration.test.ts +58 -0
- package/src/__tests__/usePolymorphSession.test.ts +422 -0
- package/src/index.ts +4 -1
- package/src/styles.module.css +203 -67
- package/src/types.ts +39 -16
- package/src/usePolymorphSession.ts +360 -61
package/src/styles.module.css
CHANGED
|
@@ -8,21 +8,19 @@
|
|
|
8
8
|
gap: 12px;
|
|
9
9
|
pointer-events: none;
|
|
10
10
|
}
|
|
11
|
-
|
|
12
11
|
.bottomRight {
|
|
13
12
|
top: 24px;
|
|
14
13
|
bottom: 24px;
|
|
15
14
|
right: 24px;
|
|
16
15
|
}
|
|
17
|
-
|
|
18
16
|
.bottomLeft {
|
|
19
17
|
top: 24px;
|
|
20
18
|
bottom: 24px;
|
|
21
19
|
left: 24px;
|
|
22
20
|
align-items: flex-start;
|
|
23
21
|
}
|
|
24
|
-
|
|
25
22
|
.fab {
|
|
23
|
+
position: relative;
|
|
26
24
|
width: 56px;
|
|
27
25
|
height: 56px;
|
|
28
26
|
border-radius: 28px;
|
|
@@ -38,15 +36,73 @@
|
|
|
38
36
|
color: white;
|
|
39
37
|
pointer-events: auto;
|
|
40
38
|
}
|
|
41
|
-
|
|
39
|
+
.fab svg {
|
|
40
|
+
transition: transform 200ms ease;
|
|
41
|
+
}
|
|
42
|
+
.fabOpen svg {
|
|
43
|
+
transform: rotate(90deg);
|
|
44
|
+
}
|
|
42
45
|
.fab:hover {
|
|
43
46
|
transform: scale(1.05);
|
|
44
47
|
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.2);
|
|
45
48
|
}
|
|
46
|
-
|
|
49
|
+
.fab:focus-visible {
|
|
50
|
+
outline: 2px solid white;
|
|
51
|
+
outline-offset: 2px;
|
|
52
|
+
}
|
|
53
|
+
.notificationDot {
|
|
54
|
+
position: absolute;
|
|
55
|
+
top: 2px;
|
|
56
|
+
right: 2px;
|
|
57
|
+
width: 12px;
|
|
58
|
+
height: 12px;
|
|
59
|
+
border-radius: 50%;
|
|
60
|
+
background: #ef4444;
|
|
61
|
+
border: 2px solid white;
|
|
62
|
+
animation: notificationPulse 2s ease-in-out infinite;
|
|
63
|
+
}
|
|
64
|
+
@keyframes notificationPulse {
|
|
65
|
+
0%,
|
|
66
|
+
100% {
|
|
67
|
+
transform: scale(1);
|
|
68
|
+
box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.4);
|
|
69
|
+
}
|
|
70
|
+
50% {
|
|
71
|
+
transform: scale(1.1);
|
|
72
|
+
box-shadow: 0 0 0 4px rgba(239, 68, 68, 0);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
.fabWiggle {
|
|
76
|
+
animation: fabWiggle 0.6s ease-in-out;
|
|
77
|
+
}
|
|
78
|
+
@keyframes fabWiggle {
|
|
79
|
+
0% {
|
|
80
|
+
transform: rotate(0deg);
|
|
81
|
+
}
|
|
82
|
+
15% {
|
|
83
|
+
transform: rotate(-12deg);
|
|
84
|
+
}
|
|
85
|
+
30% {
|
|
86
|
+
transform: rotate(10deg);
|
|
87
|
+
}
|
|
88
|
+
45% {
|
|
89
|
+
transform: rotate(-8deg);
|
|
90
|
+
}
|
|
91
|
+
60% {
|
|
92
|
+
transform: rotate(6deg);
|
|
93
|
+
}
|
|
94
|
+
75% {
|
|
95
|
+
transform: rotate(-2deg);
|
|
96
|
+
}
|
|
97
|
+
100% {
|
|
98
|
+
transform: rotate(0deg);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
47
101
|
.panel {
|
|
48
102
|
width: 380px;
|
|
49
|
-
|
|
103
|
+
height: 400px;
|
|
104
|
+
flex-shrink: 0;
|
|
105
|
+
min-height: 0;
|
|
50
106
|
display: flex;
|
|
51
107
|
flex-direction: column;
|
|
52
108
|
border-radius: 16px;
|
|
@@ -57,8 +113,16 @@
|
|
|
57
113
|
background: var(--mantine-color-body);
|
|
58
114
|
color: var(--mantine-color-text);
|
|
59
115
|
pointer-events: auto;
|
|
116
|
+
transition:
|
|
117
|
+
opacity 200ms ease,
|
|
118
|
+
transform 200ms ease;
|
|
119
|
+
transform-origin: bottom right;
|
|
120
|
+
}
|
|
121
|
+
.panelHidden {
|
|
122
|
+
opacity: 0;
|
|
123
|
+
transform: scale(0.95) translateY(8px);
|
|
124
|
+
pointer-events: none;
|
|
60
125
|
}
|
|
61
|
-
|
|
62
126
|
.header {
|
|
63
127
|
padding: 16px 16px 12px;
|
|
64
128
|
border-bottom: 1px solid var(--mantine-color-default-border);
|
|
@@ -66,7 +130,6 @@
|
|
|
66
130
|
justify-content: space-between;
|
|
67
131
|
align-items: flex-start;
|
|
68
132
|
}
|
|
69
|
-
|
|
70
133
|
.chatThread {
|
|
71
134
|
flex: 1;
|
|
72
135
|
overflow-y: auto;
|
|
@@ -74,10 +137,8 @@
|
|
|
74
137
|
display: flex;
|
|
75
138
|
flex-direction: column;
|
|
76
139
|
gap: 8px;
|
|
77
|
-
min-height:
|
|
78
|
-
max-height: 400px;
|
|
140
|
+
min-height: 0;
|
|
79
141
|
}
|
|
80
|
-
|
|
81
142
|
.messageBubble {
|
|
82
143
|
max-width: 80%;
|
|
83
144
|
padding: 8px 12px;
|
|
@@ -85,25 +146,38 @@
|
|
|
85
146
|
font-size: 14px;
|
|
86
147
|
line-height: 1.4;
|
|
87
148
|
word-wrap: break-word;
|
|
149
|
+
animation: messageAppear 200ms ease;
|
|
150
|
+
}
|
|
151
|
+
@keyframes messageAppear {
|
|
152
|
+
from {
|
|
153
|
+
opacity: 0;
|
|
154
|
+
transform: translateY(4px);
|
|
155
|
+
}
|
|
156
|
+
to {
|
|
157
|
+
opacity: 1;
|
|
158
|
+
transform: translateY(0);
|
|
159
|
+
}
|
|
88
160
|
}
|
|
89
|
-
|
|
90
161
|
.agentMessage {
|
|
91
162
|
align-self: flex-start;
|
|
92
163
|
background: var(--mantine-color-gray-light);
|
|
93
164
|
color: var(--mantine-color-text);
|
|
94
165
|
}
|
|
95
|
-
|
|
96
166
|
.userMessage {
|
|
97
167
|
align-self: flex-end;
|
|
98
168
|
color: white;
|
|
99
169
|
}
|
|
100
|
-
|
|
170
|
+
.senderLabel {
|
|
171
|
+
font-size: 11px;
|
|
172
|
+
font-weight: 500;
|
|
173
|
+
opacity: 0.7;
|
|
174
|
+
margin-bottom: 2px;
|
|
175
|
+
}
|
|
101
176
|
.voiceLabel {
|
|
102
177
|
font-size: 10px;
|
|
103
178
|
opacity: 0.6;
|
|
104
179
|
margin-top: 2px;
|
|
105
180
|
}
|
|
106
|
-
|
|
107
181
|
.voiceOverlay {
|
|
108
182
|
padding: 8px 16px;
|
|
109
183
|
display: flex;
|
|
@@ -113,21 +187,18 @@
|
|
|
113
187
|
color: var(--mantine-color-dimmed);
|
|
114
188
|
border-top: 1px solid var(--mantine-color-default-border);
|
|
115
189
|
}
|
|
116
|
-
|
|
117
190
|
.voiceBars {
|
|
118
191
|
display: flex;
|
|
119
192
|
align-items: center;
|
|
120
193
|
gap: 2px;
|
|
121
194
|
height: 16px;
|
|
122
195
|
}
|
|
123
|
-
|
|
124
196
|
.voiceBar {
|
|
125
197
|
width: 3px;
|
|
126
198
|
border-radius: 2px;
|
|
127
|
-
background: #
|
|
199
|
+
background: light-dark(#16a34a, #4ade80);
|
|
128
200
|
animation: voiceBar 1.2s ease-in-out infinite;
|
|
129
201
|
}
|
|
130
|
-
|
|
131
202
|
.voiceBar:nth-child(1) {
|
|
132
203
|
height: 6px;
|
|
133
204
|
animation-delay: 0s;
|
|
@@ -140,7 +211,6 @@
|
|
|
140
211
|
height: 8px;
|
|
141
212
|
animation-delay: 0.4s;
|
|
142
213
|
}
|
|
143
|
-
|
|
144
214
|
@keyframes voiceBar {
|
|
145
215
|
0%,
|
|
146
216
|
100% {
|
|
@@ -150,12 +220,15 @@
|
|
|
150
220
|
transform: scaleY(0.4);
|
|
151
221
|
}
|
|
152
222
|
}
|
|
153
|
-
|
|
154
|
-
.voiceToggle {
|
|
223
|
+
.toggleGroup {
|
|
155
224
|
margin-left: auto;
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
225
|
+
display: flex;
|
|
226
|
+
gap: 6px;
|
|
227
|
+
}
|
|
228
|
+
.voiceToggle {
|
|
229
|
+
width: 36px;
|
|
230
|
+
height: 36px;
|
|
231
|
+
border-radius: 18px;
|
|
159
232
|
border: 1px solid var(--mantine-color-default-border);
|
|
160
233
|
cursor: pointer;
|
|
161
234
|
display: flex;
|
|
@@ -165,45 +238,58 @@
|
|
|
165
238
|
color: var(--mantine-color-dimmed);
|
|
166
239
|
transition: all 150ms ease;
|
|
167
240
|
}
|
|
168
|
-
|
|
169
241
|
.voiceToggle:hover {
|
|
170
242
|
background: var(--mantine-color-gray-light-hover);
|
|
171
243
|
}
|
|
172
|
-
|
|
244
|
+
.voiceToggle:focus-visible {
|
|
245
|
+
outline: 2px solid var(--mantine-primary-color-filled);
|
|
246
|
+
outline-offset: 1px;
|
|
247
|
+
}
|
|
173
248
|
.voiceToggleActive {
|
|
174
249
|
background: light-dark(#dcfce7, #1a3a2a);
|
|
175
250
|
border-color: light-dark(#bbf7d0, #2a5a3a);
|
|
176
251
|
color: light-dark(#16a34a, #4ade80);
|
|
177
252
|
}
|
|
178
|
-
|
|
179
253
|
.voiceToggleActive:hover {
|
|
180
254
|
background: light-dark(#bbf7d0, #2a5a3a);
|
|
181
255
|
}
|
|
182
|
-
|
|
256
|
+
.screenShareToggleActive {
|
|
257
|
+
background: light-dark(#dbeafe, #1e3a5f);
|
|
258
|
+
border-color: light-dark(#93c5fd, #3b82f6);
|
|
259
|
+
color: light-dark(#2563eb, #60a5fa);
|
|
260
|
+
}
|
|
261
|
+
.screenShareToggleActive:hover {
|
|
262
|
+
background: light-dark(#bfdbfe, #2a4a6f);
|
|
263
|
+
}
|
|
183
264
|
.inputBar {
|
|
184
265
|
padding: 12px 16px;
|
|
185
266
|
border-top: 1px solid var(--mantine-color-default-border);
|
|
186
267
|
display: flex;
|
|
187
268
|
gap: 8px;
|
|
188
|
-
align-items:
|
|
269
|
+
align-items: flex-end;
|
|
189
270
|
}
|
|
190
|
-
|
|
191
271
|
.inputField {
|
|
192
272
|
flex: 1;
|
|
193
273
|
border: 1px solid var(--mantine-color-default-border);
|
|
194
274
|
border-radius: 8px;
|
|
195
275
|
padding: 8px 12px;
|
|
196
|
-
font-size:
|
|
276
|
+
font-size: 16px;
|
|
277
|
+
line-height: 1.4;
|
|
197
278
|
outline: none;
|
|
198
279
|
font-family: inherit;
|
|
199
280
|
background: var(--mantine-color-body);
|
|
200
281
|
color: var(--mantine-color-text);
|
|
282
|
+
resize: none;
|
|
283
|
+
overflow-y: auto;
|
|
284
|
+
max-height: 120px;
|
|
201
285
|
}
|
|
202
|
-
|
|
203
286
|
.inputField:focus {
|
|
204
287
|
border-color: var(--mantine-color-dimmed);
|
|
205
288
|
}
|
|
206
|
-
|
|
289
|
+
.inputField:focus-visible {
|
|
290
|
+
outline: 2px solid var(--mantine-primary-color-filled);
|
|
291
|
+
outline-offset: -1px;
|
|
292
|
+
}
|
|
207
293
|
.iconButton {
|
|
208
294
|
width: 36px;
|
|
209
295
|
height: 36px;
|
|
@@ -218,62 +304,39 @@
|
|
|
218
304
|
transition:
|
|
219
305
|
background 150ms ease,
|
|
220
306
|
color 150ms ease;
|
|
307
|
+
flex-shrink: 0;
|
|
221
308
|
}
|
|
222
|
-
|
|
223
309
|
.iconButton:hover {
|
|
224
310
|
background: var(--mantine-color-gray-light);
|
|
225
311
|
}
|
|
226
|
-
|
|
312
|
+
.iconButton:focus-visible {
|
|
313
|
+
outline: 2px solid var(--mantine-primary-color-filled);
|
|
314
|
+
outline-offset: 1px;
|
|
315
|
+
}
|
|
227
316
|
.iconButton:disabled {
|
|
228
317
|
opacity: 0.4;
|
|
229
318
|
cursor: default;
|
|
230
319
|
}
|
|
231
|
-
|
|
232
320
|
.iconButtonActive {
|
|
233
|
-
color: #
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
.connectButton {
|
|
237
|
-
margin: 16px;
|
|
238
|
-
padding: 10px 20px;
|
|
239
|
-
border-radius: 8px;
|
|
240
|
-
border: none;
|
|
241
|
-
cursor: pointer;
|
|
242
|
-
font-size: 14px;
|
|
243
|
-
font-weight: 500;
|
|
244
|
-
color: white;
|
|
245
|
-
transition: opacity 150ms ease;
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
.connectButton:hover {
|
|
249
|
-
opacity: 0.9;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
.connectButton:disabled {
|
|
253
|
-
opacity: 0.5;
|
|
254
|
-
cursor: default;
|
|
321
|
+
color: light-dark(#16a34a, #4ade80);
|
|
255
322
|
}
|
|
256
|
-
|
|
257
323
|
.statusBadge {
|
|
258
324
|
font-size: 11px;
|
|
259
325
|
padding: 2px 8px;
|
|
260
326
|
border-radius: 10px;
|
|
261
327
|
font-weight: 500;
|
|
262
328
|
}
|
|
263
|
-
|
|
264
329
|
.errorText {
|
|
265
|
-
color: #dc2626;
|
|
330
|
+
color: light-dark(#dc2626, #f87171);
|
|
266
331
|
font-size: 13px;
|
|
267
332
|
padding: 0 16px;
|
|
268
333
|
}
|
|
269
|
-
|
|
270
334
|
.thinkingDots {
|
|
271
335
|
display: flex;
|
|
272
336
|
gap: 4px;
|
|
273
337
|
align-items: center;
|
|
274
338
|
height: 20px;
|
|
275
339
|
}
|
|
276
|
-
|
|
277
340
|
.thinkingDots span {
|
|
278
341
|
width: 6px;
|
|
279
342
|
height: 6px;
|
|
@@ -281,15 +344,12 @@
|
|
|
281
344
|
background: var(--mantine-color-dimmed);
|
|
282
345
|
animation: thinkingDot 1.4s ease-in-out infinite;
|
|
283
346
|
}
|
|
284
|
-
|
|
285
347
|
.thinkingDots span:nth-child(2) {
|
|
286
348
|
animation-delay: 0.2s;
|
|
287
349
|
}
|
|
288
|
-
|
|
289
350
|
.thinkingDots span:nth-child(3) {
|
|
290
351
|
animation-delay: 0.4s;
|
|
291
352
|
}
|
|
292
|
-
|
|
293
353
|
@keyframes thinkingDot {
|
|
294
354
|
0%,
|
|
295
355
|
80%,
|
|
@@ -302,3 +362,79 @@
|
|
|
302
362
|
transform: scale(1);
|
|
303
363
|
}
|
|
304
364
|
}
|
|
365
|
+
.identityForm {
|
|
366
|
+
padding: 20px 16px;
|
|
367
|
+
display: flex;
|
|
368
|
+
flex-direction: column;
|
|
369
|
+
gap: 14px;
|
|
370
|
+
flex: 1;
|
|
371
|
+
overflow-y: auto;
|
|
372
|
+
}
|
|
373
|
+
.formField {
|
|
374
|
+
display: flex;
|
|
375
|
+
flex-direction: column;
|
|
376
|
+
gap: 4px;
|
|
377
|
+
}
|
|
378
|
+
.formLabel {
|
|
379
|
+
font-size: 13px;
|
|
380
|
+
font-weight: 500;
|
|
381
|
+
color: var(--mantine-color-text);
|
|
382
|
+
}
|
|
383
|
+
.formInput {
|
|
384
|
+
border: 1px solid var(--mantine-color-default-border);
|
|
385
|
+
border-radius: 8px;
|
|
386
|
+
padding: 8px 12px;
|
|
387
|
+
font-size: 16px;
|
|
388
|
+
line-height: 1.4;
|
|
389
|
+
outline: none;
|
|
390
|
+
font-family: inherit;
|
|
391
|
+
background: var(--mantine-color-body);
|
|
392
|
+
color: var(--mantine-color-text);
|
|
393
|
+
}
|
|
394
|
+
.formInput:focus {
|
|
395
|
+
border-color: var(--mantine-color-dimmed);
|
|
396
|
+
}
|
|
397
|
+
.formInput:focus-visible {
|
|
398
|
+
outline: 2px solid var(--mantine-primary-color-filled);
|
|
399
|
+
outline-offset: -1px;
|
|
400
|
+
}
|
|
401
|
+
.formError {
|
|
402
|
+
font-size: 12px;
|
|
403
|
+
color: light-dark(#dc2626, #f87171);
|
|
404
|
+
}
|
|
405
|
+
.formSubmitButton {
|
|
406
|
+
margin-top: 4px;
|
|
407
|
+
padding: 10px 16px;
|
|
408
|
+
border: none;
|
|
409
|
+
border-radius: 8px;
|
|
410
|
+
font-size: 14px;
|
|
411
|
+
font-weight: 500;
|
|
412
|
+
color: white;
|
|
413
|
+
cursor: pointer;
|
|
414
|
+
transition: opacity 150ms ease;
|
|
415
|
+
}
|
|
416
|
+
.formSubmitButton:hover {
|
|
417
|
+
opacity: 0.9;
|
|
418
|
+
}
|
|
419
|
+
.formSubmitButton:focus-visible {
|
|
420
|
+
outline: 2px solid white;
|
|
421
|
+
outline-offset: 2px;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/* Mobile: full-width panel on small screens */
|
|
425
|
+
@media (max-width: 420px) {
|
|
426
|
+
.bottomRight,
|
|
427
|
+
.bottomLeft {
|
|
428
|
+
top: 0;
|
|
429
|
+
bottom: 0;
|
|
430
|
+
left: 0;
|
|
431
|
+
right: 0;
|
|
432
|
+
padding: 12px;
|
|
433
|
+
}
|
|
434
|
+
.panel {
|
|
435
|
+
width: 100%;
|
|
436
|
+
height: auto;
|
|
437
|
+
flex: 1;
|
|
438
|
+
border-radius: 12px;
|
|
439
|
+
}
|
|
440
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,28 +1,49 @@
|
|
|
1
1
|
export interface WidgetConfig {
|
|
2
|
-
|
|
2
|
+
/** Backend API URL. Defaults to https://api.usepolymorph.com in production, http://localhost:8080 on localhost. */
|
|
3
|
+
apiBaseUrl?: string;
|
|
3
4
|
apiKey?: string;
|
|
5
|
+
/** Server-side widget config ID. When omitted, the org's default config is used. */
|
|
6
|
+
configId?: string;
|
|
4
7
|
/** LiveKit dispatched agent name (default: "custom-voice-agent"). */
|
|
5
8
|
agentName?: string;
|
|
9
|
+
/** Inline metadata (only used when no server-side config is resolved). */
|
|
6
10
|
metadata?: Record<string, string | string[]>;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
/** Enable voice call (default: true). When false, widget is chat-only. */
|
|
10
|
-
enableVoice?: boolean;
|
|
11
|
+
/** Pre-filled user identity. When provided, the identity form is skipped. */
|
|
12
|
+
user?: WidgetUser;
|
|
11
13
|
/** Extra options passed to fetch (e.g. { credentials: "include" }) */
|
|
12
14
|
fetchOptions?: RequestInit;
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
+
/** Called when a session starts with room info for constructing join URLs. */
|
|
16
|
+
onSessionStart?: (info: { roomId: string; joinToken: string }) => void;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
|
-
export interface
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
export interface WidgetUser {
|
|
20
|
+
/** Display name (e.g. "Jane Smith") */
|
|
21
|
+
name?: string;
|
|
22
|
+
/** Email address */
|
|
23
|
+
email?: string;
|
|
24
|
+
/** Phone number */
|
|
25
|
+
phone?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Resolved from the backend via /widget-configs/resolve. */
|
|
29
|
+
export interface ResolvedWidgetConfig {
|
|
30
|
+
id: string;
|
|
31
|
+
title: string;
|
|
32
|
+
subtitle: string;
|
|
33
|
+
primaryColor: string;
|
|
34
|
+
position: "bottom-right" | "bottom-left";
|
|
35
|
+
darkMode: boolean;
|
|
36
|
+
enableVoice: boolean;
|
|
37
|
+
greeting: string;
|
|
38
|
+
collectEmail: FieldRequirement;
|
|
39
|
+
collectPhone: FieldRequirement;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type FieldRequirement = "required" | "optional" | "hidden";
|
|
43
|
+
|
|
44
|
+
export interface IdentityCollection {
|
|
45
|
+
collectEmail: FieldRequirement;
|
|
46
|
+
collectPhone: FieldRequirement;
|
|
26
47
|
}
|
|
27
48
|
|
|
28
49
|
export interface ChatMessage {
|
|
@@ -31,6 +52,8 @@ export interface ChatMessage {
|
|
|
31
52
|
text: string;
|
|
32
53
|
source: "chat" | "voice";
|
|
33
54
|
timestamp: number;
|
|
55
|
+
senderName?: string;
|
|
56
|
+
senderType?: "human";
|
|
34
57
|
}
|
|
35
58
|
|
|
36
59
|
export type SessionStatus = "idle" | "connecting" | "connected" | "error";
|