@bytexbyte/nxtlinq-ai-agent-sdk 1.6.32 → 1.6.33
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 +50 -1
- package/dist/components/context/ChatBotContext.d.ts.map +1 -1
- package/dist/components/context/ChatBotContext.js +47 -23
- package/dist/components/types/ChatBotTypes.d.ts +7 -2
- package/dist/components/types/ChatBotTypes.d.ts.map +1 -1
- package/dist/components/ui/ChatBotUI.d.ts +0 -1
- package/dist/components/ui/ChatBotUI.d.ts.map +1 -1
- package/dist/components/ui/ChatBotUI.js +97 -48
- package/dist/components/ui/MessageInput.d.ts.map +1 -1
- package/dist/components/ui/MessageInput.js +228 -8
- package/dist/components/ui/MessageList.d.ts.map +1 -1
- package/dist/components/ui/MessageList.js +44 -1
- package/dist/core/lib/useLocalStorage.d.ts +8 -0
- package/dist/core/lib/useLocalStorage.d.ts.map +1 -1
- package/dist/core/lib/useLocalStorage.js +71 -6
- package/dist/types/ait-api.d.ts +27 -0
- package/dist/types/ait-api.d.ts.map +1 -1
- package/package.json +1 -1
- package/umd/nxtlinq-ai-agent.umd.js +168 -379
|
@@ -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;AA4eF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,WAAW,MAAM,KAAG,MAUpE,CAAC"}
|
package/dist/api/nxtlinq-api.js
CHANGED
|
@@ -106,6 +106,7 @@ const createAgentApi = () => ({
|
|
|
106
106
|
customUserInfo: params.customUserInfo,
|
|
107
107
|
customUsername: params.customUsername,
|
|
108
108
|
message: params.message,
|
|
109
|
+
attachments: params.attachments,
|
|
109
110
|
walletAddress: walletAddress || undefined,
|
|
110
111
|
aitToken: aitToken || undefined,
|
|
111
112
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
|
|
@@ -295,7 +296,55 @@ const createAgentApi = () => ({
|
|
|
295
296
|
console.error('Failed to update message content:', error);
|
|
296
297
|
return { error: error instanceof Error ? error.message : 'Failed to update message content' };
|
|
297
298
|
}
|
|
298
|
-
}
|
|
299
|
+
},
|
|
300
|
+
uploadAttachment: async (params) => {
|
|
301
|
+
try {
|
|
302
|
+
const originalName = params.file.name;
|
|
303
|
+
const safeName = originalName.replace(/[^\x00-\x7F.a-zA-Z0-9_-]/g, '_').replace(/^\.+/, '') || 'file';
|
|
304
|
+
const fileForUpload = safeName !== originalName
|
|
305
|
+
? new File([params.file], safeName, { type: params.file.type, lastModified: params.file.lastModified })
|
|
306
|
+
: params.file;
|
|
307
|
+
const form = new FormData();
|
|
308
|
+
form.append('file', fileForUpload);
|
|
309
|
+
form.append('pseudoId', params.pseudoId);
|
|
310
|
+
if (safeName !== originalName) {
|
|
311
|
+
form.append('originalName', originalName);
|
|
312
|
+
}
|
|
313
|
+
const walletAddress = typeof localStorage !== 'undefined' ? localStorage.getItem('walletAddress') : null;
|
|
314
|
+
const aitTokenRaw = typeof localStorage !== 'undefined' ? localStorage.getItem('nxtlinqAITServiceAccessToken') : null;
|
|
315
|
+
const aitToken = aitTokenRaw ? JSON.parse(aitTokenRaw) : null;
|
|
316
|
+
const headers = {
|
|
317
|
+
'X-API-Key': params.apiKey,
|
|
318
|
+
'X-API-Secret': params.apiSecret,
|
|
319
|
+
'X-Wallet-Address': walletAddress || '',
|
|
320
|
+
'X-AIT-Token': aitToken || '',
|
|
321
|
+
};
|
|
322
|
+
const response = await fetch(`${AI_AGENT_API_HOST}/api/upload`, {
|
|
323
|
+
method: 'POST',
|
|
324
|
+
headers,
|
|
325
|
+
body: form,
|
|
326
|
+
});
|
|
327
|
+
const text = await response.text();
|
|
328
|
+
let data;
|
|
329
|
+
try {
|
|
330
|
+
data = text ? JSON.parse(text) : {};
|
|
331
|
+
}
|
|
332
|
+
catch {
|
|
333
|
+
data = {};
|
|
334
|
+
}
|
|
335
|
+
if (!response.ok) {
|
|
336
|
+
return { error: data.error || response.statusText || 'Upload failed' };
|
|
337
|
+
}
|
|
338
|
+
if (!data.url) {
|
|
339
|
+
return { error: data.error || 'Upload failed' };
|
|
340
|
+
}
|
|
341
|
+
return data;
|
|
342
|
+
}
|
|
343
|
+
catch (e) {
|
|
344
|
+
console.error('Upload attachment failed:', e);
|
|
345
|
+
return { error: e instanceof Error ? e.message : 'Upload failed' };
|
|
346
|
+
}
|
|
347
|
+
},
|
|
299
348
|
});
|
|
300
349
|
// Permissions API module
|
|
301
350
|
const createPermissionsApi = (apiKey, apiSecret) => ({
|
|
@@ -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,CA2vFlD,CAAC"}
|
|
@@ -24,7 +24,7 @@ export const ChatBotProvider = ({ onMessage, onError, onToolUse, presetMessages
|
|
|
24
24
|
// AI Model related attributes
|
|
25
25
|
onModelChange,
|
|
26
26
|
// Storage mode configuration
|
|
27
|
-
|
|
27
|
+
storageMode = "local-storage",
|
|
28
28
|
// Wallet verification configuration
|
|
29
29
|
requireWalletIDVVerification = true, isSemiAutomaticMode = false,
|
|
30
30
|
// Custom user identity information
|
|
@@ -45,11 +45,11 @@ customError, }) => {
|
|
|
45
45
|
apiKey,
|
|
46
46
|
apiSecret
|
|
47
47
|
});
|
|
48
|
-
//
|
|
49
|
-
const [messages, setMessages] =
|
|
50
|
-
?
|
|
51
|
-
:
|
|
52
|
-
const [isOpen, setIsOpen] =
|
|
48
|
+
// Messages: Use storage based on storageMode to support cross-tab sync (local-storage) or session isolation (session-storage)
|
|
49
|
+
const [messages, setMessages] = storageMode === "local-storage"
|
|
50
|
+
? useLocalStorage('chatbot-messages', [])
|
|
51
|
+
: useSessionStorage('chatbot-messages', []);
|
|
52
|
+
const [isOpen, setIsOpen] = storageMode === "session-storage"
|
|
53
53
|
? useSessionStorage('chatbot-is-open', false)
|
|
54
54
|
: React.useState(false);
|
|
55
55
|
const [inputValue, setInputValue] = React.useState('');
|
|
@@ -69,12 +69,13 @@ customError, }) => {
|
|
|
69
69
|
// Persistent data (always use localStorage)
|
|
70
70
|
const [nxtlinqAITServiceAccessToken, setNxtlinqAITServiceAccessToken] = useLocalStorage('nxtlinqAITServiceAccessToken', '');
|
|
71
71
|
const [pseudoId, setPseudoId] = useLocalStorage('pseudoId', uuidv4());
|
|
72
|
-
//
|
|
73
|
-
const [suggestions, setSuggestions] =
|
|
74
|
-
?
|
|
75
|
-
:
|
|
72
|
+
// Suggestions: Use storage based on storageMode to support cross-tab sync (local-storage) or session isolation (session-storage)
|
|
73
|
+
const [suggestions, setSuggestions] = storageMode === "local-storage"
|
|
74
|
+
? useLocalStorage('chatbot-suggestions', presetMessages)
|
|
75
|
+
: useSessionStorage('chatbot-suggestions', presetMessages);
|
|
76
76
|
const [isAITEnabling, setIsAITEnabling] = React.useState(false);
|
|
77
77
|
const [isAwaitingMicGesture, setIsAwaitingMicGesture] = React.useState(false);
|
|
78
|
+
// autoSendEnabled: Always use localStorage (do not sync across tabs to avoid conflicts with speech-to-text)
|
|
78
79
|
const [autoSendEnabled, setAutoSendEnabled] = useLocalStorage('chatbot-auto-send-enabled', true);
|
|
79
80
|
// Speech related state
|
|
80
81
|
const [textToSpeechEnabled, setTextToSpeechEnabled] = useLocalStorage('chatbot-text-to-speech-enabled', false);
|
|
@@ -465,7 +466,7 @@ customError, }) => {
|
|
|
465
466
|
if (typeof window === 'undefined') {
|
|
466
467
|
return;
|
|
467
468
|
}
|
|
468
|
-
if (
|
|
469
|
+
if (storageMode !== "session-storage") {
|
|
469
470
|
sessionStorage.removeItem(MIC_ENABLED_SESSION_KEY);
|
|
470
471
|
hasSyncedMicStateRef.current = false;
|
|
471
472
|
return;
|
|
@@ -479,7 +480,7 @@ customError, }) => {
|
|
|
479
480
|
catch (error) {
|
|
480
481
|
console.warn('Failed to persist recording state to sessionStorage:', error);
|
|
481
482
|
}
|
|
482
|
-
}, [isMicEnabled,
|
|
483
|
+
}, [isMicEnabled, storageMode]);
|
|
483
484
|
React.useEffect(() => {
|
|
484
485
|
if (typeof window === 'undefined') {
|
|
485
486
|
return;
|
|
@@ -490,7 +491,7 @@ customError, }) => {
|
|
|
490
491
|
autoStartGestureCleanupRef.current = null;
|
|
491
492
|
}
|
|
492
493
|
};
|
|
493
|
-
if (
|
|
494
|
+
if (storageMode !== "session-storage") {
|
|
494
495
|
cleanupAutoStartListeners();
|
|
495
496
|
pendingMicAutoStartRef.current = false;
|
|
496
497
|
setIsAwaitingMicGesture(false);
|
|
@@ -627,7 +628,7 @@ customError, }) => {
|
|
|
627
628
|
pendingMicAutoStartRef.current = false;
|
|
628
629
|
setIsAwaitingMicGesture(false);
|
|
629
630
|
};
|
|
630
|
-
}, [
|
|
631
|
+
}, [storageMode, startRecording]);
|
|
631
632
|
const [notification, setNotification] = React.useState({
|
|
632
633
|
show: false,
|
|
633
634
|
type: 'info',
|
|
@@ -1341,9 +1342,10 @@ customError, }) => {
|
|
|
1341
1342
|
autoSend: true
|
|
1342
1343
|
})));
|
|
1343
1344
|
}, []);
|
|
1344
|
-
// Updated sendMessage function to support different AI models
|
|
1345
|
-
const sendMessage = async (content, retryCount = 0, isPresetMessage = false) => {
|
|
1346
|
-
|
|
1345
|
+
// Updated sendMessage function to support different AI models and attachments
|
|
1346
|
+
const sendMessage = async (content, retryCount = 0, isPresetMessage = false, attachments) => {
|
|
1347
|
+
const hasContent = content.trim() || (attachments && attachments.length > 0);
|
|
1348
|
+
if (!hasContent || isLoading)
|
|
1347
1349
|
return;
|
|
1348
1350
|
const currentModel = getCurrentModel();
|
|
1349
1351
|
// Initialize with current model, will be updated with actual model from backend response
|
|
@@ -1353,9 +1355,10 @@ customError, }) => {
|
|
|
1353
1355
|
if (retryCount === 0 && !isPresetMessage) {
|
|
1354
1356
|
const userMessage = {
|
|
1355
1357
|
id: Date.now().toString(),
|
|
1356
|
-
content,
|
|
1358
|
+
content: content || (attachments && attachments.length > 0 ? `已上傳 ${attachments.length} 個檔案` : ''),
|
|
1357
1359
|
role: 'user',
|
|
1358
1360
|
timestamp: new Date().toISOString(),
|
|
1361
|
+
attachments: attachments,
|
|
1359
1362
|
metadata: {
|
|
1360
1363
|
model: currentModel.value,
|
|
1361
1364
|
permissions: permissions,
|
|
@@ -1367,6 +1370,13 @@ customError, }) => {
|
|
|
1367
1370
|
}
|
|
1368
1371
|
setIsLoading(true);
|
|
1369
1372
|
try {
|
|
1373
|
+
// Prepare attachments for API
|
|
1374
|
+
const apiAttachments = attachments?.map(att => ({
|
|
1375
|
+
type: att.type,
|
|
1376
|
+
url: att.url,
|
|
1377
|
+
name: att.name,
|
|
1378
|
+
mimeType: att.mimeType
|
|
1379
|
+
}));
|
|
1370
1380
|
const response = await nxtlinqApi.agent.sendMessage({
|
|
1371
1381
|
model: currentModel.value,
|
|
1372
1382
|
apiKey,
|
|
@@ -1375,7 +1385,8 @@ customError, }) => {
|
|
|
1375
1385
|
externalId: localStorage.getItem('walletAddress') || undefined,
|
|
1376
1386
|
customUserInfo,
|
|
1377
1387
|
customUsername,
|
|
1378
|
-
message: content,
|
|
1388
|
+
message: content || (attachments && attachments.length > 0 ? `已上傳 ${attachments.length} 個檔案` : ''),
|
|
1389
|
+
attachments: apiAttachments,
|
|
1379
1390
|
});
|
|
1380
1391
|
// Get the actual model used from response (may differ due to fallback)
|
|
1381
1392
|
actualModelUsed = response.model || currentModel.value;
|
|
@@ -1786,7 +1797,7 @@ customError, }) => {
|
|
|
1786
1797
|
}
|
|
1787
1798
|
};
|
|
1788
1799
|
// Handle submit
|
|
1789
|
-
const handleSubmit = async (e) => {
|
|
1800
|
+
const handleSubmit = async (e, attachments) => {
|
|
1790
1801
|
e.preventDefault();
|
|
1791
1802
|
if (isStopRecordingOnSend) {
|
|
1792
1803
|
while (isMicEnabledRef.current) {
|
|
@@ -1802,7 +1813,8 @@ customError, }) => {
|
|
|
1802
1813
|
}
|
|
1803
1814
|
if (!textInputRef.current)
|
|
1804
1815
|
return;
|
|
1805
|
-
|
|
1816
|
+
const hasContent = textInputRef.current.value.trim() || (attachments && attachments.length > 0);
|
|
1817
|
+
if (!hasContent || isLoading)
|
|
1806
1818
|
return;
|
|
1807
1819
|
// 如果此時有語音自動發送的計時器,優先取消,避免與手動發送同內容時重複送出
|
|
1808
1820
|
if (autoSendTimerRef.current) {
|
|
@@ -1833,7 +1845,7 @@ customError, }) => {
|
|
|
1833
1845
|
return;
|
|
1834
1846
|
}
|
|
1835
1847
|
try {
|
|
1836
|
-
await sendMessage(textInputRef.current.value);
|
|
1848
|
+
await sendMessage(textInputRef.current.value, 0, false, attachments);
|
|
1837
1849
|
}
|
|
1838
1850
|
catch (error) {
|
|
1839
1851
|
console.error('Failed to send message:', error);
|
|
@@ -1946,6 +1958,17 @@ customError, }) => {
|
|
|
1946
1958
|
window.addEventListener('pointerdown', handleUserGesture, { once: true });
|
|
1947
1959
|
return () => window.removeEventListener('pointerdown', handleUserGesture);
|
|
1948
1960
|
}, [requiresGesture, textToSpeechEnabled, retryTtsWithGesture]);
|
|
1961
|
+
const uploadAttachment = React.useCallback(async (file) => {
|
|
1962
|
+
const result = await nxtlinqApi.agent.uploadAttachment({
|
|
1963
|
+
apiKey,
|
|
1964
|
+
apiSecret,
|
|
1965
|
+
pseudoId,
|
|
1966
|
+
file,
|
|
1967
|
+
});
|
|
1968
|
+
if ('error' in result)
|
|
1969
|
+
return result;
|
|
1970
|
+
return { url: result.url };
|
|
1971
|
+
}, [nxtlinqApi, apiKey, apiSecret, pseudoId]);
|
|
1949
1972
|
// Handle preset message
|
|
1950
1973
|
const handlePresetMessage = (message) => {
|
|
1951
1974
|
// If preset is configured as auto-send, avoid duplicate sends when user clicks repeatedly
|
|
@@ -2530,6 +2553,7 @@ customError, }) => {
|
|
|
2530
2553
|
playTextToSpeech,
|
|
2531
2554
|
stopTextToSpeech,
|
|
2532
2555
|
retryTtsWithGesture,
|
|
2556
|
+
uploadAttachment,
|
|
2533
2557
|
// Additional properties for PermissionForm
|
|
2534
2558
|
onSave: savePermissions,
|
|
2535
2559
|
onConnectWallet: () => connectWallet(false),
|
|
@@ -2554,7 +2578,7 @@ customError, }) => {
|
|
|
2554
2578
|
onVerifyWallet,
|
|
2555
2579
|
permissionGroup,
|
|
2556
2580
|
onModelChange,
|
|
2557
|
-
|
|
2581
|
+
storageMode,
|
|
2558
2582
|
requireWalletIDVVerification,
|
|
2559
2583
|
isSemiAutomaticMode,
|
|
2560
2584
|
customUserInfo,
|
|
@@ -53,7 +53,7 @@ export interface ChatBotProps {
|
|
|
53
53
|
permissionGroup?: string;
|
|
54
54
|
children?: React.ReactNode;
|
|
55
55
|
onModelChange?: (model: AIModel) => void;
|
|
56
|
-
|
|
56
|
+
storageMode?: "session-storage" | "local-storage";
|
|
57
57
|
requireWalletIDVVerification?: boolean;
|
|
58
58
|
isSemiAutomaticMode?: boolean;
|
|
59
59
|
customUserInfo?: Record<string, any>;
|
|
@@ -115,7 +115,7 @@ export interface ChatBotContextType {
|
|
|
115
115
|
connectWallet: (autoShowSignInMessage?: boolean) => Promise<string | false | undefined>;
|
|
116
116
|
signInWallet: (autoShowSuccessMessage?: boolean) => Promise<void>;
|
|
117
117
|
sendMessage: (content: string, retryCount?: number) => Promise<void>;
|
|
118
|
-
handleSubmit: (e: React.FormEvent) => Promise<void>;
|
|
118
|
+
handleSubmit: (e: React.FormEvent, attachments?: import('../../types/ait-api').Attachment[]) => Promise<void>;
|
|
119
119
|
handlePresetMessage: (message: PresetMessage) => void;
|
|
120
120
|
savePermissions: (newPermissions?: string[]) => Promise<void>;
|
|
121
121
|
enableAIT: (toolName: string) => Promise<boolean>;
|
|
@@ -133,6 +133,11 @@ export interface ChatBotContextType {
|
|
|
133
133
|
playTextToSpeech: (text: string) => Promise<void>;
|
|
134
134
|
stopTextToSpeech: () => void;
|
|
135
135
|
retryTtsWithGesture?: () => Promise<void>;
|
|
136
|
+
uploadAttachment: (file: File) => Promise<{
|
|
137
|
+
url: string;
|
|
138
|
+
} | {
|
|
139
|
+
error: string;
|
|
140
|
+
}>;
|
|
136
141
|
onSave: (newPermissions?: string[]) => Promise<void>;
|
|
137
142
|
onConnectWallet: () => Promise<string | false | undefined>;
|
|
138
143
|
onSignIn: () => Promise<void>;
|
|
@@ -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,CACV,OAAO,EAAE,OAAO,EAChB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE;QACpB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,KAAK,IAAI,KACP,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC7B,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACvC,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC;QAC7B,KAAK,EAAE,MAAM,CAAC;KACf,GAAG,SAAS,CAAC,CAAC;IACf,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAE3B,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC,
|
|
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":"
|
|
1
|
+
{"version":3,"file":"ChatBotUI.d.ts","sourceRoot":"","sources":["../../../src/components/ui/ChatBotUI.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA4F/B,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAwrB7B,CAAC"}
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "@emotion/react/jsx-runtime";
|
|
2
2
|
/** @jsxImportSource @emotion/react */
|
|
3
|
-
import * as React from 'react';
|
|
4
3
|
import { css } from '@emotion/react';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import { useDraggable } from '../../core/lib/useDraggable';
|
|
6
|
+
import useLocalStorage from '../../core/lib/useLocalStorage';
|
|
7
|
+
import { useResizable } from '../../core/lib/useResizable';
|
|
8
|
+
import * as walletTextUtils from '../../core/utils/walletTextUtils';
|
|
5
9
|
import { useChatBot } from '../context/ChatBotContext';
|
|
6
|
-
import { PermissionForm } from './PermissionForm';
|
|
7
|
-
import { MessageList } from './MessageList';
|
|
8
10
|
import { MessageInput } from './MessageInput';
|
|
9
|
-
import {
|
|
11
|
+
import { MessageList } from './MessageList';
|
|
10
12
|
import { ModelSelector } from './ModelSelector';
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import useLocalStorage from '../../core/lib/useLocalStorage';
|
|
15
|
-
import { sdkContainer, floatingButton, chatWindow, chatHeader, headerTitle, headerButton, closeButton, modalOverlay, idvBanner, idvBannerTitle, idvBannerText, idvVerifyButton, idvDismissButton, loadingSpinner, successToast, errorToast, warningToast, infoToast, toastCloseButton } from './styles/isolatedStyles';
|
|
16
|
-
import { resizeHandle } from './styles/isolatedStyles';
|
|
13
|
+
import { PermissionForm } from './PermissionForm';
|
|
14
|
+
import { PresetMessages } from './PresetMessages';
|
|
15
|
+
import { chatHeader, chatWindow, closeButton, errorToast, floatingButton, headerButton, headerTitle, idvBanner, idvBannerText, idvBannerTitle, idvDismissButton, idvVerifyButton, infoToast, loadingSpinner, modalOverlay, resizeHandle, sdkContainer, successToast, toastCloseButton, warningToast } from './styles/isolatedStyles';
|
|
17
16
|
// Toast Notification Component
|
|
18
17
|
const ToastNotification = ({ type, message, onClose, isChatOpen = false }) => {
|
|
19
18
|
const getToastStyles = () => {
|
|
@@ -71,10 +70,62 @@ export const ChatBotUI = () => {
|
|
|
71
70
|
const [showIDVSuggestion, setShowIDVSuggestion] = React.useState(true);
|
|
72
71
|
const [dismissUntil, setDismissUntil] = React.useState(null);
|
|
73
72
|
const [timeRemaining, setTimeRemaining] = React.useState('');
|
|
73
|
+
const countdownIntervalRef = React.useRef(null);
|
|
74
74
|
// Check if there's a berifyme token in URL (indicating recent berifyme verification)
|
|
75
75
|
const urlParams = new URLSearchParams(window.location.search);
|
|
76
76
|
const hasBerifymeToken = urlParams.get('token') && urlParams.get('method') === 'berifyme';
|
|
77
77
|
const isWalletVerifiedWithBerifyme = walletInfo?.id && walletInfo?.method === 'berifyme';
|
|
78
|
+
// Helper function to update IDV suggestion state based on storage value
|
|
79
|
+
const updateIDVSuggestionState = React.useCallback((dismissedValue) => {
|
|
80
|
+
// Clear any existing countdown interval
|
|
81
|
+
if (countdownIntervalRef.current) {
|
|
82
|
+
clearInterval(countdownIntervalRef.current);
|
|
83
|
+
countdownIntervalRef.current = null;
|
|
84
|
+
}
|
|
85
|
+
if (dismissedValue) {
|
|
86
|
+
const dismissTime = parseInt(dismissedValue);
|
|
87
|
+
const now = Date.now();
|
|
88
|
+
const timeLeft = dismissTime - now;
|
|
89
|
+
if (timeLeft > 0) {
|
|
90
|
+
setShowIDVSuggestion(false);
|
|
91
|
+
setDismissUntil(dismissTime);
|
|
92
|
+
// Calculate initial time remaining immediately
|
|
93
|
+
const hours = Math.floor(timeLeft / (1000 * 60 * 60));
|
|
94
|
+
const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60));
|
|
95
|
+
setTimeRemaining(`${hours}h ${minutes}m`);
|
|
96
|
+
// Set up countdown interval to update time remaining every minute
|
|
97
|
+
countdownIntervalRef.current = setInterval(() => {
|
|
98
|
+
const remaining = dismissTime - Date.now();
|
|
99
|
+
if (remaining > 0) {
|
|
100
|
+
const hours = Math.floor(remaining / (1000 * 60 * 60));
|
|
101
|
+
const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
|
|
102
|
+
setTimeRemaining(`${hours}h ${minutes}m`);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
setShowIDVSuggestion(true);
|
|
106
|
+
setDismissUntil(null);
|
|
107
|
+
setTimeRemaining('');
|
|
108
|
+
localStorage.removeItem('idv-suggestion-dismissed');
|
|
109
|
+
if (countdownIntervalRef.current) {
|
|
110
|
+
clearInterval(countdownIntervalRef.current);
|
|
111
|
+
countdownIntervalRef.current = null;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}, 60000);
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
localStorage.removeItem('idv-suggestion-dismissed');
|
|
118
|
+
setShowIDVSuggestion(true);
|
|
119
|
+
setDismissUntil(null);
|
|
120
|
+
setTimeRemaining('');
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
setShowIDVSuggestion(true);
|
|
125
|
+
setDismissUntil(null);
|
|
126
|
+
setTimeRemaining('');
|
|
127
|
+
}
|
|
128
|
+
}, []);
|
|
78
129
|
// Check if IDV suggestion should be shown
|
|
79
130
|
React.useEffect(() => {
|
|
80
131
|
const shouldShowBanner = hitAddress &&
|
|
@@ -91,42 +142,7 @@ export const ChatBotUI = () => {
|
|
|
91
142
|
!isNeedSignInWithWallet;
|
|
92
143
|
if (shouldShowBannerAfterDelay) {
|
|
93
144
|
const dismissed = localStorage.getItem('idv-suggestion-dismissed');
|
|
94
|
-
|
|
95
|
-
const dismissTime = parseInt(dismissed);
|
|
96
|
-
const now = Date.now();
|
|
97
|
-
const timeLeft = dismissTime - now;
|
|
98
|
-
if (timeLeft > 0) {
|
|
99
|
-
setShowIDVSuggestion(false);
|
|
100
|
-
setDismissUntil(dismissTime);
|
|
101
|
-
const countdownTimer = setInterval(() => {
|
|
102
|
-
const remaining = dismissTime - Date.now();
|
|
103
|
-
if (remaining > 0) {
|
|
104
|
-
const hours = Math.floor(remaining / (1000 * 60 * 60));
|
|
105
|
-
const minutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
|
|
106
|
-
setTimeRemaining(`${hours}h ${minutes}m`);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
setShowIDVSuggestion(true);
|
|
110
|
-
setDismissUntil(null);
|
|
111
|
-
setTimeRemaining('');
|
|
112
|
-
localStorage.removeItem('idv-suggestion-dismissed');
|
|
113
|
-
clearInterval(countdownTimer);
|
|
114
|
-
}
|
|
115
|
-
}, 60000);
|
|
116
|
-
return () => clearInterval(countdownTimer);
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
localStorage.removeItem('idv-suggestion-dismissed');
|
|
120
|
-
setShowIDVSuggestion(true);
|
|
121
|
-
setDismissUntil(null);
|
|
122
|
-
setTimeRemaining('');
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
setShowIDVSuggestion(true);
|
|
127
|
-
setDismissUntil(null);
|
|
128
|
-
setTimeRemaining('');
|
|
129
|
-
}
|
|
145
|
+
updateIDVSuggestionState(dismissed);
|
|
130
146
|
}
|
|
131
147
|
else {
|
|
132
148
|
setShowIDVSuggestion(false);
|
|
@@ -134,7 +150,14 @@ export const ChatBotUI = () => {
|
|
|
134
150
|
setTimeRemaining('');
|
|
135
151
|
}
|
|
136
152
|
}, 1000);
|
|
137
|
-
return () =>
|
|
153
|
+
return () => {
|
|
154
|
+
clearTimeout(timer);
|
|
155
|
+
// Clear countdown interval on cleanup
|
|
156
|
+
if (countdownIntervalRef.current) {
|
|
157
|
+
clearInterval(countdownIntervalRef.current);
|
|
158
|
+
countdownIntervalRef.current = null;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
138
161
|
}
|
|
139
162
|
else {
|
|
140
163
|
// Don't show when:
|
|
@@ -144,13 +167,39 @@ export const ChatBotUI = () => {
|
|
|
144
167
|
setDismissUntil(null);
|
|
145
168
|
setTimeRemaining('');
|
|
146
169
|
}
|
|
147
|
-
}, [hitAddress, walletInfo, isNeedSignInWithWallet, props.requireWalletIDVVerification]);
|
|
170
|
+
}, [hitAddress, walletInfo, isNeedSignInWithWallet, props.requireWalletIDVVerification, updateIDVSuggestionState]);
|
|
148
171
|
const handleDismissIDV = () => {
|
|
149
172
|
const dismissSeconds = props.idvBannerDismissSeconds || 86400;
|
|
150
173
|
const dismissTime = Date.now() + (dismissSeconds * 1000);
|
|
151
174
|
localStorage.setItem('idv-suggestion-dismissed', dismissTime.toString());
|
|
152
175
|
setShowIDVSuggestion(false);
|
|
153
176
|
setDismissUntil(dismissTime);
|
|
177
|
+
// Calculate and set initial time remaining
|
|
178
|
+
const initialHours = Math.floor(dismissSeconds / 3600);
|
|
179
|
+
const initialMinutes = Math.floor((dismissSeconds % 3600) / 60);
|
|
180
|
+
setTimeRemaining(`${initialHours}h ${initialMinutes}m`);
|
|
181
|
+
// Set up countdown interval
|
|
182
|
+
if (countdownIntervalRef.current) {
|
|
183
|
+
clearInterval(countdownIntervalRef.current);
|
|
184
|
+
}
|
|
185
|
+
countdownIntervalRef.current = setInterval(() => {
|
|
186
|
+
const remaining = dismissTime - Date.now();
|
|
187
|
+
if (remaining > 0) {
|
|
188
|
+
const remainingHours = Math.floor(remaining / (1000 * 60 * 60));
|
|
189
|
+
const remainingMinutes = Math.floor((remaining % (1000 * 60 * 60)) / (1000 * 60));
|
|
190
|
+
setTimeRemaining(`${remainingHours}h ${remainingMinutes}m`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
setShowIDVSuggestion(true);
|
|
194
|
+
setDismissUntil(null);
|
|
195
|
+
setTimeRemaining('');
|
|
196
|
+
localStorage.removeItem('idv-suggestion-dismissed');
|
|
197
|
+
if (countdownIntervalRef.current) {
|
|
198
|
+
clearInterval(countdownIntervalRef.current);
|
|
199
|
+
countdownIntervalRef.current = null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}, 60000);
|
|
154
203
|
const hours = Math.floor(dismissSeconds / 3600);
|
|
155
204
|
const minutes = Math.floor((dismissSeconds % 3600) / 60);
|
|
156
205
|
const timeText = hours > 0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../../src/components/ui/MessageInput.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../../src/components/ui/MessageInput.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EA6ehC,CAAC"}
|