@bytexbyte/nxtlinq-ai-agent-sdk 1.6.28 → 1.6.30
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/api/nxtlinq-api.d.ts.map +1 -1
- package/dist/api/nxtlinq-api.js +5 -1
- package/dist/components/context/ChatBotContext.d.ts.map +1 -1
- package/dist/components/context/ChatBotContext.js +216 -69
- package/dist/components/types/ChatBotTypes.d.ts +8 -1
- package/dist/components/types/ChatBotTypes.d.ts.map +1 -1
- package/dist/components/ui/ChatBotUI.d.ts.map +1 -1
- package/dist/components/ui/ChatBotUI.js +255 -16
- package/dist/components/ui/MessageList.d.ts.map +1 -1
- package/dist/components/ui/MessageList.js +6 -2
- package/dist/components/ui/styles/isolatedStyles.d.ts +14 -0
- package/dist/components/ui/styles/isolatedStyles.d.ts.map +1 -1
- package/dist/components/ui/styles/isolatedStyles.js +138 -7
- package/dist/core/lib/textToSpeech.js +1 -1
- package/dist/core/lib/useDraggable.d.ts +15 -0
- package/dist/core/lib/useDraggable.d.ts.map +1 -0
- package/dist/core/lib/useDraggable.js +158 -0
- package/dist/core/lib/useResizable.d.ts +16 -0
- package/dist/core/lib/useResizable.d.ts.map +1 -0
- package/dist/core/lib/useResizable.js +180 -0
- package/dist/core/lib/useSpeechToTextFromMic/helper.d.ts.map +1 -1
- package/dist/core/lib/useSpeechToTextFromMic/helper.js +13 -1
- package/dist/types/ait-api.d.ts +7 -0
- package/dist/types/ait-api.d.ts.map +1 -1
- package/package.json +1 -1
- package/umd/nxtlinq-ai-agent.umd.js +140 -125
- package/dist/assets/images/adilasDogHeadTiltDataUri.d.ts +0 -2
- package/dist/assets/images/adilasDogHeadTiltDataUri.d.ts.map +0 -1
- package/dist/assets/images/adilasDogHeadTiltDataUri.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nxtlinq-api.d.ts","sourceRoot":"","sources":["../../src/api/nxtlinq-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,eAAO,MAAM,WAAW,GAAI,aAAa,YAAY,GAAG,SAAS,SAQhE,CAAC;
|
|
1
|
+
{"version":3,"file":"nxtlinq-api.d.ts","sourceRoot":"","sources":["../../src/api/nxtlinq-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1C,eAAO,MAAM,WAAW,GAAI,aAAa,YAAY,GAAG,SAAS,SAQhE,CAAC;AAiZF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MAUpE,CAAC"}
|
package/dist/api/nxtlinq-api.js
CHANGED
|
@@ -32,7 +32,11 @@ const makeRequest = async (url, options, apiKey, apiSecret) => {
|
|
|
32
32
|
// AIT API module
|
|
33
33
|
const createAITApi = (apiKey, apiSecret) => ({
|
|
34
34
|
getAITByServiceIdAndController: async (params, token) => {
|
|
35
|
-
|
|
35
|
+
const url = new URL(`${AIT_SERVICE_API_HOST}/api/ait/service/${params.serviceId}/controller/${params.controller}`);
|
|
36
|
+
if (params.customUsername) {
|
|
37
|
+
url.searchParams.append('customUsername', params.customUsername);
|
|
38
|
+
}
|
|
39
|
+
return makeRequest(url.toString(), { method: 'GET' }, apiKey, apiSecret);
|
|
36
40
|
},
|
|
37
41
|
createAIT: async (params, token) => {
|
|
38
42
|
return makeRequest(`${AIT_SERVICE_API_HOST}/api/ait`, {
|
|
@@ -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;AAW/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;AAW/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,CA8rFlD,CAAC"}
|
|
@@ -34,7 +34,9 @@ customUsername,
|
|
|
34
34
|
// IDV suggestion banner configuration
|
|
35
35
|
idvBannerDismissSeconds = 86400,
|
|
36
36
|
// 24 hours in seconds
|
|
37
|
-
isStopRecordingOnSend = false,
|
|
37
|
+
isStopRecordingOnSend = false,
|
|
38
|
+
// Custom error message to display in chat
|
|
39
|
+
customError, }) => {
|
|
38
40
|
// Set API hosts immediately based on environment (before any API calls)
|
|
39
41
|
setApiHosts(environment);
|
|
40
42
|
const nxtlinqApi = React.useMemo(() => createNxtlinqApi(apiKey, apiSecret), [apiKey, apiSecret]);
|
|
@@ -121,6 +123,7 @@ isStopRecordingOnSend = false, }) => {
|
|
|
121
123
|
const lastPartialRangeRef = React.useRef(null);
|
|
122
124
|
const lastAutoSentTranscriptRef = React.useRef('');
|
|
123
125
|
const autoSendTimerRef = React.useRef(null);
|
|
126
|
+
const lastCustomErrorRef = React.useRef(undefined);
|
|
124
127
|
function insertPartial(input, partial, caret) {
|
|
125
128
|
let start = caret;
|
|
126
129
|
let end = caret;
|
|
@@ -747,7 +750,8 @@ isStopRecordingOnSend = false, }) => {
|
|
|
747
750
|
if (nxtlinqAITServiceAccessToken) {
|
|
748
751
|
const response = await nxtlinqApi.ait.getAITByServiceIdAndController({
|
|
749
752
|
serviceId,
|
|
750
|
-
controller: hitAddress
|
|
753
|
+
controller: hitAddress,
|
|
754
|
+
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
751
755
|
}, nxtlinqAITServiceAccessToken);
|
|
752
756
|
if ('error' in response) {
|
|
753
757
|
console.error('Failed to fetch AIT:', response.error);
|
|
@@ -1543,46 +1547,114 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1543
1547
|
}]);
|
|
1544
1548
|
return;
|
|
1545
1549
|
}
|
|
1546
|
-
|
|
1550
|
+
// Create streaming message for tool execution
|
|
1551
|
+
const streamingMessageId = `streaming-${Date.now()}`;
|
|
1552
|
+
const streamingMessage = {
|
|
1553
|
+
id: streamingMessageId,
|
|
1554
|
+
content: '',
|
|
1555
|
+
role: 'assistant',
|
|
1556
|
+
timestamp: new Date().toISOString(),
|
|
1557
|
+
isStreaming: true,
|
|
1558
|
+
streamingToolName: toolUse.name,
|
|
1559
|
+
streamingStatus: `Starting ${toolUse.name}...`,
|
|
1560
|
+
streamingProgress: 0,
|
|
1561
|
+
streamingSteps: [],
|
|
1562
|
+
metadata: {
|
|
1563
|
+
model: actualModelUsed,
|
|
1564
|
+
permissions: permissions,
|
|
1565
|
+
issuedBy: hitAddress || '',
|
|
1566
|
+
toolUse: toolUse
|
|
1567
|
+
}
|
|
1568
|
+
};
|
|
1569
|
+
// Add streaming message to chat
|
|
1570
|
+
setMessages(prev => [...prev, streamingMessage]);
|
|
1571
|
+
// Execute tool with streaming updates
|
|
1572
|
+
const toolResult = await onToolUse(toolUse, (update) => {
|
|
1573
|
+
// Update streaming message with progress
|
|
1574
|
+
setMessages(prev => prev.map(msg => msg.id === streamingMessageId
|
|
1575
|
+
? {
|
|
1576
|
+
...msg,
|
|
1577
|
+
content: update.partialResult || msg.content,
|
|
1578
|
+
partialContent: update.partialContent, // Token-level streaming
|
|
1579
|
+
streamingProgress: update.progress,
|
|
1580
|
+
streamingStatus: update.status,
|
|
1581
|
+
streamingSteps: update.steps || msg.streamingSteps
|
|
1582
|
+
}
|
|
1583
|
+
: msg));
|
|
1584
|
+
});
|
|
1547
1585
|
toolMsg = toolResult?.content || `Tool ${toolUse.name} executed successfully`;
|
|
1586
|
+
// Merge AI original reply
|
|
1587
|
+
let replyText = '';
|
|
1588
|
+
if (response.reply) {
|
|
1589
|
+
replyText = Array.isArray(response.reply)
|
|
1590
|
+
? response.reply
|
|
1591
|
+
.map((item) => item.text)
|
|
1592
|
+
.join(' ') || ''
|
|
1593
|
+
: response.reply || '';
|
|
1594
|
+
}
|
|
1595
|
+
else if (response.fullResponse?.output?.message?.content) {
|
|
1596
|
+
replyText = response.fullResponse.output.message.content
|
|
1597
|
+
?.find((item) => item.text)?.text || '';
|
|
1598
|
+
}
|
|
1599
|
+
let finalContent = toolMsg;
|
|
1600
|
+
if (replyText && replyText.trim()) {
|
|
1601
|
+
finalContent += `\n\n${replyText}`;
|
|
1602
|
+
}
|
|
1603
|
+
// Mark streaming as complete with final content
|
|
1604
|
+
setMessages(prev => prev.map(msg => msg.id === streamingMessageId
|
|
1605
|
+
? {
|
|
1606
|
+
...msg,
|
|
1607
|
+
isStreaming: false,
|
|
1608
|
+
streamingProgress: 100,
|
|
1609
|
+
content: finalContent,
|
|
1610
|
+
metadata: {
|
|
1611
|
+
...msg.metadata,
|
|
1612
|
+
model: actualModelUsed,
|
|
1613
|
+
toolUse: toolUse
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1616
|
+
: msg));
|
|
1617
|
+
updateSuggestions(pseudoId, localStorage.getItem('walletAddress') || undefined);
|
|
1618
|
+
// Skip creating a new botResponse since we already updated the streaming message
|
|
1548
1619
|
}
|
|
1549
1620
|
else {
|
|
1550
1621
|
toolMsg = `Tool ${toolUse.name} executed successfully`;
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
.
|
|
1559
|
-
: response.reply || '';
|
|
1560
|
-
}
|
|
1561
|
-
else if (response.fullResponse?.output?.message?.content) {
|
|
1562
|
-
replyText = response.fullResponse.output.message.content
|
|
1563
|
-
?.find((item) => item.text)?.text || '';
|
|
1564
|
-
}
|
|
1565
|
-
let mergedContent = '';
|
|
1566
|
-
if (toolMsg) {
|
|
1567
|
-
mergedContent += toolMsg;
|
|
1568
|
-
}
|
|
1569
|
-
if (replyText && replyText.trim()) {
|
|
1570
|
-
mergedContent += `\n\n${replyText}`;
|
|
1571
|
-
}
|
|
1572
|
-
updateSuggestions(pseudoId, localStorage.getItem('walletAddress') || undefined);
|
|
1573
|
-
botResponse = {
|
|
1574
|
-
id: (Date.now() + 1).toString(),
|
|
1575
|
-
content: mergedContent,
|
|
1576
|
-
role: 'assistant',
|
|
1577
|
-
timestamp: new Date().toISOString(),
|
|
1578
|
-
metadata: {
|
|
1579
|
-
model: actualModelUsed,
|
|
1580
|
-
permissions: permissions,
|
|
1581
|
-
issuedBy: hitAddress || '',
|
|
1582
|
-
toolUse: toolUse
|
|
1622
|
+
// No onToolUse callback - create message without streaming
|
|
1623
|
+
let replyText = '';
|
|
1624
|
+
if (response.reply) {
|
|
1625
|
+
replyText = Array.isArray(response.reply)
|
|
1626
|
+
? response.reply
|
|
1627
|
+
.map((item) => item.text)
|
|
1628
|
+
.join(' ') || ''
|
|
1629
|
+
: response.reply || '';
|
|
1583
1630
|
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1631
|
+
else if (response.fullResponse?.output?.message?.content) {
|
|
1632
|
+
replyText = response.fullResponse.output.message.content
|
|
1633
|
+
?.find((item) => item.text)?.text || '';
|
|
1634
|
+
}
|
|
1635
|
+
let mergedContent = '';
|
|
1636
|
+
if (toolMsg) {
|
|
1637
|
+
mergedContent += toolMsg;
|
|
1638
|
+
}
|
|
1639
|
+
if (replyText && replyText.trim()) {
|
|
1640
|
+
mergedContent += `\n\n${replyText}`;
|
|
1641
|
+
}
|
|
1642
|
+
updateSuggestions(pseudoId, localStorage.getItem('walletAddress') || undefined);
|
|
1643
|
+
const newBotResponse = {
|
|
1644
|
+
id: (Date.now() + 1).toString(),
|
|
1645
|
+
content: mergedContent,
|
|
1646
|
+
role: 'assistant',
|
|
1647
|
+
timestamp: new Date().toISOString(),
|
|
1648
|
+
metadata: {
|
|
1649
|
+
model: actualModelUsed,
|
|
1650
|
+
permissions: permissions,
|
|
1651
|
+
issuedBy: hitAddress || '',
|
|
1652
|
+
toolUse: toolUse
|
|
1653
|
+
}
|
|
1654
|
+
};
|
|
1655
|
+
setMessages(prev => [...prev, newBotResponse]);
|
|
1656
|
+
botResponse = newBotResponse;
|
|
1657
|
+
}
|
|
1586
1658
|
}
|
|
1587
1659
|
else if (response.reply) {
|
|
1588
1660
|
const replyText = Array.isArray(response.reply)
|
|
@@ -1591,7 +1663,7 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1591
1663
|
.join(' ') || 'Sorry, I cannot understand your question'
|
|
1592
1664
|
: response.reply || 'Sorry, I cannot understand your question';
|
|
1593
1665
|
updateSuggestions(pseudoId, localStorage.getItem('walletAddress') || undefined);
|
|
1594
|
-
|
|
1666
|
+
const newBotResponse = {
|
|
1595
1667
|
id: (Date.now() + 1).toString(),
|
|
1596
1668
|
content: replyText,
|
|
1597
1669
|
role: 'assistant',
|
|
@@ -1602,12 +1674,13 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1602
1674
|
issuedBy: hitAddress || ''
|
|
1603
1675
|
}
|
|
1604
1676
|
};
|
|
1605
|
-
setMessages(prev => [...prev,
|
|
1677
|
+
setMessages(prev => [...prev, newBotResponse]);
|
|
1678
|
+
botResponse = newBotResponse;
|
|
1606
1679
|
}
|
|
1607
1680
|
else {
|
|
1608
1681
|
const replyText = response.fullResponse?.output?.message?.content
|
|
1609
1682
|
?.find((item) => item.text)?.text || 'Sorry, I cannot understand your question';
|
|
1610
|
-
|
|
1683
|
+
const newBotResponse = {
|
|
1611
1684
|
id: (Date.now() + 1).toString(),
|
|
1612
1685
|
content: replyText,
|
|
1613
1686
|
role: 'assistant',
|
|
@@ -1618,7 +1691,8 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1618
1691
|
issuedBy: hitAddress || ''
|
|
1619
1692
|
}
|
|
1620
1693
|
};
|
|
1621
|
-
setMessages(prev => [...prev,
|
|
1694
|
+
setMessages(prev => [...prev, newBotResponse]);
|
|
1695
|
+
botResponse = newBotResponse;
|
|
1622
1696
|
}
|
|
1623
1697
|
// Execute redirect after all message processing is complete
|
|
1624
1698
|
if (redirectUrl) {
|
|
@@ -1691,14 +1765,22 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1691
1765
|
if (isMicEnabledRef.current) {
|
|
1692
1766
|
await sleep(1000);
|
|
1693
1767
|
clearRecording();
|
|
1694
|
-
// Reset auto-sent transcript ref when clearing recording
|
|
1695
|
-
lastAutoSentTranscriptRef.current = '';
|
|
1696
1768
|
}
|
|
1697
1769
|
}
|
|
1698
1770
|
if (!textInputRef.current)
|
|
1699
1771
|
return;
|
|
1700
1772
|
if (!textInputRef.current.value.trim() || isLoading)
|
|
1701
1773
|
return;
|
|
1774
|
+
// 如果此時有語音自動發送的計時器,優先取消,避免與手動發送同內容時重複送出
|
|
1775
|
+
if (autoSendTimerRef.current) {
|
|
1776
|
+
clearTimeout(autoSendTimerRef.current);
|
|
1777
|
+
autoSendTimerRef.current = null;
|
|
1778
|
+
}
|
|
1779
|
+
// 標記這次手動送出的內容,讓語音自動發送邏輯視為已送出,避免同一段文字再自動發送一次
|
|
1780
|
+
const manualContent = textInputRef.current.value.trim();
|
|
1781
|
+
if (manualContent) {
|
|
1782
|
+
lastAutoSentTranscriptRef.current = manualContent;
|
|
1783
|
+
}
|
|
1702
1784
|
// Stop current speech playback when user sends new message
|
|
1703
1785
|
stopTextToSpeechAndReset();
|
|
1704
1786
|
// Show loading message if AIT is still loading
|
|
@@ -1766,6 +1848,12 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1766
1848
|
setIsTtsProcessing(false);
|
|
1767
1849
|
pendingTtsRef.current = null;
|
|
1768
1850
|
}, [stopTextToSpeech]);
|
|
1851
|
+
// When TTS is disabled during playback, stop immediately
|
|
1852
|
+
React.useEffect(() => {
|
|
1853
|
+
if (!textToSpeechEnabled) {
|
|
1854
|
+
stopTextToSpeechAndReset();
|
|
1855
|
+
}
|
|
1856
|
+
}, [textToSpeechEnabled, stopTextToSpeechAndReset]);
|
|
1769
1857
|
// Play text-to-speech (simplified, no queue)
|
|
1770
1858
|
const playTextToSpeech = React.useCallback(async (text, messageIndex) => {
|
|
1771
1859
|
if (!textToSpeechEnabled || !text.trim())
|
|
@@ -1793,13 +1881,57 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1793
1881
|
console.error('TTS playback failed after retries:', lastError);
|
|
1794
1882
|
setIsTtsProcessing(false);
|
|
1795
1883
|
}, [textToSpeechEnabled, stopTextToSpeech, playTextToSpeechWithRetry]);
|
|
1884
|
+
const retryTtsWithGesture = React.useCallback(async () => {
|
|
1885
|
+
try {
|
|
1886
|
+
setRequiresGesture(false);
|
|
1887
|
+
// Try to resume audio context
|
|
1888
|
+
if (audioCtxRef.current) {
|
|
1889
|
+
try {
|
|
1890
|
+
await audioCtxRef.current.resume();
|
|
1891
|
+
}
|
|
1892
|
+
catch { }
|
|
1893
|
+
}
|
|
1894
|
+
const pending = pendingTtsRef.current;
|
|
1895
|
+
if (pending && textToSpeechEnabled) {
|
|
1896
|
+
setIsTtsProcessing(true);
|
|
1897
|
+
await playTextToSpeech(pending);
|
|
1898
|
+
pendingTtsRef.current = null;
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
catch (err) {
|
|
1902
|
+
console.error('Retry TTS with gesture failed:', err);
|
|
1903
|
+
setIsTtsProcessing(false);
|
|
1904
|
+
}
|
|
1905
|
+
}, [textToSpeechEnabled, playTextToSpeech]);
|
|
1906
|
+
// When browser blocks autoplay (requires gesture), retry on next user interaction
|
|
1907
|
+
React.useEffect(() => {
|
|
1908
|
+
if (!requiresGesture || !textToSpeechEnabled || !pendingTtsRef.current)
|
|
1909
|
+
return;
|
|
1910
|
+
const handleUserGesture = () => {
|
|
1911
|
+
retryTtsWithGesture();
|
|
1912
|
+
};
|
|
1913
|
+
window.addEventListener('pointerdown', handleUserGesture, { once: true });
|
|
1914
|
+
return () => window.removeEventListener('pointerdown', handleUserGesture);
|
|
1915
|
+
}, [requiresGesture, textToSpeechEnabled, retryTtsWithGesture]);
|
|
1796
1916
|
// Handle preset message
|
|
1797
1917
|
const handlePresetMessage = (message) => {
|
|
1918
|
+
// If preset is configured as auto-send, avoid duplicate sends when user clicks repeatedly
|
|
1798
1919
|
if (message.autoSend) {
|
|
1920
|
+
const trimmedText = (message.text || '').trim();
|
|
1921
|
+
if (!trimmedText)
|
|
1922
|
+
return;
|
|
1923
|
+
// Prevent sending messages while AI Agent is processing
|
|
1924
|
+
if (isLoading) {
|
|
1925
|
+
return;
|
|
1926
|
+
}
|
|
1927
|
+
// If this exact preset text was just sent (by auto-send / manual / preset), skip to prevent duplicates
|
|
1928
|
+
if (lastAutoSentTranscriptRef.current === trimmedText) {
|
|
1929
|
+
return;
|
|
1930
|
+
}
|
|
1799
1931
|
// For preset messages, we need to add the user message first since sendMessage won't add it on retries
|
|
1800
1932
|
const userMessage = {
|
|
1801
1933
|
id: Date.now().toString(),
|
|
1802
|
-
content:
|
|
1934
|
+
content: trimmedText,
|
|
1803
1935
|
role: 'user',
|
|
1804
1936
|
timestamp: new Date().toISOString(),
|
|
1805
1937
|
metadata: {
|
|
@@ -1809,8 +1941,10 @@ isStopRecordingOnSend = false, }) => {
|
|
|
1809
1941
|
}
|
|
1810
1942
|
};
|
|
1811
1943
|
setMessages(prev => [...prev, userMessage]);
|
|
1944
|
+
// Mark as last sent to guard against rapid re-clicks and other duplicate flows
|
|
1945
|
+
lastAutoSentTranscriptRef.current = trimmedText;
|
|
1812
1946
|
// Pass a flag to indicate this is a preset message so sendMessage won't add user message again
|
|
1813
|
-
sendMessage(
|
|
1947
|
+
sendMessage(trimmedText, 0, true);
|
|
1814
1948
|
}
|
|
1815
1949
|
else {
|
|
1816
1950
|
setInputValue(message.text);
|
|
@@ -2052,7 +2186,11 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2052
2186
|
const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
|
|
2053
2187
|
if (!('error' in walletResponse)) {
|
|
2054
2188
|
setWalletInfo(walletResponse);
|
|
2055
|
-
const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
|
|
2189
|
+
const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
|
|
2190
|
+
serviceId,
|
|
2191
|
+
controller: address,
|
|
2192
|
+
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
2193
|
+
}, token);
|
|
2056
2194
|
if (!('error' in aitResponse)) {
|
|
2057
2195
|
setAit(aitResponse);
|
|
2058
2196
|
}
|
|
@@ -2088,7 +2226,11 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2088
2226
|
const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
|
|
2089
2227
|
if (!('error' in walletResponse)) {
|
|
2090
2228
|
setWalletInfo(walletResponse);
|
|
2091
|
-
const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
|
|
2229
|
+
const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
|
|
2230
|
+
serviceId,
|
|
2231
|
+
controller: address,
|
|
2232
|
+
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
2233
|
+
}, token);
|
|
2092
2234
|
if (!('error' in aitResponse)) {
|
|
2093
2235
|
setAit(aitResponse);
|
|
2094
2236
|
}
|
|
@@ -2224,6 +2366,31 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2224
2366
|
}
|
|
2225
2367
|
}
|
|
2226
2368
|
}, [hitAddress]);
|
|
2369
|
+
// Handle custom error message display
|
|
2370
|
+
React.useEffect(() => {
|
|
2371
|
+
const trimmedError = customError?.trim();
|
|
2372
|
+
// Only display error if it's a new value (different from last displayed error)
|
|
2373
|
+
if (trimmedError && trimmedError !== lastCustomErrorRef.current) {
|
|
2374
|
+
lastCustomErrorRef.current = trimmedError;
|
|
2375
|
+
const errorMessage = {
|
|
2376
|
+
id: `custom-error-${Date.now()}`,
|
|
2377
|
+
content: trimmedError,
|
|
2378
|
+
role: 'assistant',
|
|
2379
|
+
timestamp: new Date().toISOString(),
|
|
2380
|
+
metadata: {
|
|
2381
|
+
model: getCurrentModel().value,
|
|
2382
|
+
permissions: permissions,
|
|
2383
|
+
issuedBy: hitAddress || ''
|
|
2384
|
+
}
|
|
2385
|
+
};
|
|
2386
|
+
setMessages(prev => [...prev, errorMessage]);
|
|
2387
|
+
onMessage?.(errorMessage);
|
|
2388
|
+
}
|
|
2389
|
+
else if (!trimmedError) {
|
|
2390
|
+
// Reset ref when customError is cleared
|
|
2391
|
+
lastCustomErrorRef.current = undefined;
|
|
2392
|
+
}
|
|
2393
|
+
}, [customError, getCurrentModel, permissions, hitAddress, onMessage]);
|
|
2227
2394
|
React.useEffect(() => {
|
|
2228
2395
|
if (messages.length > 0) {
|
|
2229
2396
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -2328,28 +2495,7 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2328
2495
|
// Speech related functions
|
|
2329
2496
|
playTextToSpeech,
|
|
2330
2497
|
stopTextToSpeech,
|
|
2331
|
-
retryTtsWithGesture
|
|
2332
|
-
try {
|
|
2333
|
-
setRequiresGesture(false);
|
|
2334
|
-
// Try to resume audio context
|
|
2335
|
-
if (audioCtxRef.current) {
|
|
2336
|
-
try {
|
|
2337
|
-
await audioCtxRef.current.resume();
|
|
2338
|
-
}
|
|
2339
|
-
catch { }
|
|
2340
|
-
}
|
|
2341
|
-
const pending = pendingTtsRef.current;
|
|
2342
|
-
if (pending && textToSpeechEnabled) {
|
|
2343
|
-
setIsTtsProcessing(true);
|
|
2344
|
-
await playTextToSpeech(pending);
|
|
2345
|
-
pendingTtsRef.current = null;
|
|
2346
|
-
}
|
|
2347
|
-
}
|
|
2348
|
-
catch (err) {
|
|
2349
|
-
console.error('Retry TTS with gesture failed:', err);
|
|
2350
|
-
setIsTtsProcessing(false);
|
|
2351
|
-
}
|
|
2352
|
-
},
|
|
2498
|
+
retryTtsWithGesture,
|
|
2353
2499
|
// Additional properties for PermissionForm
|
|
2354
2500
|
onSave: savePermissions,
|
|
2355
2501
|
onConnectWallet: () => connectWallet(false),
|
|
@@ -2381,6 +2527,7 @@ isStopRecordingOnSend = false, }) => {
|
|
|
2381
2527
|
customUsername,
|
|
2382
2528
|
idvBannerDismissSeconds,
|
|
2383
2529
|
isStopRecordingOnSend,
|
|
2530
|
+
customError,
|
|
2384
2531
|
},
|
|
2385
2532
|
nxtlinqApi
|
|
2386
2533
|
};
|
|
@@ -31,7 +31,13 @@ export interface AIModel {
|
|
|
31
31
|
export interface ChatBotProps {
|
|
32
32
|
onMessage?: (message: Message) => void;
|
|
33
33
|
onError?: (error: Error) => void;
|
|
34
|
-
onToolUse?: (toolUse: ToolUse
|
|
34
|
+
onToolUse?: (toolUse: ToolUse, onProgress?: (update: {
|
|
35
|
+
status?: string;
|
|
36
|
+
progress?: number;
|
|
37
|
+
partialResult?: string;
|
|
38
|
+
steps?: string[];
|
|
39
|
+
partialContent?: string;
|
|
40
|
+
}) => void) => Promise<Message | void>;
|
|
35
41
|
presetMessages?: PresetMessage[];
|
|
36
42
|
placeholder?: string;
|
|
37
43
|
className?: string;
|
|
@@ -55,6 +61,7 @@ export interface ChatBotProps {
|
|
|
55
61
|
idvBannerDismissSeconds?: number;
|
|
56
62
|
berifymeMode?: 'built-in' | 'external';
|
|
57
63
|
isStopRecordingOnSend?: boolean;
|
|
64
|
+
customError?: string;
|
|
58
65
|
}
|
|
59
66
|
export interface ChatBotContextType {
|
|
60
67
|
messages: Message[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatBotTypes.d.ts","sourceRoot":"","sources":["../../../src/components/types/ChatBotTypes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE9E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/B,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAGD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,
|
|
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":"ChatBotUI.d.ts","sourceRoot":"","sources":["../../../src/components/ui/ChatBotUI.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatBotUI.d.ts","sourceRoot":"","sources":["../../../src/components/ui/ChatBotUI.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA8F/B,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAooB7B,CAAC"}
|