@bytexbyte/nxtlinq-ai-agent-sdk 1.6.21 → 1.6.23
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/context/ChatBotContext.d.ts.map +1 -1
- package/dist/components/context/ChatBotContext.js +252 -49
- package/dist/components/types/ChatBotTypes.d.ts +3 -0
- package/dist/components/types/ChatBotTypes.d.ts.map +1 -1
- package/dist/components/ui/MessageList.d.ts.map +1 -1
- package/dist/components/ui/MessageList.js +23 -2
- package/dist/components/ui/ModelSelector.d.ts.map +1 -1
- package/dist/components/ui/ModelSelector.js +15 -5
- package/package.json +1 -1
- package/umd/nxtlinq-ai-agent.umd.js +158 -138
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../../src/components/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAM/B,eAAO,MAAM,UAAU,0BAMtB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,
|
|
1
|
+
{"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../../src/components/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAU/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAM/B,eAAO,MAAM,UAAU,0BAMtB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAk+ElD,CAAC"}
|
|
@@ -79,7 +79,11 @@ isStopRecordingOnSend = false, }) => {
|
|
|
79
79
|
// Speech related refs
|
|
80
80
|
const audioCtxRef = React.useRef(null);
|
|
81
81
|
const audioSourceRef = React.useRef(null);
|
|
82
|
+
const audioElementRef = React.useRef(null);
|
|
82
83
|
const speechingRef = React.useRef(false);
|
|
84
|
+
const [isTtsProcessing, setIsTtsProcessing] = React.useState(false);
|
|
85
|
+
const [requiresGesture, setRequiresGesture] = React.useState(false);
|
|
86
|
+
const pendingTtsRef = React.useRef(null);
|
|
83
87
|
// Use refs to get latest state values in hasPermission function
|
|
84
88
|
const hitAddressRef = React.useRef(hitAddress);
|
|
85
89
|
const aitRef = React.useRef(ait);
|
|
@@ -139,6 +143,183 @@ isStopRecordingOnSend = false, }) => {
|
|
|
139
143
|
console.error('Error clearing expired token:', error);
|
|
140
144
|
}
|
|
141
145
|
}, []);
|
|
146
|
+
// Internal: Play text-to-speech with retry mechanism
|
|
147
|
+
const playTextToSpeechWithRetry = React.useCallback(async (text, messageIndex, attempt = 0) => {
|
|
148
|
+
if (attempt > 2) {
|
|
149
|
+
console.error('TTS playback failed after retries');
|
|
150
|
+
setIsTtsProcessing(false);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const bufferData = await textToBuffer(text, getDefaultSpeechToken);
|
|
154
|
+
if (!bufferData)
|
|
155
|
+
throw new Error('Failed to get audio buffer');
|
|
156
|
+
const isMobileDevice = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
|
|
157
|
+
if (isMobileDevice) {
|
|
158
|
+
const blob = new Blob([bufferData], { type: 'audio/wav' });
|
|
159
|
+
const audioUrl = URL.createObjectURL(blob);
|
|
160
|
+
const audio = new Audio(audioUrl);
|
|
161
|
+
if ('setSinkId' in HTMLMediaElement.prototype) {
|
|
162
|
+
try {
|
|
163
|
+
const devices = await navigator.mediaDevices?.enumerateDevices?.();
|
|
164
|
+
const speakerDevice = devices?.find((d) => d.kind === 'audiooutput' && d.label.toLowerCase().includes('speaker'));
|
|
165
|
+
if (speakerDevice)
|
|
166
|
+
await audio.setSinkId(speakerDevice.deviceId);
|
|
167
|
+
else
|
|
168
|
+
await audio.setSinkId('default');
|
|
169
|
+
}
|
|
170
|
+
catch (err) {
|
|
171
|
+
console.debug('Could not set audio sink:', err);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
audio.volume = 1.0;
|
|
175
|
+
audioElementRef.current = audio;
|
|
176
|
+
speechingRef.current = true;
|
|
177
|
+
if (messageIndex !== undefined)
|
|
178
|
+
setSpeechingIndex(messageIndex);
|
|
179
|
+
// Track if onplay has been called to avoid clearing state multiple times
|
|
180
|
+
let playStarted = false;
|
|
181
|
+
const clearProcessingState = () => {
|
|
182
|
+
if (!playStarted) {
|
|
183
|
+
playStarted = true;
|
|
184
|
+
setIsTtsProcessing(false);
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
await new Promise(async (resolve, reject) => {
|
|
188
|
+
audio.onended = () => {
|
|
189
|
+
speechingRef.current = false;
|
|
190
|
+
setSpeechingIndex(undefined);
|
|
191
|
+
URL.revokeObjectURL(audioUrl);
|
|
192
|
+
audioElementRef.current = null;
|
|
193
|
+
resolve();
|
|
194
|
+
};
|
|
195
|
+
audio.onerror = (error) => {
|
|
196
|
+
speechingRef.current = false;
|
|
197
|
+
setSpeechingIndex(undefined);
|
|
198
|
+
URL.revokeObjectURL(audioUrl);
|
|
199
|
+
audioElementRef.current = null;
|
|
200
|
+
clearProcessingState();
|
|
201
|
+
reject(error);
|
|
202
|
+
};
|
|
203
|
+
audio.onplay = () => {
|
|
204
|
+
// Clear processing state when audio actually starts playing
|
|
205
|
+
setRequiresGesture(false);
|
|
206
|
+
clearProcessingState();
|
|
207
|
+
};
|
|
208
|
+
// Handle play() promise - some mobile browsers require user interaction
|
|
209
|
+
audio.play().then(() => {
|
|
210
|
+
// Play promise resolved, but wait for onplay event to confirm actual playback
|
|
211
|
+
// Don't clear requiresGesture here - let onplay handle it
|
|
212
|
+
setTimeout(clearProcessingState, 100);
|
|
213
|
+
}).catch((playError) => {
|
|
214
|
+
// Mark requires gesture and store pending text
|
|
215
|
+
setRequiresGesture(true);
|
|
216
|
+
pendingTtsRef.current = text;
|
|
217
|
+
// Fallback: try WebAudio (AudioContext) playback on mobile
|
|
218
|
+
try {
|
|
219
|
+
if (audioCtxRef.current === null) {
|
|
220
|
+
audioCtxRef.current = new AudioContext();
|
|
221
|
+
}
|
|
222
|
+
audioSourceRef.current = audioCtxRef.current.createBufferSource();
|
|
223
|
+
if (!audioSourceRef.current) {
|
|
224
|
+
throw playError;
|
|
225
|
+
}
|
|
226
|
+
audioCtxRef.current.decodeAudioData(bufferData.slice(0), (decodedBuffer) => {
|
|
227
|
+
if (!audioSourceRef.current) {
|
|
228
|
+
reject(playError);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
audioSourceRef.current.buffer = decodedBuffer;
|
|
232
|
+
audioSourceRef.current.connect(audioCtxRef.current.destination);
|
|
233
|
+
speechingRef.current = true;
|
|
234
|
+
clearProcessingState();
|
|
235
|
+
audioSourceRef.current.onended = () => {
|
|
236
|
+
speechingRef.current = false;
|
|
237
|
+
setSpeechingIndex(undefined);
|
|
238
|
+
audioSourceRef.current = null;
|
|
239
|
+
// cleanup audio element blob URL
|
|
240
|
+
URL.revokeObjectURL(audioUrl);
|
|
241
|
+
audioElementRef.current = null;
|
|
242
|
+
resolve();
|
|
243
|
+
};
|
|
244
|
+
try {
|
|
245
|
+
// Ensure AudioContext is running before starting
|
|
246
|
+
if (audioCtxRef.current?.state === 'suspended') {
|
|
247
|
+
audioCtxRef.current.resume().then(() => {
|
|
248
|
+
audioSourceRef.current?.start();
|
|
249
|
+
// Only clear requiresGesture after successfully starting
|
|
250
|
+
setRequiresGesture(false);
|
|
251
|
+
}).catch((resumeErr) => {
|
|
252
|
+
// AudioContext resume failed, keep requiresGesture true
|
|
253
|
+
reject(resumeErr);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
audioSourceRef.current.start();
|
|
258
|
+
// Only clear requiresGesture after successfully starting
|
|
259
|
+
setRequiresGesture(false);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch (e) {
|
|
263
|
+
// start() failed, keep requiresGesture true
|
|
264
|
+
reject(e);
|
|
265
|
+
}
|
|
266
|
+
}, (decodeErr) => {
|
|
267
|
+
// If decode also fails, give up
|
|
268
|
+
speechingRef.current = false;
|
|
269
|
+
setSpeechingIndex(undefined);
|
|
270
|
+
URL.revokeObjectURL(audioUrl);
|
|
271
|
+
audioElementRef.current = null;
|
|
272
|
+
clearProcessingState();
|
|
273
|
+
reject(decodeErr);
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
catch (fallbackErr) {
|
|
277
|
+
// Play failed (e.g., user interaction required)
|
|
278
|
+
speechingRef.current = false;
|
|
279
|
+
setSpeechingIndex(undefined);
|
|
280
|
+
URL.revokeObjectURL(audioUrl);
|
|
281
|
+
audioElementRef.current = null;
|
|
282
|
+
clearProcessingState();
|
|
283
|
+
reject(fallbackErr);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (audioCtxRef.current === null) {
|
|
290
|
+
audioCtxRef.current = new AudioContext();
|
|
291
|
+
}
|
|
292
|
+
audioSourceRef.current = audioCtxRef.current.createBufferSource();
|
|
293
|
+
if (!audioSourceRef.current)
|
|
294
|
+
return;
|
|
295
|
+
const buffer = await new Promise((resolve, reject) => {
|
|
296
|
+
if (audioCtxRef.current !== null && bufferData) {
|
|
297
|
+
audioCtxRef.current.decodeAudioData(bufferData, (decodedBuffer) => resolve(decodedBuffer), (error) => reject(error));
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
reject(new Error('Audio context or buffer data is missing'));
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
if (!audioSourceRef.current.buffer) {
|
|
304
|
+
audioSourceRef.current.buffer = buffer;
|
|
305
|
+
audioSourceRef.current.connect(audioCtxRef.current.destination);
|
|
306
|
+
speechingRef.current = true;
|
|
307
|
+
if (messageIndex !== undefined)
|
|
308
|
+
setSpeechingIndex(messageIndex);
|
|
309
|
+
// Clear processing state when audio starts playing
|
|
310
|
+
setRequiresGesture(false);
|
|
311
|
+
setIsTtsProcessing(false);
|
|
312
|
+
await new Promise((resolve) => {
|
|
313
|
+
audioSourceRef.current.onended = () => {
|
|
314
|
+
speechingRef.current = false;
|
|
315
|
+
setSpeechingIndex(undefined);
|
|
316
|
+
audioSourceRef.current = null;
|
|
317
|
+
resolve();
|
|
318
|
+
};
|
|
319
|
+
audioSourceRef.current.start();
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
}, []);
|
|
142
323
|
// Update refs when state changes
|
|
143
324
|
React.useEffect(() => {
|
|
144
325
|
hitAddressRef.current = hitAddress;
|
|
@@ -1393,11 +1574,9 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1393
1574
|
window.location.href = redirectUrl;
|
|
1394
1575
|
}, 100);
|
|
1395
1576
|
}
|
|
1396
|
-
//
|
|
1577
|
+
// Play text-to-speech for AI response if enabled
|
|
1397
1578
|
if (botResponse && botResponse.role === 'assistant' && textToSpeechEnabled) {
|
|
1398
|
-
// Use setTimeout to ensure the message is added to state first
|
|
1399
1579
|
setTimeout(() => {
|
|
1400
|
-
// Play speech without needing exact index (index is mainly for UI indication)
|
|
1401
1580
|
playTextToSpeech(botResponse.content).catch(error => {
|
|
1402
1581
|
console.error('Failed to play text-to-speech:', error);
|
|
1403
1582
|
});
|
|
@@ -1467,6 +1646,8 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1467
1646
|
return;
|
|
1468
1647
|
if (!textInputRef.current.value.trim() || isLoading)
|
|
1469
1648
|
return;
|
|
1649
|
+
// Stop current speech playback when user sends new message
|
|
1650
|
+
stopTextToSpeechAndReset();
|
|
1470
1651
|
// Show loading message if AIT is still loading
|
|
1471
1652
|
if (isAITLoading) {
|
|
1472
1653
|
const loadingMessage = {
|
|
@@ -1503,64 +1684,62 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1503
1684
|
setMessages(prev => [...prev, errorMessage]);
|
|
1504
1685
|
}
|
|
1505
1686
|
};
|
|
1506
|
-
// Stop text-to-speech
|
|
1687
|
+
// Stop text-to-speech (does not clear queue)
|
|
1507
1688
|
const stopTextToSpeech = React.useCallback(() => {
|
|
1508
|
-
if (speechingRef.current
|
|
1689
|
+
if (speechingRef.current) {
|
|
1690
|
+
// Stop AudioContext source if exists
|
|
1691
|
+
if (audioSourceRef.current) {
|
|
1692
|
+
audioSourceRef.current.stop();
|
|
1693
|
+
audioSourceRef.current.disconnect();
|
|
1694
|
+
audioSourceRef.current = null;
|
|
1695
|
+
}
|
|
1696
|
+
// Stop HTML Audio element if exists
|
|
1697
|
+
if (audioElementRef.current) {
|
|
1698
|
+
audioElementRef.current.pause();
|
|
1699
|
+
audioElementRef.current.currentTime = 0;
|
|
1700
|
+
if (audioElementRef.current.src.startsWith('blob:')) {
|
|
1701
|
+
URL.revokeObjectURL(audioElementRef.current.src);
|
|
1702
|
+
}
|
|
1703
|
+
audioElementRef.current = null;
|
|
1704
|
+
}
|
|
1509
1705
|
speechingRef.current = false;
|
|
1510
|
-
audioSourceRef.current.stop();
|
|
1511
|
-
audioSourceRef.current.disconnect();
|
|
1512
|
-
audioSourceRef.current = null;
|
|
1513
1706
|
}
|
|
1514
1707
|
setSpeechingIndex(undefined);
|
|
1515
1708
|
}, []);
|
|
1516
|
-
//
|
|
1709
|
+
// Stop text-to-speech (used when user sends new message)
|
|
1710
|
+
const stopTextToSpeechAndReset = React.useCallback(() => {
|
|
1711
|
+
stopTextToSpeech();
|
|
1712
|
+
setRequiresGesture(false);
|
|
1713
|
+
setIsTtsProcessing(false);
|
|
1714
|
+
pendingTtsRef.current = null;
|
|
1715
|
+
}, [stopTextToSpeech]);
|
|
1716
|
+
// Play text-to-speech (simplified, no queue)
|
|
1517
1717
|
const playTextToSpeech = React.useCallback(async (text, messageIndex) => {
|
|
1518
|
-
if (!textToSpeechEnabled || !text.trim())
|
|
1718
|
+
if (!textToSpeechEnabled || !text.trim())
|
|
1519
1719
|
return;
|
|
1520
|
-
}
|
|
1521
1720
|
// Stop any ongoing speech
|
|
1522
1721
|
stopTextToSpeech();
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
}
|
|
1538
|
-
else {
|
|
1539
|
-
reject(new Error('Audio context or buffer data is missing'));
|
|
1540
|
-
}
|
|
1541
|
-
});
|
|
1542
|
-
if (audioSourceRef.current && !audioSourceRef.current.buffer) {
|
|
1543
|
-
audioSourceRef.current.buffer = buffer;
|
|
1544
|
-
audioSourceRef.current.connect(audioCtxRef.current.destination);
|
|
1545
|
-
speechingRef.current = true;
|
|
1546
|
-
if (messageIndex !== undefined) {
|
|
1547
|
-
setSpeechingIndex(messageIndex);
|
|
1548
|
-
}
|
|
1549
|
-
audioSourceRef.current.start();
|
|
1550
|
-
audioSourceRef.current.onended = () => {
|
|
1551
|
-
speechingRef.current = false;
|
|
1552
|
-
setSpeechingIndex(undefined);
|
|
1553
|
-
audioSourceRef.current = null;
|
|
1554
|
-
};
|
|
1722
|
+
// Show processing indicator
|
|
1723
|
+
setIsTtsProcessing(true);
|
|
1724
|
+
// Retry up to 2 times (3 attempts total)
|
|
1725
|
+
let lastError;
|
|
1726
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
1727
|
+
try {
|
|
1728
|
+
await playTextToSpeechWithRetry(text, messageIndex, attempt);
|
|
1729
|
+
return; // Success, exit
|
|
1730
|
+
}
|
|
1731
|
+
catch (err) {
|
|
1732
|
+
lastError = err;
|
|
1733
|
+
if (attempt < 2) {
|
|
1734
|
+
// Continue to next attempt
|
|
1735
|
+
continue;
|
|
1555
1736
|
}
|
|
1556
1737
|
}
|
|
1557
1738
|
}
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
}
|
|
1563
|
-
}, [textToSpeechEnabled, stopTextToSpeech]);
|
|
1739
|
+
// All attempts failed
|
|
1740
|
+
console.error('TTS playback failed after retries:', lastError);
|
|
1741
|
+
setIsTtsProcessing(false);
|
|
1742
|
+
}, [textToSpeechEnabled, stopTextToSpeech, playTextToSpeechWithRetry]);
|
|
1564
1743
|
// Handle preset message
|
|
1565
1744
|
const handlePresetMessage = (message) => {
|
|
1566
1745
|
if (message.autoSend) {
|
|
@@ -2052,6 +2231,8 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2052
2231
|
// Speech related state
|
|
2053
2232
|
textToSpeechEnabled,
|
|
2054
2233
|
speechingIndex,
|
|
2234
|
+
isTtsProcessing,
|
|
2235
|
+
requiresGesture,
|
|
2055
2236
|
// AI Model related state
|
|
2056
2237
|
availableModels: effectiveAvailableModels,
|
|
2057
2238
|
selectedModelIndex,
|
|
@@ -2095,6 +2276,28 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2095
2276
|
// Speech related functions
|
|
2096
2277
|
playTextToSpeech,
|
|
2097
2278
|
stopTextToSpeech,
|
|
2279
|
+
retryTtsWithGesture: async () => {
|
|
2280
|
+
try {
|
|
2281
|
+
setRequiresGesture(false);
|
|
2282
|
+
// Try to resume audio context
|
|
2283
|
+
if (audioCtxRef.current) {
|
|
2284
|
+
try {
|
|
2285
|
+
await audioCtxRef.current.resume();
|
|
2286
|
+
}
|
|
2287
|
+
catch { }
|
|
2288
|
+
}
|
|
2289
|
+
const pending = pendingTtsRef.current;
|
|
2290
|
+
if (pending && textToSpeechEnabled) {
|
|
2291
|
+
setIsTtsProcessing(true);
|
|
2292
|
+
await playTextToSpeech(pending);
|
|
2293
|
+
pendingTtsRef.current = null;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
catch (err) {
|
|
2297
|
+
console.error('Retry TTS with gesture failed:', err);
|
|
2298
|
+
setIsTtsProcessing(false);
|
|
2299
|
+
}
|
|
2300
|
+
},
|
|
2098
2301
|
// Additional properties for PermissionForm
|
|
2099
2302
|
onSave: savePermissions,
|
|
2100
2303
|
onConnectWallet: () => connectWallet(false),
|
|
@@ -88,6 +88,8 @@ export interface ChatBotContextType {
|
|
|
88
88
|
autoSendEnabled: boolean;
|
|
89
89
|
textToSpeechEnabled: boolean;
|
|
90
90
|
speechingIndex: number | undefined;
|
|
91
|
+
isTtsProcessing: boolean;
|
|
92
|
+
requiresGesture?: boolean;
|
|
91
93
|
availableModels: AIModel[];
|
|
92
94
|
selectedModelIndex: number;
|
|
93
95
|
showModelSelector: boolean;
|
|
@@ -124,6 +126,7 @@ export interface ChatBotContextType {
|
|
|
124
126
|
getCurrentModel: () => AIModel;
|
|
125
127
|
playTextToSpeech: (text: string) => Promise<void>;
|
|
126
128
|
stopTextToSpeech: () => void;
|
|
129
|
+
retryTtsWithGesture?: () => Promise<void>;
|
|
127
130
|
onSave: (newPermissions?: string[]) => Promise<void>;
|
|
128
131
|
onConnectWallet: () => Promise<string | false | undefined>;
|
|
129
132
|
onSignIn: () => Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatBotTypes.d.ts","sourceRoot":"","sources":["../../../src/components/types/ChatBotTypes.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ChatBotTypes.d.ts","sourceRoot":"","sources":["../../../src/components/types/ChatBotTypes.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/ui/MessageList.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAoB/B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/components/ui/MessageList.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAoB/B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EA4K/B,CAAC"}
|
|
@@ -6,7 +6,7 @@ import { convertUrlsToLinks } from '../../core/utils/urlUtils';
|
|
|
6
6
|
import { useChatBot } from '../context/ChatBotContext';
|
|
7
7
|
import { messageListContainer, messageBubble, userMessage, messageContent, userMessageContent, retryMessageContent, chatbotButton, connectedButton, loadingIndicator, modelIndicator, modelBadge, modelDot } from './styles/isolatedStyles';
|
|
8
8
|
export const MessageList = () => {
|
|
9
|
-
const { messages, isLoading, connectWallet, signInWallet, hitAddress, isAutoConnecting, isNeedSignInWithWallet, enableAIT, isAITLoading, isAITEnabling, sendMessage, permissions, availableModels } = useChatBot();
|
|
9
|
+
const { messages, isLoading, isTtsProcessing, requiresGesture, retryTtsWithGesture, connectWallet, signInWallet, hitAddress, isAutoConnecting, isNeedSignInWithWallet, enableAIT, isAITLoading, isAITEnabling, sendMessage, permissions, availableModels, serviceId } = useChatBot();
|
|
10
10
|
const messagesEndRef = React.useRef(null);
|
|
11
11
|
const scrollToBottom = () => {
|
|
12
12
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
|
|
@@ -47,6 +47,11 @@ export const MessageList = () => {
|
|
|
47
47
|
const getModelDisplayName = (modelValue) => {
|
|
48
48
|
if (!modelValue)
|
|
49
49
|
return '';
|
|
50
|
+
// Special case: show "Adi" for specific serviceId
|
|
51
|
+
const targetServiceId = 'e48fc2b9-a7d1-49e3-85cb-9d621a0bf774';
|
|
52
|
+
if (serviceId && serviceId.trim() === targetServiceId) {
|
|
53
|
+
return 'Adi';
|
|
54
|
+
}
|
|
50
55
|
// Find model in the list returned by API
|
|
51
56
|
const model = availableModels.find(m => m.value === modelValue);
|
|
52
57
|
// Use label from API or fallback to value
|
|
@@ -75,5 +80,21 @@ export const MessageList = () => {
|
|
|
75
80
|
message.button === 'enableAIT' ?
|
|
76
81
|
((isAITLoading || isAITEnabling) ? 'Enabling...' :
|
|
77
82
|
(message.metadata?.requiredPermission && permissions.includes(message.metadata.requiredPermission)) ? 'AIT Enabled' : 'Enable AIT Permissions') :
|
|
78
|
-
message.button }) }))] }), message.role === 'assistant' && message.metadata?.model && (
|
|
83
|
+
message.button }) }))] }), message.role === 'assistant' && message.metadata?.model && (_jsxs("div", { css: css `
|
|
84
|
+
${modelIndicator}
|
|
85
|
+
gap: 8px !important;
|
|
86
|
+
`, children: [_jsxs("div", { css: modelBadge, children: [_jsx("span", { css: modelDot }), getModelDisplayName(message.metadata.model)] }), (isTtsProcessing || requiresGesture) && !isLoading && message.id === messages[messages.length - 1]?.id && (_jsxs("div", { css: css `
|
|
87
|
+
display: flex !important;
|
|
88
|
+
align-items: center !important;
|
|
89
|
+
font-size: 12px !important;
|
|
90
|
+
color: #666 !important;
|
|
91
|
+
gap: 4px !important;
|
|
92
|
+
`, children: [_jsx("span", { role: "img", "aria-hidden": "true", children: "\uD83D\uDD0A" }), _jsx("span", { children: requiresGesture ? (_jsx("button", { onClick: () => retryTtsWithGesture && retryTtsWithGesture(), css: css `
|
|
93
|
+
background: none !important;
|
|
94
|
+
border: none !important;
|
|
95
|
+
color: #1976d2 !important;
|
|
96
|
+
padding: 0 !important;
|
|
97
|
+
text-decoration: underline !important;
|
|
98
|
+
cursor: pointer !important;
|
|
99
|
+
`, children: "Tap to play voice" })) : 'Preparing voice reply...' })] }))] }))] }, message.id))), isLoading && (_jsx("div", { css: loadingIndicator, children: "Thinking..." })), _jsx("div", { ref: messagesEndRef })] }));
|
|
79
100
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../../src/components/ui/ModelSelector.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,
|
|
1
|
+
{"version":3,"file":"ModelSelector.d.ts","sourceRoot":"","sources":["../../../src/components/ui/ModelSelector.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,eAAO,MAAM,aAAa,EAAE,KAAK,CAAC,EAmJjC,CAAC"}
|
|
@@ -4,11 +4,21 @@ import * as React from 'react';
|
|
|
4
4
|
import { css } from '@emotion/react';
|
|
5
5
|
import { useChatBot } from '../context/ChatBotContext';
|
|
6
6
|
export const ModelSelector = () => {
|
|
7
|
-
const { availableModels, selectedModelIndex, handleModelChange } = useChatBot();
|
|
7
|
+
const { availableModels, selectedModelIndex, handleModelChange, serviceId } = useChatBot();
|
|
8
8
|
// Safety check: ensure selectedModelIndex is within bounds
|
|
9
9
|
const safeSelectedModelIndex = selectedModelIndex >= availableModels.length ? 0 : selectedModelIndex;
|
|
10
10
|
// Get fallback model label (first available model or 'Unknown')
|
|
11
|
-
|
|
11
|
+
// Special case: show "Adi" for specific serviceId
|
|
12
|
+
const getDisplayLabel = (label) => {
|
|
13
|
+
const targetServiceId = 'e48fc2b9-a7d1-49e3-85cb-9d621a0bf774';
|
|
14
|
+
if (serviceId && serviceId.trim() === targetServiceId) {
|
|
15
|
+
return 'Adi';
|
|
16
|
+
}
|
|
17
|
+
return label;
|
|
18
|
+
};
|
|
19
|
+
const fallbackModelLabel = availableModels.length > 0
|
|
20
|
+
? getDisplayLabel(availableModels[0].label)
|
|
21
|
+
: 'Unknown';
|
|
12
22
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
|
13
23
|
const open = Boolean(anchorEl);
|
|
14
24
|
const handleClick = (event) => {
|
|
@@ -35,7 +45,7 @@ export const ModelSelector = () => {
|
|
|
35
45
|
background-color: rgba(255, 255, 255, 0.1) !important;
|
|
36
46
|
font-size: 12px !important;
|
|
37
47
|
font-weight: 500 !important;
|
|
38
|
-
`, children: _jsx("span", { children: availableModels[0].label }) }));
|
|
48
|
+
`, children: _jsx("span", { children: getDisplayLabel(availableModels[0].label) }) }));
|
|
39
49
|
}
|
|
40
50
|
// If 2+ models, show full selector with dropdown
|
|
41
51
|
return (_jsxs("div", { css: css `
|
|
@@ -56,7 +66,7 @@ export const ModelSelector = () => {
|
|
|
56
66
|
&:hover {
|
|
57
67
|
background-color: rgba(255, 255, 255, 0.2) !important;
|
|
58
68
|
}
|
|
59
|
-
`, onClick: handleClick, title: "Change AI Model", children: [_jsx("span", { css: css `margin-right: 4px !important;`, children: availableModels[safeSelectedModelIndex]?.label || fallbackModelLabel }), _jsx("span", { css: css `font-size: 10px !important;`, children: "\u25BC" })] }), open && (_jsx("div", { css: css `
|
|
69
|
+
`, onClick: handleClick, title: "Change AI Model", children: [_jsx("span", { css: css `margin-right: 4px !important;`, children: getDisplayLabel(availableModels[safeSelectedModelIndex]?.label || fallbackModelLabel) }), _jsx("span", { css: css `font-size: 10px !important;`, children: "\u25BC" })] }), open && (_jsx("div", { css: css `
|
|
60
70
|
position: absolute !important;
|
|
61
71
|
top: 100% !important;
|
|
62
72
|
left: 0 !important;
|
|
@@ -78,7 +88,7 @@ export const ModelSelector = () => {
|
|
|
78
88
|
&:hover {
|
|
79
89
|
background-color: ${index === safeSelectedModelIndex ? '#f0f0f0' : '#f8f9fa'} !important;
|
|
80
90
|
}
|
|
81
|
-
`, onClick: (event) => handleMenuItemClick(event, index), children: model.label }, model.value))) })), open && (_jsx("div", { css: css `
|
|
91
|
+
`, onClick: (event) => handleMenuItemClick(event, index), children: getDisplayLabel(model.label) }, model.value))) })), open && (_jsx("div", { css: css `
|
|
82
92
|
position: fixed !important;
|
|
83
93
|
top: 0 !important;
|
|
84
94
|
left: 0 !important;
|
package/package.json
CHANGED