@bytexbyte/nxtlinq-ai-agent-sdk 1.2.2 → 1.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.
Files changed (48) hide show
  1. package/README.md +282 -200
  2. package/dist/api/nxtlinq-api.d.ts.map +1 -1
  3. package/dist/api/nxtlinq-api.js +127 -142
  4. package/dist/components/ChatBot.d.ts +2 -44
  5. package/dist/components/ChatBot.d.ts.map +1 -1
  6. package/dist/components/ChatBot.js +5 -1241
  7. package/dist/components/context/ChatBotContext.d.ts +5 -0
  8. package/dist/components/context/ChatBotContext.d.ts.map +1 -0
  9. package/dist/components/context/ChatBotContext.js +865 -0
  10. package/dist/components/types/ChatBotTypes.d.ts +115 -0
  11. package/dist/components/types/ChatBotTypes.d.ts.map +1 -0
  12. package/dist/components/types/ChatBotTypes.js +14 -0
  13. package/dist/components/ui/ChatBotUI.d.ts +3 -0
  14. package/dist/components/ui/ChatBotUI.d.ts.map +1 -0
  15. package/dist/components/ui/ChatBotUI.js +147 -0
  16. package/dist/components/ui/MessageInput.d.ts +3 -0
  17. package/dist/components/ui/MessageInput.d.ts.map +1 -0
  18. package/dist/components/ui/MessageInput.js +46 -0
  19. package/dist/components/ui/MessageList.d.ts +3 -0
  20. package/dist/components/ui/MessageList.d.ts.map +1 -0
  21. package/dist/components/ui/MessageList.js +84 -0
  22. package/dist/components/ui/ModelSelector.d.ts +3 -0
  23. package/dist/components/ui/ModelSelector.d.ts.map +1 -0
  24. package/dist/components/ui/ModelSelector.js +65 -0
  25. package/dist/components/ui/NotificationModal.d.ts +14 -0
  26. package/dist/components/ui/NotificationModal.d.ts.map +1 -0
  27. package/dist/components/ui/NotificationModal.js +79 -0
  28. package/dist/components/ui/PermissionForm.d.ts +8 -0
  29. package/dist/components/ui/PermissionForm.d.ts.map +1 -0
  30. package/dist/components/ui/PermissionForm.js +299 -0
  31. package/dist/components/ui/PresetMessages.d.ts +3 -0
  32. package/dist/components/ui/PresetMessages.d.ts.map +1 -0
  33. package/dist/components/ui/PresetMessages.js +35 -0
  34. package/dist/core/utils/aitUtils.d.ts +28 -0
  35. package/dist/core/utils/aitUtils.d.ts.map +1 -0
  36. package/dist/core/utils/aitUtils.js +34 -0
  37. package/dist/core/utils/notificationUtils.d.ts +29 -0
  38. package/dist/core/utils/notificationUtils.d.ts.map +1 -0
  39. package/dist/core/utils/notificationUtils.js +47 -0
  40. package/dist/core/utils/walletUtils.d.ts +10 -0
  41. package/dist/core/utils/walletUtils.d.ts.map +1 -0
  42. package/dist/core/utils/walletUtils.js +38 -0
  43. package/dist/index.d.ts +14 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +18 -0
  46. package/dist/types/ait-api.d.ts +32 -1
  47. package/dist/types/ait-api.d.ts.map +1 -1
  48. package/package.json +1 -1
@@ -1,1242 +1,6 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import * as React from 'react';
3
- import { ethers } from 'ethers';
4
- import { createNxtlinqApi } from '../api/nxtlinq-api';
5
- import stringify from 'fast-json-stable-stringify';
6
- import metakeepClient from '../core/metakeepClient';
7
- import useLocalStorage from '../core/lib/useLocalStorage';
8
- const NotificationModal = ({ notification, onClose }) => {
9
- const getStyles = () => {
10
- const baseStyles = {
11
- position: 'fixed',
12
- bottom: 20,
13
- right: 20,
14
- padding: '12px 24px',
15
- borderRadius: 8,
16
- zIndex: 2000,
17
- fontWeight: 600,
18
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
19
- transition: 'all 0.3s ease',
20
- display: 'flex',
21
- alignItems: 'center',
22
- gap: '12px',
23
- minWidth: '300px',
24
- maxWidth: '500px'
25
- };
26
- switch (notification.type) {
27
- case 'success':
28
- return { ...baseStyles, background: '#4caf50', color: 'white' };
29
- case 'error':
30
- return { ...baseStyles, background: '#f44336', color: 'white' };
31
- case 'warning':
32
- return { ...baseStyles, background: '#ff9800', color: 'white' };
33
- default:
34
- return { ...baseStyles, background: '#2196f3', color: 'white' };
35
- }
36
- };
37
- const getIcon = () => {
38
- switch (notification.type) {
39
- case 'success':
40
- return '✅';
41
- case 'error':
42
- return '❌';
43
- case 'warning':
44
- return '⚠️';
45
- default:
46
- return 'ℹ️';
47
- }
48
- };
49
- return (notification.show && (_jsxs("div", { style: getStyles(), children: [_jsx("span", { style: { fontSize: '18px' }, children: getIcon() }), _jsx("span", { style: { flex: 1 }, children: notification.message }), _jsx("button", { onClick: onClose, style: {
50
- background: 'none',
51
- border: 'none',
52
- color: 'white',
53
- fontSize: '18px',
54
- cursor: 'pointer',
55
- padding: '4px',
56
- display: 'flex',
57
- alignItems: 'center',
58
- justifyContent: 'center',
59
- borderRadius: '4px',
60
- transition: 'background-color 0.2s'
61
- }, onMouseOver: (e) => e.currentTarget.style.backgroundColor = 'rgba(255, 255, 255, 0.2)', onMouseOut: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "\u00D7" })] })));
62
- };
63
- const PermissionForm = ({ hitAddress, permissions, setPermissions, setIsDisabled, onClose, onSave, onConnectWallet, onSignIn, isNeedSignInWithWallet, walletInfo, onVerifyWallet, serviceId, nxtlinqApi, permissionGroup, isAITLoading, isWalletLoading = false }) => {
64
- const [availablePermissions, setAvailablePermissions] = React.useState([]);
65
- const [isSaving, setIsSaving] = React.useState(false);
66
- const fetchAvailablePermissions = async () => {
67
- if (!serviceId)
68
- return;
69
- try {
70
- const result = await nxtlinqApi.permissions.getServicePermissions({
71
- serviceId,
72
- ...(permissionGroup && { groupName: permissionGroup })
73
- });
74
- if ('error' in result) {
75
- console.error('Failed to fetch permissions:', result.error);
76
- return;
77
- }
78
- setAvailablePermissions(result.permissions);
79
- }
80
- catch (error) {
81
- console.error('Error fetching permissions:', error);
82
- }
83
- };
84
- React.useEffect(() => {
85
- fetchAvailablePermissions();
86
- }, [serviceId, nxtlinqApi, permissionGroup]);
87
- const isWalletVerified = Boolean(walletInfo?.id);
88
- const handleSave = async () => {
89
- setIsSaving(true);
90
- try {
91
- await onSave();
92
- }
93
- finally {
94
- setIsSaving(false);
95
- }
96
- };
97
- // Show loading state while checking wallet status
98
- if (isWalletLoading) {
99
- return (_jsxs("div", { style: {
100
- backgroundColor: 'white',
101
- padding: '24px',
102
- borderRadius: '12px',
103
- width: '480px',
104
- maxWidth: '90%',
105
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
106
- }, children: [_jsxs("div", { style: {
107
- display: 'flex',
108
- justifyContent: 'space-between',
109
- alignItems: 'center',
110
- marginBottom: '24px'
111
- }, children: [_jsx("h3", { style: {
112
- margin: 0,
113
- fontSize: '20px',
114
- fontWeight: '600',
115
- color: '#1a1a1a'
116
- }, children: "AIT Settings" }), _jsx("button", { onClick: onClose, style: {
117
- background: 'none',
118
- border: 'none',
119
- fontSize: '24px',
120
- cursor: 'pointer',
121
- color: '#666',
122
- padding: '4px',
123
- display: 'flex',
124
- alignItems: 'center',
125
- justifyContent: 'center'
126
- }, children: "\u00D7" })] }), _jsxs("div", { style: { textAlign: 'center', padding: '32px 0' }, children: [_jsx("div", { style: {
127
- width: '64px',
128
- height: '64px',
129
- margin: '0 auto 16px',
130
- backgroundColor: '#f5f5f5',
131
- borderRadius: '50%',
132
- display: 'flex',
133
- alignItems: 'center',
134
- justifyContent: 'center'
135
- }, children: _jsx("div", { style: {
136
- width: '32px',
137
- height: '32px',
138
- border: '3px solid #e3e3e3',
139
- borderTop: '3px solid #007bff',
140
- borderRadius: '50%',
141
- animation: 'spin 1s linear infinite'
142
- } }) }), _jsx("p", { style: {
143
- marginBottom: '24px',
144
- fontSize: '16px',
145
- color: '#666'
146
- }, children: "Checking wallet status..." })] }), _jsx("style", { children: `
147
- @keyframes spin {
148
- 0% { transform: rotate(0deg); }
149
- 100% { transform: rotate(360deg); }
150
- }
151
- ` })] }));
152
- }
153
- return (_jsxs("div", { style: {
154
- backgroundColor: 'white',
155
- padding: '24px',
156
- borderRadius: '12px',
157
- width: '480px',
158
- maxWidth: '90%',
159
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
160
- }, children: [_jsxs("div", { style: {
161
- display: 'flex',
162
- justifyContent: 'space-between',
163
- alignItems: 'center',
164
- marginBottom: '24px'
165
- }, children: [_jsx("h3", { style: {
166
- margin: 0,
167
- fontSize: '20px',
168
- fontWeight: '600',
169
- color: '#1a1a1a'
170
- }, children: "AIT Settings" }), _jsx("button", { onClick: onClose, style: {
171
- background: 'none',
172
- border: 'none',
173
- fontSize: '24px',
174
- cursor: 'pointer',
175
- color: '#666',
176
- padding: '4px',
177
- display: 'flex',
178
- alignItems: 'center',
179
- justifyContent: 'center'
180
- }, children: "\u00D7" })] }), !hitAddress ? (_jsxs("div", { style: { textAlign: 'center', padding: '32px 0' }, children: [_jsx("div", { style: {
181
- width: '64px',
182
- height: '64px',
183
- margin: '0 auto 16px',
184
- backgroundColor: '#f5f5f5',
185
- borderRadius: '50%',
186
- display: 'flex',
187
- alignItems: 'center',
188
- justifyContent: 'center'
189
- }, children: _jsx("span", { style: { fontSize: '32px' }, children: "\uD83D\uDC5B" }) }), _jsx("p", { style: {
190
- marginBottom: '24px',
191
- fontSize: '16px',
192
- color: '#666'
193
- }, children: "Please connect your wallet first" }), _jsx("button", { onClick: onConnectWallet, style: {
194
- padding: '12px 24px',
195
- backgroundColor: '#007bff',
196
- color: 'white',
197
- border: 'none',
198
- borderRadius: '8px',
199
- cursor: 'pointer',
200
- fontSize: '16px',
201
- fontWeight: '500',
202
- transition: 'background-color 0.2s'
203
- }, onMouseOver: (e) => e.currentTarget.style.backgroundColor = '#0056b3', onMouseOut: (e) => e.currentTarget.style.backgroundColor = '#007bff', children: "Connect Wallet" })] })) : isNeedSignInWithWallet ? (_jsxs("div", { style: { textAlign: 'center', padding: '32px 0' }, children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: {
204
- marginBottom: '12px',
205
- fontSize: '16px',
206
- color: '#666'
207
- }, children: "Connected Wallet" }), _jsx("p", { style: {
208
- wordBreak: 'break-all',
209
- backgroundColor: '#f8f9fa',
210
- padding: '12px',
211
- borderRadius: '8px',
212
- fontSize: '14px',
213
- color: '#333',
214
- border: '1px solid #e9ecef'
215
- }, children: hitAddress })] }), _jsx("p", { style: {
216
- marginBottom: '24px',
217
- fontSize: '16px',
218
- color: '#666'
219
- }, children: "Please sign in to continue" }), _jsx("button", { onClick: onSignIn, style: {
220
- padding: '12px 24px',
221
- backgroundColor: '#007bff',
222
- color: 'white',
223
- border: 'none',
224
- borderRadius: '8px',
225
- cursor: 'pointer',
226
- fontSize: '16px',
227
- fontWeight: '500',
228
- transition: 'background-color 0.2s'
229
- }, onMouseOver: (e) => e.currentTarget.style.backgroundColor = '#0056b3', onMouseOut: (e) => e.currentTarget.style.backgroundColor = '#007bff', children: "Sign In" })] })) : !isWalletVerified ? (_jsxs("div", { style: { textAlign: 'center', padding: '32px 0' }, children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: {
230
- marginBottom: '12px',
231
- fontSize: '16px',
232
- color: '#666'
233
- }, children: "Connected Wallet" }), _jsx("p", { style: {
234
- wordBreak: 'break-all',
235
- backgroundColor: '#f8f9fa',
236
- padding: '12px',
237
- borderRadius: '8px',
238
- fontSize: '14px',
239
- color: '#333',
240
- border: '1px solid #e9ecef'
241
- }, children: hitAddress })] }), _jsx("p", { style: {
242
- marginBottom: '24px',
243
- fontSize: '16px',
244
- color: '#666'
245
- }, children: "Please verify your wallet to continue" }), _jsx("button", { onClick: onVerifyWallet, style: {
246
- padding: '12px 24px',
247
- backgroundColor: '#007bff',
248
- color: 'white',
249
- border: 'none',
250
- borderRadius: '8px',
251
- cursor: 'pointer',
252
- fontSize: '16px',
253
- fontWeight: '500',
254
- transition: 'background-color 0.2s'
255
- }, onMouseOver: (e) => e.currentTarget.style.backgroundColor = '#0056b3', onMouseOut: (e) => e.currentTarget.style.backgroundColor = '#007bff', children: "Verify your wallet" })] })) : (_jsxs(_Fragment, { children: [_jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: {
256
- marginBottom: '12px',
257
- fontSize: '16px',
258
- color: '#666'
259
- }, children: "Connected Wallet" }), _jsx("p", { style: {
260
- wordBreak: 'break-all',
261
- backgroundColor: '#f8f9fa',
262
- padding: '12px',
263
- borderRadius: '8px',
264
- fontSize: '14px',
265
- color: '#333',
266
- border: '1px solid #e9ecef'
267
- }, children: hitAddress })] }), _jsxs("div", { style: { marginBottom: '24px' }, children: [_jsx("h4", { style: {
268
- marginBottom: '12px',
269
- fontSize: '16px',
270
- color: '#666'
271
- }, children: "Permissions" }), isAITLoading ? (_jsx("div", { style: {
272
- backgroundColor: '#f8f9fa',
273
- padding: '16px',
274
- borderRadius: '8px',
275
- border: '1px solid #e9ecef',
276
- textAlign: 'center',
277
- color: '#666'
278
- }, children: "Loading permissions..." })) : (_jsx("div", { style: {
279
- backgroundColor: '#f8f9fa',
280
- padding: '16px',
281
- borderRadius: '8px',
282
- border: '1px solid #e9ecef'
283
- }, children: availablePermissions.map((permission) => (_jsx("div", { style: { marginBottom: '12px' }, children: _jsxs("label", { style: {
284
- display: 'flex',
285
- alignItems: 'center',
286
- gap: '12px',
287
- cursor: isAITLoading ? 'not-allowed' : 'pointer',
288
- padding: '8px',
289
- borderRadius: '6px',
290
- transition: 'background-color 0.2s',
291
- opacity: isAITLoading ? 0.6 : 1
292
- }, onMouseOver: (e) => {
293
- if (!isAITLoading) {
294
- e.currentTarget.style.backgroundColor = '#e9ecef';
295
- }
296
- }, onMouseOut: (e) => {
297
- if (!isAITLoading) {
298
- e.currentTarget.style.backgroundColor = 'transparent';
299
- }
300
- }, children: [_jsx("input", { type: "checkbox", checked: permissions.includes(permission.label), onChange: () => {
301
- if (!isAITLoading) {
302
- const newPermissions = permissions.includes(permission.label)
303
- ? permissions.filter(p => p !== permission.label)
304
- : [...permissions, permission.label].sort();
305
- setPermissions(newPermissions);
306
- setIsDisabled(false);
307
- }
308
- }, disabled: isAITLoading, style: {
309
- margin: 0,
310
- width: '18px',
311
- height: '18px',
312
- cursor: isAITLoading ? 'not-allowed' : 'pointer'
313
- } }), _jsx("span", { style: {
314
- fontSize: '14px',
315
- color: '#333'
316
- }, children: permission.label })] }) }, permission.id))) }))] }), _jsxs("div", { style: {
317
- display: 'flex',
318
- justifyContent: 'flex-end',
319
- gap: '12px',
320
- borderTop: '1px solid #e9ecef',
321
- paddingTop: '24px'
322
- }, children: [_jsx("button", { onClick: onClose, style: {
323
- padding: '10px 20px',
324
- backgroundColor: '#f8f9fa',
325
- color: '#666',
326
- border: '1px solid #dee2e6',
327
- borderRadius: '8px',
328
- cursor: 'pointer',
329
- fontSize: '14px',
330
- fontWeight: '500',
331
- transition: 'all 0.2s'
332
- }, onMouseOver: (e) => {
333
- e.currentTarget.style.backgroundColor = '#e9ecef';
334
- e.currentTarget.style.borderColor = '#ced4da';
335
- }, onMouseOut: (e) => {
336
- e.currentTarget.style.backgroundColor = '#f8f9fa';
337
- e.currentTarget.style.borderColor = '#dee2e6';
338
- }, children: "Cancel" }), _jsx("button", { onClick: handleSave, disabled: permissions.length === 0 || isSaving || isAITLoading, style: {
339
- padding: '10px 20px',
340
- backgroundColor: permissions.length === 0 || isSaving || isAITLoading ? '#e9ecef' : '#007bff',
341
- color: permissions.length === 0 || isSaving || isAITLoading ? '#6c757d' : 'white',
342
- border: 'none',
343
- borderRadius: '8px',
344
- cursor: permissions.length === 0 || isSaving || isAITLoading ? 'not-allowed' : 'pointer',
345
- fontSize: '14px',
346
- fontWeight: '500',
347
- transition: 'background-color 0.2s'
348
- }, onMouseOver: (e) => {
349
- if (permissions.length > 0 && !isSaving && !isAITLoading) {
350
- e.currentTarget.style.backgroundColor = '#0056b3';
351
- }
352
- }, onMouseOut: (e) => {
353
- if (permissions.length > 0 && !isSaving && !isAITLoading) {
354
- e.currentTarget.style.backgroundColor = '#007bff';
355
- }
356
- }, children: isSaving ? 'Saving...' : 'Save' })] })] }))] }));
357
- };
358
- export const ChatBot = ({ onMessage, onError, onToolUse, presetMessages = [], placeholder = 'Type a message...', className = '', maxRetries = 3, retryDelay = 1000, serviceId, apiKey, apiSecret, onVerifyWallet, permissionGroup }) => {
359
- const [messages, setMessages] = React.useState([]);
360
- const [inputValue, setInputValue] = React.useState('');
361
- const [isLoading, setIsLoading] = React.useState(false);
362
- const [isOpen, setIsOpen] = React.useState(false);
363
- const [hitAddress, setHitAddress] = React.useState(null);
364
- const [ait, setAit] = React.useState(null);
365
- const [permissions, setPermissions] = React.useState([]);
366
- const [availablePermissions, setAvailablePermissions] = React.useState([]);
367
- const [showPermissionForm, setShowPermissionForm] = React.useState(false);
368
- const [isPermissionFormOpen, setIsPermissionFormOpen] = React.useState(false);
369
- const [isAITLoading, setIsAITLoading] = React.useState(false);
370
- const messagesEndRef = React.useRef(null);
371
- const [isDisabled, setIsDisabled] = React.useState(true);
372
- const [signer, setSigner] = React.useState(null);
373
- const [walletInfo, setWalletInfo] = React.useState(null);
374
- const verifyWalletBtnRef = React.useRef(null);
375
- const [nxtlinqAITServiceAccessToken, setNxtlinqAITServiceAccessToken] = useLocalStorage('nxtlinqAITServiceAccessToken', '');
376
- const [isWalletLoading, setIsWalletLoading] = React.useState(false);
377
- const [notification, setNotification] = React.useState({
378
- show: false,
379
- type: 'info',
380
- message: '',
381
- autoHide: true,
382
- duration: 5000
383
- });
384
- const nxtlinqApi = React.useMemo(() => createNxtlinqApi(apiKey, apiSecret), [apiKey, apiSecret]);
385
- // Unified notification functions
386
- const showNotification = (type, message, duration = 5000) => {
387
- setNotification({
388
- show: true,
389
- type,
390
- message,
391
- autoHide: true,
392
- duration
393
- });
394
- // Auto-hide
395
- if (duration > 0) {
396
- setTimeout(() => {
397
- setNotification(prev => ({ ...prev, show: false }));
398
- }, duration);
399
- }
400
- };
401
- const showSuccess = (message) => showNotification('success', message, 3000);
402
- const showError = (message) => showNotification('error', message, 5000);
403
- const showWarning = (message) => showNotification('warning', message, 4000);
404
- const showInfo = (message) => showNotification('info', message, 3000);
405
- const fetchAvailablePermissions = async () => {
406
- if (!serviceId)
407
- return;
408
- try {
409
- const result = await nxtlinqApi.permissions.getServicePermissions({
410
- serviceId,
411
- ...(permissionGroup && { groupName: permissionGroup })
412
- });
413
- if ('error' in result) {
414
- console.error('Failed to fetch permissions:', result.error);
415
- return;
416
- }
417
- setAvailablePermissions(result.permissions);
418
- }
419
- catch (error) {
420
- console.error('Error fetching permissions:', error);
421
- }
422
- };
423
- const refreshAIT = async (forceUpdatePermissions = false) => {
424
- console.log('refreshAIT called');
425
- console.log('hitAddress:', hitAddress);
426
- console.log('nxtlinqAITServiceAccessToken:', nxtlinqAITServiceAccessToken);
427
- if (!hitAddress) {
428
- setAit(null);
429
- setPermissions([]);
430
- return;
431
- }
432
- setIsAITLoading(true);
433
- try {
434
- const response = await nxtlinqApi.ait.getAITByServiceIdAndController({
435
- serviceId,
436
- controller: hitAddress
437
- }, nxtlinqAITServiceAccessToken || '');
438
- if ('error' in response) {
439
- console.error('Failed to fetch AIT:', response.error);
440
- setAit(null);
441
- setPermissions([]);
442
- return;
443
- }
444
- console.log('AIT response:', response);
445
- setAit(response);
446
- // Update permissions if form is not open OR if force update is requested
447
- if (!isPermissionFormOpen || forceUpdatePermissions) {
448
- setPermissions(response.metadata?.permissions || []);
449
- }
450
- }
451
- catch (error) {
452
- console.error('Failed to fetch AIT:', error);
453
- setAit(null);
454
- setPermissions([]);
455
- }
456
- finally {
457
- setIsAITLoading(false);
458
- }
459
- };
460
- React.useEffect(() => {
461
- console.log('hitAddress:', hitAddress);
462
- console.log('nxtlinqAITServiceAccessToken:', nxtlinqAITServiceAccessToken);
463
- if (hitAddress && nxtlinqAITServiceAccessToken) {
464
- refreshAIT();
465
- }
466
- }, [hitAddress, nxtlinqAITServiceAccessToken]);
467
- // Fetch available permissions when permissionGroup changes
468
- React.useEffect(() => {
469
- fetchAvailablePermissions();
470
- }, [serviceId, permissionGroup]);
471
- const isNeedSignInWithWallet = React.useMemo(() => {
472
- if (!hitAddress) {
473
- return false;
474
- }
475
- if (!nxtlinqAITServiceAccessToken) {
476
- return true;
477
- }
478
- try {
479
- // Check if the token is expired
480
- const payload = JSON.parse(atob(nxtlinqAITServiceAccessToken.split('.')[1]));
481
- const exp = payload.exp * 1000; // Convert to milliseconds
482
- const now = Date.now();
483
- if (exp < now) {
484
- return true;
485
- }
486
- // Check if the token's payload has the same address as the wallet address
487
- const address = payload.address;
488
- if (address !== hitAddress) {
489
- return true;
490
- }
491
- // If user has valid token but no AIT, they don't need to sign in again
492
- // They just need to generate AIT through the permission form
493
- return false;
494
- }
495
- catch (error) {
496
- console.error('Error parsing token:', error);
497
- return true;
498
- }
499
- }, [hitAddress, nxtlinqAITServiceAccessToken]);
500
- const handleVerifySuccess = (address) => {
501
- localStorage.setItem(`wallet_verified_${address}`, 'true');
502
- const getWalletInfo = async () => {
503
- setIsWalletLoading(true);
504
- try {
505
- const token = JSON.parse(localStorage.getItem('nxtlinqAITServiceAccessToken') || '');
506
- const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
507
- console.log('Wallet response:', walletResponse);
508
- if (!('error' in walletResponse)) {
509
- setWalletInfo(walletResponse);
510
- const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
511
- serviceId,
512
- controller: address
513
- }, token);
514
- console.log('AIT response:', aitResponse);
515
- if (!('error' in aitResponse)) {
516
- setAit(aitResponse);
517
- }
518
- }
519
- }
520
- catch (error) {
521
- console.error('Failed to update wallet info after verification:', error);
522
- }
523
- finally {
524
- setIsWalletLoading(false);
525
- }
526
- };
527
- getWalletInfo();
528
- };
529
- React.useEffect(() => {
530
- const getWalletInfo = async () => {
531
- if (!hitAddress) {
532
- return;
533
- }
534
- if (isNeedSignInWithWallet) {
535
- return;
536
- }
537
- setIsWalletLoading(true);
538
- try {
539
- const getWalletResponse = await nxtlinqApi.wallet.getWallet({ address: hitAddress }, nxtlinqAITServiceAccessToken);
540
- if ('error' in getWalletResponse) {
541
- if (getWalletResponse.error === 'Wallet not found') {
542
- console.log('Wallet not found - this is expected for new users');
543
- return;
544
- }
545
- console.error(getWalletResponse.error);
546
- return;
547
- }
548
- setWalletInfo(getWalletResponse);
549
- }
550
- catch (error) {
551
- console.error('Error getting wallet info:', error);
552
- }
553
- finally {
554
- setIsWalletLoading(false);
555
- }
556
- };
557
- getWalletInfo();
558
- }, [hitAddress, isNeedSignInWithWallet]);
559
- const handleVerifyWalletClick = async () => {
560
- console.log('handleVerifyWalletClick called');
561
- console.log('Current states:', {
562
- hitAddress,
563
- isNeedSignInWithWallet,
564
- walletInfo,
565
- signer: !!signer
566
- });
567
- if (!hitAddress) {
568
- showError('Please connect your wallet first.');
569
- return;
570
- }
571
- try {
572
- if (onVerifyWallet) {
573
- setIsLoading(true);
574
- const result = await onVerifyWallet();
575
- console.log('Verify wallet response:', result);
576
- if (!result) {
577
- setIsLoading(false);
578
- return;
579
- }
580
- const { token } = result;
581
- const address = hitAddress;
582
- if (token && address) {
583
- const payload = {
584
- address: hitAddress,
585
- token,
586
- timestamp: Date.now(),
587
- method: 'berifyme'
588
- };
589
- try {
590
- const verifyWalletResponse = await nxtlinqApi.wallet.verifyWallet({ ...payload }, token);
591
- if ('error' in verifyWalletResponse) {
592
- if (verifyWalletResponse.error === 'Wallet already exists') {
593
- // If wallet exists, get wallet info directly
594
- setIsWalletLoading(true);
595
- try {
596
- const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
597
- if (!('error' in walletResponse)) {
598
- setWalletInfo(walletResponse);
599
- const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({ serviceId, controller: address }, token);
600
- if (!('error' in aitResponse)) {
601
- setAit(aitResponse);
602
- }
603
- }
604
- }
605
- finally {
606
- setIsWalletLoading(false);
607
- }
608
- // Clean up URL parameters after wallet verification
609
- if (typeof window !== 'undefined') {
610
- try {
611
- const url = new URL(window.location.href);
612
- // Clean up all Berify.me related parameters
613
- url.searchParams.delete('token');
614
- url.searchParams.delete('isAutoConnect');
615
- url.searchParams.delete('method');
616
- url.searchParams.delete('returnUrl');
617
- window.history.replaceState({}, '', url.toString());
618
- }
619
- catch (e) {
620
- console.error('Failed to clean URL:', e);
621
- }
622
- }
623
- setIsLoading(false);
624
- // Use Modal notification instead of ChatBot message
625
- showSuccess('Wallet verification completed successfully! Your wallet is now verified and ready to use.');
626
- // Refresh AIT after wallet verification
627
- refreshAIT();
628
- return { token, hitAddress: address };
629
- }
630
- showError(verifyWalletResponse.error);
631
- setIsLoading(false);
632
- return;
633
- }
634
- // Verification successful, get wallet info
635
- setIsWalletLoading(true);
636
- try {
637
- const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
638
- if (!('error' in walletResponse)) {
639
- setWalletInfo(walletResponse);
640
- const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({ serviceId, controller: address }, token);
641
- if (!('error' in aitResponse)) {
642
- setAit(aitResponse);
643
- }
644
- }
645
- }
646
- finally {
647
- setIsWalletLoading(false);
648
- }
649
- // Clean up URL parameters after wallet verification
650
- if (typeof window !== 'undefined') {
651
- try {
652
- const url = new URL(window.location.href);
653
- // Clean up all Berify.me related parameters
654
- url.searchParams.delete('token');
655
- url.searchParams.delete('isAutoConnect');
656
- url.searchParams.delete('method');
657
- url.searchParams.delete('returnUrl');
658
- window.history.replaceState({}, '', url.toString());
659
- }
660
- catch (e) {
661
- console.error('Failed to clean URL:', e);
662
- }
663
- }
664
- setIsLoading(false);
665
- // Use Modal notification instead of ChatBot message
666
- showSuccess('Wallet verification completed successfully! Your wallet is now verified and ready to use.');
667
- // Refresh AIT after wallet verification
668
- refreshAIT();
669
- return { token, hitAddress: address };
670
- }
671
- catch (error) {
672
- let msg = 'Verification failed';
673
- if (typeof error === 'object' && error !== null && 'response' in error) {
674
- // @ts-ignore
675
- msg = error.response?.data?.error || error.message || msg;
676
- }
677
- else if (error instanceof Error) {
678
- msg = error.message;
679
- }
680
- console.error('Wallet verification failed:', error);
681
- showError(msg);
682
- setIsLoading(false);
683
- throw error;
684
- }
685
- }
686
- setIsLoading(false);
687
- return { token, hitAddress: address };
688
- }
689
- }
690
- catch (error) {
691
- console.error('Failed to verify wallet:', error);
692
- setIsLoading(false);
693
- showError('Failed to verify wallet. Please try again.');
694
- throw error;
695
- }
696
- };
697
- // Add useEffect to handle URL parameters
698
- React.useEffect(() => {
699
- if (typeof window !== 'undefined') {
700
- try {
701
- const urlParams = new URLSearchParams(window.location.search);
702
- const token = urlParams.get('token');
703
- if (token && hitAddress) {
704
- handleVerifyWalletClick();
705
- }
706
- }
707
- catch (e) {
708
- console.error('Failed to get URL params:', e);
709
- }
710
- }
711
- }, [hitAddress]);
712
- React.useEffect(() => {
713
- console.log('Wallet states changed:', {
714
- hitAddress,
715
- isNeedSignInWithWallet,
716
- walletInfo,
717
- signer: !!signer
718
- });
719
- }, [hitAddress, isNeedSignInWithWallet, walletInfo, signer]);
720
- const scrollToBottom = () => {
721
- messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
722
- };
723
- React.useEffect(() => {
724
- scrollToBottom();
725
- }, [messages]);
726
- React.useEffect(() => {
727
- if (!hitAddress) {
728
- setAit(null);
729
- }
730
- }, [hitAddress]);
731
- React.useEffect(() => {
732
- if (!ait) {
733
- return;
734
- }
735
- const aitPermissions = ait.metadata?.permissions || [];
736
- setPermissions(aitPermissions);
737
- }, [ait]);
738
- const connectWallet = React.useCallback(async (autoShowSignInMessage = true) => {
739
- if (typeof window === 'undefined') {
740
- console.error('Web3 is not available in server-side rendering');
741
- return;
742
- }
743
- try {
744
- const web3Provider = await metakeepClient.ethereum;
745
- if (!web3Provider) {
746
- throw new Error('Web3 provider not available');
747
- }
748
- await web3Provider.enable();
749
- const ethersProvider = new ethers.providers.Web3Provider(web3Provider);
750
- const userSigner = await ethersProvider.getSigner();
751
- const userAddress = await userSigner.getAddress();
752
- localStorage.setItem('walletAddress', userAddress);
753
- setHitAddress(userAddress);
754
- setSigner(userSigner);
755
- // Refresh AIT after connecting wallet and wait for completion
756
- if (nxtlinqAITServiceAccessToken) {
757
- await refreshAIT();
758
- }
759
- // Auto-show appropriate message after connecting wallet and AIT refresh
760
- if (autoShowSignInMessage) {
761
- // Check state after refreshAIT has completed
762
- if (isNeedSignInWithWallet) {
763
- // User needs to sign in
764
- setMessages(prev => [...prev, {
765
- id: Date.now().toString(),
766
- content: 'Please sign in with your wallet to continue.',
767
- role: 'assistant',
768
- timestamp: new Date().toISOString(),
769
- button: 'signIn'
770
- }]);
771
- }
772
- else {
773
- // User is already signed in
774
- showSuccess('Successfully connected your HIT wallet. You are already signed in and can use the AI agent.');
775
- }
776
- }
777
- return userAddress;
778
- }
779
- catch (error) {
780
- console.error('Failed to connect wallet:', error);
781
- localStorage.removeItem('walletAddress');
782
- setHitAddress(null);
783
- setSigner(null);
784
- throw error;
785
- }
786
- }, [nxtlinqAITServiceAccessToken, refreshAIT, isNeedSignInWithWallet]);
787
- const signInWallet = async (autoShowSuccessMessage = true) => {
788
- if (!hitAddress) {
789
- showError('Please connect your wallet first.');
790
- return;
791
- }
792
- if (!signer) {
793
- showError('Please connect your wallet first.');
794
- return;
795
- }
796
- try {
797
- const nonceResponse = await nxtlinqApi.auth.getNonce({ address: hitAddress });
798
- if ('error' in nonceResponse) {
799
- showError(nonceResponse.error);
800
- return;
801
- }
802
- const payload = {
803
- address: hitAddress,
804
- code: nonceResponse.code,
805
- timestamp: nonceResponse.timestamp
806
- };
807
- const stringToSign = stringify(payload);
808
- const signature = await signer.signMessage(stringToSign || '');
809
- const response = await nxtlinqApi.auth.signIn({
810
- ...payload,
811
- signature
812
- });
813
- if ('error' in response) {
814
- showError(response.error);
815
- return;
816
- }
817
- const { accessToken } = response;
818
- setNxtlinqAITServiceAccessToken(accessToken);
819
- // Auto-show connected message after signing in
820
- if (autoShowSuccessMessage) {
821
- showSuccess('Successfully signed in with your HIT wallet. You can now use the AI agent.');
822
- }
823
- // Refresh AIT after signing in
824
- refreshAIT();
825
- }
826
- catch (error) {
827
- console.error('Failed to sign in:', error);
828
- showError('Failed to sign in. Please try again.');
829
- }
830
- };
831
- const hasPermission = async (toolName) => {
832
- if (!hitAddress) {
833
- setMessages(prev => [...prev, {
834
- id: Date.now().toString(),
835
- content: 'Please connect your HIT wallet to continue.',
836
- role: 'assistant',
837
- timestamp: new Date().toISOString(),
838
- button: 'connect'
839
- }]);
840
- return false;
841
- }
842
- // Check if user has signed in with wallet and token is valid
843
- if (!nxtlinqAITServiceAccessToken) {
844
- setMessages(prev => [...prev, {
845
- id: Date.now().toString(),
846
- content: 'Please sign in with your HIT wallet to continue.',
847
- role: 'assistant',
848
- timestamp: new Date().toISOString(),
849
- button: 'signIn'
850
- }]);
851
- return false;
852
- }
853
- // Validate token - check if it's expired or for different address
854
- try {
855
- const payload = JSON.parse(atob(nxtlinqAITServiceAccessToken.split('.')[1]));
856
- const exp = payload.exp * 1000; // Convert to milliseconds
857
- const now = Date.now();
858
- if (exp < now) {
859
- // Clear invalid token
860
- setNxtlinqAITServiceAccessToken('');
861
- setMessages(prev => [...prev, {
862
- id: Date.now().toString(),
863
- content: 'Your wallet session has expired. Please sign in again.',
864
- role: 'assistant',
865
- timestamp: new Date().toISOString(),
866
- button: 'signIn'
867
- }]);
868
- return false;
869
- }
870
- // Check if the token's payload has the same address as the wallet address
871
- const address = payload.address;
872
- if (address !== hitAddress) {
873
- // Clear mismatched token
874
- setNxtlinqAITServiceAccessToken('');
875
- setMessages(prev => [...prev, {
876
- id: Date.now().toString(),
877
- content: 'Wallet address mismatch. Please sign in with the correct wallet.',
878
- role: 'assistant',
879
- timestamp: new Date().toISOString(),
880
- button: 'signIn'
881
- }]);
882
- return false;
883
- }
884
- }
885
- catch (error) {
886
- console.error('Error parsing token:', error);
887
- // Clear invalid token
888
- setNxtlinqAITServiceAccessToken('');
889
- setMessages(prev => [...prev, {
890
- id: Date.now().toString(),
891
- content: 'Invalid wallet session. Please sign in again.',
892
- role: 'assistant',
893
- timestamp: new Date().toISOString(),
894
- button: 'signIn'
895
- }]);
896
- return false;
897
- }
898
- if (!ait) {
899
- setMessages(prev => [...prev, {
900
- id: Date.now().toString(),
901
- content: 'No AIT found for your wallet. Please click the settings button (⚙️) to configure your AIT permissions.',
902
- role: 'assistant',
903
- timestamp: new Date().toISOString()
904
- }]);
905
- return false;
906
- }
907
- // Check if the tool permission is available for current identity provider
908
- const availablePermissionLabels = availablePermissions.map(p => p.label);
909
- if (!availablePermissionLabels.includes(toolName)) {
910
- setMessages(prev => [...prev, {
911
- id: Date.now().toString(),
912
- content: `This tool (${toolName}) is not available for your current identity provider.`,
913
- role: 'assistant',
914
- timestamp: new Date().toISOString()
915
- }]);
916
- return false;
917
- }
918
- // Check if the tool permission is included in AIT permissions
919
- if (!permissions.includes(toolName)) {
920
- setMessages(prev => [...prev, {
921
- id: Date.now().toString(),
922
- content: `You do not have the required AIT permission: ${toolName}. Please click the settings button (⚙️) to update your permissions.`,
923
- role: 'assistant',
924
- timestamp: new Date().toISOString()
925
- }]);
926
- return false;
927
- }
928
- return true;
929
- };
930
- const sendMessage = async (content, retryCount = 0) => {
931
- try {
932
- setIsLoading(true);
933
- const response = await nxtlinqApi.agent.sendMessage({
934
- message: content,
935
- apiKey,
936
- apiSecret,
937
- });
938
- if ('error' in response) {
939
- throw new Error(response.error);
940
- }
941
- const novaResponse = response;
942
- if (novaResponse.toolCall?.toolUse && novaResponse.result !== 'Authentication data retrieved') {
943
- if (onToolUse) {
944
- const isToolAllowed = await hasPermission(novaResponse.toolCall.toolUse.name);
945
- if (!isToolAllowed) {
946
- return;
947
- }
948
- const toolUseResult = await onToolUse(novaResponse.toolCall.toolUse);
949
- if (toolUseResult) {
950
- setMessages(prev => [...prev, toolUseResult]);
951
- return;
952
- }
953
- }
954
- }
955
- if (!novaResponse.toolCall?.toolUse && novaResponse.reply) {
956
- const replyText = novaResponse.reply
957
- .map(item => item.text.replace(/<thinking>/g, '').replace(/<\/thinking>/g, ''))
958
- .join(' ') || '';
959
- if (replyText) {
960
- const message = {
961
- id: Date.now().toString(),
962
- content: replyText,
963
- role: 'assistant',
964
- timestamp: new Date().toISOString()
965
- };
966
- setMessages(prev => [...prev, message]);
967
- return;
968
- }
969
- }
970
- return;
971
- }
972
- catch (error) {
973
- if (retryCount < maxRetries) {
974
- await new Promise(resolve => setTimeout(resolve, retryDelay));
975
- return sendMessage(content, retryCount + 1);
976
- }
977
- throw error;
978
- }
979
- finally {
980
- setIsLoading(false);
981
- }
982
- };
983
- const handleSubmit = async (e) => {
984
- e.preventDefault();
985
- if (!inputValue.trim() || isLoading)
986
- return;
987
- const userMessage = {
988
- id: Date.now().toString(),
989
- content: inputValue,
990
- role: 'user',
991
- timestamp: new Date().toISOString()
992
- };
993
- setMessages(prev => [...prev, userMessage]);
994
- setInputValue('');
995
- setIsLoading(true);
996
- try {
997
- await sendMessage(inputValue);
998
- }
999
- catch (error) {
1000
- console.error('Failed to send message:', error);
1001
- onError?.(error instanceof Error ? error : new Error('Failed to send message'));
1002
- const errorMessage = {
1003
- id: Date.now().toString(),
1004
- content: 'Sorry, there was an error processing your message. Please try again.',
1005
- role: 'assistant',
1006
- timestamp: new Date().toISOString()
1007
- };
1008
- setMessages(prev => [...prev, errorMessage]);
1009
- }
1010
- finally {
1011
- setIsLoading(false);
1012
- }
1013
- };
1014
- const handlePresetMessage = (message) => {
1015
- if (message.autoSend) {
1016
- setMessages(prev => [...prev, {
1017
- id: Date.now().toString(),
1018
- content: message.text,
1019
- role: 'user',
1020
- timestamp: new Date().toISOString()
1021
- }]);
1022
- sendMessage(message.text);
1023
- }
1024
- else {
1025
- setInputValue(message.text);
1026
- }
1027
- };
1028
- const generateAndRegisterAIT = async () => {
1029
- if (!signer || !hitAddress)
1030
- return;
1031
- const timestamp = Math.floor(Date.now() / 1000);
1032
- const aitId = `did:polygon:ike-dashboard:${hitAddress}:${timestamp}`;
1033
- const metadata = {
1034
- model: 'gpt-4',
1035
- permissions,
1036
- issuedBy: hitAddress,
1037
- };
1038
- const metadataStr = stringify(metadata);
1039
- const metadataHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(metadataStr));
1040
- // 1️⃣ Upload metadata to Pinata, get CID
1041
- const uploadResponse = await nxtlinqApi.metadata.createMetadata(metadata, nxtlinqAITServiceAccessToken || '');
1042
- if ('error' in uploadResponse) {
1043
- throw new Error(`Failed to upload metadata: ${uploadResponse.error}`);
1044
- }
1045
- const { metadataCid } = uploadResponse;
1046
- await nxtlinqApi.ait.createAIT({
1047
- aitId,
1048
- controller: hitAddress,
1049
- serviceId,
1050
- metadataHash,
1051
- metadataCid,
1052
- }, nxtlinqAITServiceAccessToken || '');
1053
- const aitInfo = {
1054
- aitId,
1055
- controller: hitAddress,
1056
- metadata,
1057
- metadataHash,
1058
- metadataCid,
1059
- };
1060
- setAit(aitInfo);
1061
- };
1062
- const savePermissions = async () => {
1063
- setIsDisabled(true);
1064
- try {
1065
- await generateAndRegisterAIT();
1066
- // Use Modal notification instead of ChatBot message
1067
- showSuccess('AIT permissions saved successfully! You can now use the AI agent with your configured permissions.');
1068
- setShowPermissionForm(false);
1069
- setIsPermissionFormOpen(false);
1070
- }
1071
- catch (error) {
1072
- console.error('Failed to generate AIT:', error);
1073
- setIsDisabled(false);
1074
- if (error instanceof Error) {
1075
- showError(error.message);
1076
- }
1077
- else {
1078
- showError('Failed to save permissions. Please try again.');
1079
- }
1080
- }
1081
- };
1082
- // Add state change listener
1083
- React.useEffect(() => {
1084
- console.log('States updated:', {
1085
- hitAddress,
1086
- isNeedSignInWithWallet,
1087
- walletInfo,
1088
- isOpen
1089
- });
1090
- }, [hitAddress, isNeedSignInWithWallet, walletInfo, isOpen]);
1091
- // Add useEffect to monitor message changes
1092
- React.useEffect(() => {
1093
- if (messages.length > 0) {
1094
- const lastMessage = messages[messages.length - 1];
1095
- onMessage?.(lastMessage);
1096
- }
1097
- }, [messages, onMessage]);
1098
- return (_jsxs("div", { style: {
1099
- position: 'fixed',
1100
- bottom: '20px',
1101
- right: '20px',
1102
- zIndex: 1000,
1103
- display: 'flex',
1104
- flexDirection: 'column',
1105
- alignItems: 'flex-end',
1106
- gap: '10px'
1107
- }, children: [isOpen && (_jsxs("div", { className: `nxtlinq-chatbot ${className}`, style: {
1108
- width: '350px',
1109
- height: '500px',
1110
- backgroundColor: 'white',
1111
- borderRadius: '10px',
1112
- boxShadow: '0 5px 15px rgba(0, 0, 0, 0.2)',
1113
- display: 'flex',
1114
- flexDirection: 'column',
1115
- overflow: 'hidden'
1116
- }, children: [_jsxs("div", { style: {
1117
- padding: '15px',
1118
- backgroundColor: '#007bff',
1119
- color: 'white',
1120
- borderRadius: '10px 10px 0 0',
1121
- display: 'flex',
1122
- justifyContent: 'space-between',
1123
- alignItems: 'center'
1124
- }, children: [_jsx("h3", { style: { margin: 0 }, children: "AI Agent" }), _jsxs("div", { style: { display: 'flex', gap: '10px' }, children: [_jsx("button", { onClick: async () => {
1125
- setShowPermissionForm(true);
1126
- setIsPermissionFormOpen(true);
1127
- // Force refresh AIT data when opening the form to show latest permissions
1128
- await refreshAIT(true);
1129
- }, style: {
1130
- background: 'none',
1131
- border: 'none',
1132
- color: 'white',
1133
- fontSize: '20px',
1134
- cursor: 'pointer',
1135
- padding: '0 5px'
1136
- }, children: "\u2699\uFE0F" }), _jsx("button", { onClick: () => setIsOpen(false), style: {
1137
- background: 'none',
1138
- border: 'none',
1139
- color: 'white',
1140
- fontSize: '24px',
1141
- cursor: 'pointer',
1142
- padding: '0 5px'
1143
- }, children: "\u00D7" })] })] }), _jsxs("div", { style: {
1144
- flex: 1,
1145
- overflowY: 'auto',
1146
- padding: '15px',
1147
- display: 'flex',
1148
- flexDirection: 'column',
1149
- gap: '10px'
1150
- }, children: [messages.map((message, index) => (_jsxs("div", { style: {
1151
- alignSelf: message.role === 'user' ? 'flex-end' : 'flex-start',
1152
- backgroundColor: message.role === 'user' ? '#007bff' : '#f0f0f0',
1153
- color: message.role === 'user' ? 'white' : 'black',
1154
- padding: '8px 12px',
1155
- borderRadius: '15px',
1156
- maxWidth: '80%',
1157
- wordBreak: 'break-word'
1158
- }, children: [message.content, message.button && (_jsx("button", { onClick: message.button === 'signIn' ? () => signInWallet(true) : () => connectWallet(true), disabled: message.button === 'signIn' ? (!hitAddress || !!ait) : !!hitAddress, style: {
1159
- display: 'block',
1160
- marginTop: '8px',
1161
- padding: '5px 10px',
1162
- backgroundColor: message.button === 'signIn' ? (hitAddress && !ait ? '#28a745' : '#ccc') : (hitAddress ? '#ccc' : '#28a745'),
1163
- color: 'white',
1164
- border: 'none',
1165
- borderRadius: '5px',
1166
- cursor: message.button === 'signIn' ? (hitAddress && !ait ? 'pointer' : 'not-allowed') : (hitAddress ? 'not-allowed' : 'pointer')
1167
- }, children: message.button === 'signIn' ? (!!ait ? 'Signed In' : 'Sign in HIT wallet') : (hitAddress ? 'Connected' : 'Connect HIT wallet') }))] }, index))), isLoading && (_jsx("div", { style: {
1168
- alignSelf: 'flex-start',
1169
- backgroundColor: '#f0f0f0',
1170
- padding: '8px 12px',
1171
- borderRadius: '15px',
1172
- maxWidth: '80%'
1173
- }, children: "Thinking..." })), _jsx("div", { ref: messagesEndRef })] }), _jsxs("div", { style: {
1174
- padding: '10px',
1175
- borderTop: '1px solid #eee',
1176
- display: 'flex',
1177
- flexDirection: 'column',
1178
- gap: '10px'
1179
- }, children: [_jsx("div", { style: {
1180
- display: 'flex',
1181
- gap: '5px',
1182
- overflowX: 'auto',
1183
- padding: '5px 0'
1184
- }, children: presetMessages.map((message, index) => (_jsx("button", { onClick: () => handlePresetMessage(message), style: {
1185
- padding: '5px 10px',
1186
- backgroundColor: '#f0f0f0',
1187
- border: 'none',
1188
- borderRadius: '15px',
1189
- cursor: 'pointer',
1190
- whiteSpace: 'nowrap',
1191
- fontSize: '12px'
1192
- }, children: message.text }, index))) }), _jsxs("form", { onSubmit: handleSubmit, style: {
1193
- display: 'flex',
1194
- gap: '10px'
1195
- }, children: [_jsx("input", { type: "text", value: inputValue, onChange: (e) => setInputValue(e.target.value), placeholder: placeholder, style: {
1196
- flex: 1,
1197
- padding: '8px 12px',
1198
- border: '1px solid #ddd',
1199
- borderRadius: '20px',
1200
- fontSize: '14px',
1201
- outline: 'none'
1202
- } }), _jsx("button", { type: "submit", disabled: isLoading, style: {
1203
- backgroundColor: '#007bff',
1204
- color: 'white',
1205
- border: 'none',
1206
- borderRadius: '20px',
1207
- padding: '8px 20px',
1208
- cursor: isLoading ? 'not-allowed' : 'pointer',
1209
- fontSize: '14px',
1210
- opacity: isLoading ? 0.7 : 1
1211
- }, children: "Send" })] })] })] })), _jsx("button", { onClick: () => setIsOpen(!isOpen), style: {
1212
- width: '120px',
1213
- height: '40px',
1214
- borderRadius: '20px',
1215
- backgroundColor: '#007bff',
1216
- color: '#ffffff',
1217
- border: 'none',
1218
- cursor: 'pointer',
1219
- display: 'flex',
1220
- alignItems: 'center',
1221
- justifyContent: 'center',
1222
- fontSize: '14px',
1223
- fontWeight: 'bold',
1224
- boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
1225
- transition: 'all 0.3s ease-in-out',
1226
- padding: '0 20px'
1227
- }, children: "AI Agent" }), showPermissionForm && (_jsx("div", { style: {
1228
- position: 'fixed',
1229
- top: 0,
1230
- left: 0,
1231
- right: 0,
1232
- bottom: 0,
1233
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
1234
- display: 'flex',
1235
- alignItems: 'center',
1236
- justifyContent: 'center',
1237
- zIndex: 2000
1238
- }, children: _jsx(PermissionForm, { hitAddress: hitAddress, permissions: permissions, setPermissions: setPermissions, setIsDisabled: setIsDisabled, onClose: () => {
1239
- setShowPermissionForm(false);
1240
- setIsPermissionFormOpen(false);
1241
- }, onConnectWallet: () => connectWallet(false), onSignIn: () => signInWallet(false), onSave: savePermissions, isNeedSignInWithWallet: isNeedSignInWithWallet, walletInfo: walletInfo, onVerifyWallet: handleVerifyWalletClick, serviceId: serviceId, nxtlinqApi: nxtlinqApi, permissionGroup: permissionGroup, isAITLoading: isAITLoading, isWalletLoading: isWalletLoading }) })), notification.show && (_jsx(NotificationModal, { notification: notification, onClose: () => setNotification({ ...notification, show: false }) }))] }));
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { ChatBotProvider } from './context/ChatBotContext';
3
+ import { ChatBotUI } from './ui/ChatBotUI';
4
+ export const ChatBot = (props) => {
5
+ return (_jsx(ChatBotProvider, { ...props, children: _jsx(ChatBotUI, {}) }));
1242
6
  };