@bytexbyte/nxtlinq-ai-agent-sdk 1.2.2 → 1.2.3
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/README.md +175 -221
- package/dist/api/nxtlinq-api.d.ts.map +1 -1
- package/dist/api/nxtlinq-api.js +121 -142
- package/dist/components/ChatBot.d.ts +2 -44
- package/dist/components/ChatBot.d.ts.map +1 -1
- package/dist/components/ChatBot.js +5 -1241
- package/dist/components/context/ChatBotContext.d.ts +5 -0
- package/dist/components/context/ChatBotContext.d.ts.map +1 -0
- package/dist/components/context/ChatBotContext.js +737 -0
- package/dist/components/types/ChatBotTypes.d.ts +98 -0
- package/dist/components/types/ChatBotTypes.d.ts.map +1 -0
- package/dist/components/types/ChatBotTypes.js +1 -0
- package/dist/components/ui/ChatBotUI.d.ts +3 -0
- package/dist/components/ui/ChatBotUI.d.ts.map +1 -0
- package/dist/components/ui/ChatBotUI.js +146 -0
- package/dist/components/ui/MessageInput.d.ts +3 -0
- package/dist/components/ui/MessageInput.d.ts.map +1 -0
- package/dist/components/ui/MessageInput.js +46 -0
- package/dist/components/ui/MessageList.d.ts +3 -0
- package/dist/components/ui/MessageList.d.ts.map +1 -0
- package/dist/components/ui/MessageList.js +54 -0
- package/dist/components/ui/NotificationModal.d.ts +14 -0
- package/dist/components/ui/NotificationModal.d.ts.map +1 -0
- package/dist/components/ui/NotificationModal.js +79 -0
- package/dist/components/ui/PermissionForm.d.ts +8 -0
- package/dist/components/ui/PermissionForm.d.ts.map +1 -0
- package/dist/components/ui/PermissionForm.js +299 -0
- package/dist/components/ui/PresetMessages.d.ts +3 -0
- package/dist/components/ui/PresetMessages.d.ts.map +1 -0
- package/dist/components/ui/PresetMessages.js +35 -0
- package/dist/core/utils/aitUtils.d.ts +28 -0
- package/dist/core/utils/aitUtils.d.ts.map +1 -0
- package/dist/core/utils/aitUtils.js +34 -0
- package/dist/core/utils/notificationUtils.d.ts +29 -0
- package/dist/core/utils/notificationUtils.d.ts.map +1 -0
- package/dist/core/utils/notificationUtils.js +47 -0
- package/dist/core/utils/walletUtils.d.ts +10 -0
- package/dist/core/utils/walletUtils.d.ts.map +1 -0
- package/dist/core/utils/walletUtils.js +38 -0
- package/dist/index.d.ts +13 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -0
- package/package.json +1 -1
|
@@ -1,1242 +1,6 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
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
|
};
|