@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.
Files changed (43) hide show
  1. package/README.md +175 -221
  2. package/dist/api/nxtlinq-api.d.ts.map +1 -1
  3. package/dist/api/nxtlinq-api.js +121 -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 +737 -0
  10. package/dist/components/types/ChatBotTypes.d.ts +98 -0
  11. package/dist/components/types/ChatBotTypes.d.ts.map +1 -0
  12. package/dist/components/types/ChatBotTypes.js +1 -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 +146 -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 +54 -0
  22. package/dist/components/ui/NotificationModal.d.ts +14 -0
  23. package/dist/components/ui/NotificationModal.d.ts.map +1 -0
  24. package/dist/components/ui/NotificationModal.js +79 -0
  25. package/dist/components/ui/PermissionForm.d.ts +8 -0
  26. package/dist/components/ui/PermissionForm.d.ts.map +1 -0
  27. package/dist/components/ui/PermissionForm.js +299 -0
  28. package/dist/components/ui/PresetMessages.d.ts +3 -0
  29. package/dist/components/ui/PresetMessages.d.ts.map +1 -0
  30. package/dist/components/ui/PresetMessages.js +35 -0
  31. package/dist/core/utils/aitUtils.d.ts +28 -0
  32. package/dist/core/utils/aitUtils.d.ts.map +1 -0
  33. package/dist/core/utils/aitUtils.js +34 -0
  34. package/dist/core/utils/notificationUtils.d.ts +29 -0
  35. package/dist/core/utils/notificationUtils.d.ts.map +1 -0
  36. package/dist/core/utils/notificationUtils.js +47 -0
  37. package/dist/core/utils/walletUtils.d.ts +10 -0
  38. package/dist/core/utils/walletUtils.d.ts.map +1 -0
  39. package/dist/core/utils/walletUtils.js +38 -0
  40. package/dist/index.d.ts +13 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +17 -0
  43. package/package.json +1 -1
@@ -0,0 +1,737 @@
1
+ import { jsx as _jsx } 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 ChatBotContext = React.createContext(undefined);
9
+ export const useChatBot = () => {
10
+ const context = React.useContext(ChatBotContext);
11
+ if (!context) {
12
+ throw new Error('useChatBot must be used within a ChatBotProvider');
13
+ }
14
+ return context;
15
+ };
16
+ export const ChatBotProvider = ({ onMessage, onError, onToolUse, presetMessages = [], placeholder = 'Type a message...', className = '', maxRetries = 3, retryDelay = 1000, serviceId, apiKey, apiSecret, onVerifyWallet, permissionGroup, children }) => {
17
+ // State
18
+ const [messages, setMessages] = React.useState([]);
19
+ const [inputValue, setInputValue] = React.useState('');
20
+ const [isLoading, setIsLoading] = React.useState(false);
21
+ const [isOpen, setIsOpen] = React.useState(false);
22
+ const [hitAddress, setHitAddress] = React.useState(null);
23
+ const [ait, setAit] = React.useState(null);
24
+ const [permissions, setPermissions] = React.useState([]);
25
+ const [availablePermissions, setAvailablePermissions] = React.useState([]);
26
+ const [showPermissionForm, setShowPermissionForm] = React.useState(false);
27
+ const [isPermissionFormOpen, setIsPermissionFormOpen] = React.useState(false);
28
+ const [isAITLoading, setIsAITLoading] = React.useState(false);
29
+ const [isDisabled, setIsDisabled] = React.useState(true);
30
+ const [signer, setSigner] = React.useState(null);
31
+ const [walletInfo, setWalletInfo] = React.useState(null);
32
+ const [isWalletLoading, setIsWalletLoading] = React.useState(false);
33
+ const [nxtlinqAITServiceAccessToken, setNxtlinqAITServiceAccessToken] = useLocalStorage('nxtlinqAITServiceAccessToken', '');
34
+ const [notification, setNotification] = React.useState({
35
+ show: false,
36
+ type: 'info',
37
+ message: '',
38
+ autoHide: true,
39
+ duration: 5000
40
+ });
41
+ const nxtlinqApi = React.useMemo(() => createNxtlinqApi(apiKey, apiSecret), [apiKey, apiSecret]);
42
+ // Notification functions
43
+ const showNotification = (type, message, duration = 5000) => {
44
+ setNotification({
45
+ show: true,
46
+ type,
47
+ message,
48
+ autoHide: true,
49
+ duration
50
+ });
51
+ if (duration > 0) {
52
+ setTimeout(() => {
53
+ setNotification(prev => ({ ...prev, show: false }));
54
+ }, duration);
55
+ }
56
+ };
57
+ const showSuccess = (message) => showNotification('success', message, 3000);
58
+ const showError = (message) => showNotification('error', message, 5000);
59
+ const showWarning = (message) => showNotification('warning', message, 4000);
60
+ const showInfo = (message) => showNotification('info', message, 3000);
61
+ // Fetch available permissions
62
+ const fetchAvailablePermissions = async () => {
63
+ if (!serviceId)
64
+ return;
65
+ try {
66
+ const result = await nxtlinqApi.permissions.getServicePermissions({
67
+ serviceId,
68
+ ...(permissionGroup && { groupName: permissionGroup })
69
+ });
70
+ if ('error' in result) {
71
+ console.error('Failed to fetch permissions:', result.error);
72
+ return;
73
+ }
74
+ setAvailablePermissions(result.permissions);
75
+ }
76
+ catch (error) {
77
+ console.error('Error fetching permissions:', error);
78
+ }
79
+ };
80
+ // Refresh AIT
81
+ const refreshAIT = async (forceUpdatePermissions = false) => {
82
+ if (!hitAddress) {
83
+ setAit(null);
84
+ setPermissions([]);
85
+ setWalletInfo(null);
86
+ return;
87
+ }
88
+ setIsAITLoading(true);
89
+ try {
90
+ // Get wallet info first
91
+ if (nxtlinqAITServiceAccessToken) {
92
+ try {
93
+ const walletResponse = await nxtlinqApi.wallet.getWallet({ address: hitAddress }, nxtlinqAITServiceAccessToken);
94
+ if (!('error' in walletResponse)) {
95
+ setWalletInfo(walletResponse);
96
+ }
97
+ }
98
+ catch (error) {
99
+ console.error('Failed to fetch wallet info:', error);
100
+ }
101
+ }
102
+ const response = await nxtlinqApi.ait.getAITByServiceIdAndController({
103
+ serviceId,
104
+ controller: hitAddress
105
+ }, nxtlinqAITServiceAccessToken || '');
106
+ if ('error' in response) {
107
+ console.error('Failed to fetch AIT:', response.error);
108
+ setAit(null);
109
+ setPermissions([]);
110
+ return;
111
+ }
112
+ setAit(response);
113
+ if (!isPermissionFormOpen || forceUpdatePermissions) {
114
+ const newPermissions = response.metadata?.permissions || [];
115
+ setPermissions(newPermissions);
116
+ }
117
+ }
118
+ catch (error) {
119
+ console.error('Failed to fetch AIT:', error);
120
+ setAit(null);
121
+ setPermissions([]);
122
+ }
123
+ finally {
124
+ setIsAITLoading(false);
125
+ }
126
+ };
127
+ // Check if user needs to sign in
128
+ const isNeedSignInWithWallet = React.useMemo(() => {
129
+ if (!hitAddress)
130
+ return false;
131
+ if (!nxtlinqAITServiceAccessToken)
132
+ return true;
133
+ try {
134
+ const payload = JSON.parse(atob(nxtlinqAITServiceAccessToken.split('.')[1]));
135
+ const exp = payload.exp * 1000;
136
+ const now = Date.now();
137
+ if (exp < now)
138
+ return true;
139
+ const address = payload.address;
140
+ if (address !== hitAddress)
141
+ return true;
142
+ return false;
143
+ }
144
+ catch (error) {
145
+ console.error('Error parsing token:', error);
146
+ return true;
147
+ }
148
+ }, [hitAddress, nxtlinqAITServiceAccessToken]);
149
+ // Connect wallet
150
+ const connectWallet = React.useCallback(async (autoShowSignInMessage = true) => {
151
+ if (typeof window === 'undefined') {
152
+ console.error('Web3 is not available in server-side rendering');
153
+ return;
154
+ }
155
+ try {
156
+ const web3Provider = await metakeepClient.ethereum;
157
+ if (!web3Provider) {
158
+ throw new Error('Web3 provider not available');
159
+ }
160
+ await web3Provider.enable();
161
+ const ethersProvider = new ethers.providers.Web3Provider(web3Provider);
162
+ const userSigner = await ethersProvider.getSigner();
163
+ const userAddress = await userSigner.getAddress();
164
+ localStorage.setItem('walletAddress', userAddress);
165
+ setHitAddress(userAddress);
166
+ setSigner(userSigner);
167
+ if (nxtlinqAITServiceAccessToken) {
168
+ await refreshAIT();
169
+ }
170
+ if (autoShowSignInMessage) {
171
+ if (isNeedSignInWithWallet) {
172
+ setMessages(prev => [...prev, {
173
+ id: Date.now().toString(),
174
+ content: 'Please sign in with your wallet to continue.',
175
+ role: 'assistant',
176
+ timestamp: new Date().toISOString(),
177
+ button: 'signIn'
178
+ }]);
179
+ }
180
+ else {
181
+ showSuccess('Successfully connected your HIT wallet. You are already signed in and can use the AI agent.');
182
+ }
183
+ }
184
+ return userAddress;
185
+ }
186
+ catch (error) {
187
+ console.error('Failed to connect wallet:', error);
188
+ localStorage.removeItem('walletAddress');
189
+ setHitAddress(null);
190
+ setSigner(null);
191
+ throw error;
192
+ }
193
+ }, [nxtlinqAITServiceAccessToken, refreshAIT, isNeedSignInWithWallet]);
194
+ // Sign in wallet
195
+ const signInWallet = async (autoShowSuccessMessage = true) => {
196
+ if (!hitAddress) {
197
+ showError('Please connect your wallet first.');
198
+ return;
199
+ }
200
+ if (!signer) {
201
+ showError('Please connect your wallet first.');
202
+ return;
203
+ }
204
+ try {
205
+ const nonceResponse = await nxtlinqApi.auth.getNonce({ address: hitAddress });
206
+ if ('error' in nonceResponse) {
207
+ showError(nonceResponse.error);
208
+ return;
209
+ }
210
+ const payload = {
211
+ address: hitAddress,
212
+ code: nonceResponse.code,
213
+ timestamp: nonceResponse.timestamp
214
+ };
215
+ const stringToSign = stringify(payload);
216
+ const signature = await signer.signMessage(stringToSign || '');
217
+ const response = await nxtlinqApi.auth.signIn({
218
+ ...payload,
219
+ signature
220
+ });
221
+ if ('error' in response) {
222
+ showError(response.error);
223
+ return;
224
+ }
225
+ const { accessToken } = response;
226
+ setNxtlinqAITServiceAccessToken(accessToken);
227
+ if (autoShowSuccessMessage) {
228
+ showSuccess('Successfully signed in with your HIT wallet. You can now use the AI agent.');
229
+ }
230
+ refreshAIT();
231
+ }
232
+ catch (error) {
233
+ console.error('Failed to sign in:', error);
234
+ showError('Failed to sign in. Please try again.');
235
+ }
236
+ };
237
+ // Check permissions
238
+ const hasPermission = async (toolName) => {
239
+ if (!hitAddress) {
240
+ setMessages(prev => [...prev, {
241
+ id: Date.now().toString(),
242
+ content: 'Please connect your HIT wallet to continue.',
243
+ role: 'assistant',
244
+ timestamp: new Date().toISOString(),
245
+ button: 'connect'
246
+ }]);
247
+ return false;
248
+ }
249
+ if (!nxtlinqAITServiceAccessToken) {
250
+ setMessages(prev => [...prev, {
251
+ id: Date.now().toString(),
252
+ content: 'Please sign in with your HIT wallet to continue.',
253
+ role: 'assistant',
254
+ timestamp: new Date().toISOString(),
255
+ button: 'signIn'
256
+ }]);
257
+ return false;
258
+ }
259
+ try {
260
+ const payload = JSON.parse(atob(nxtlinqAITServiceAccessToken.split('.')[1]));
261
+ const exp = payload.exp * 1000;
262
+ const now = Date.now();
263
+ if (exp < now) {
264
+ setNxtlinqAITServiceAccessToken('');
265
+ setMessages(prev => [...prev, {
266
+ id: Date.now().toString(),
267
+ content: 'Your wallet session has expired. Please sign in again.',
268
+ role: 'assistant',
269
+ timestamp: new Date().toISOString(),
270
+ button: 'signIn'
271
+ }]);
272
+ return false;
273
+ }
274
+ const address = payload.address;
275
+ if (address !== hitAddress) {
276
+ setNxtlinqAITServiceAccessToken('');
277
+ setMessages(prev => [...prev, {
278
+ id: Date.now().toString(),
279
+ content: 'Wallet address mismatch. Please sign in with the correct wallet.',
280
+ role: 'assistant',
281
+ timestamp: new Date().toISOString(),
282
+ button: 'signIn'
283
+ }]);
284
+ return false;
285
+ }
286
+ }
287
+ catch (error) {
288
+ console.error('Error parsing token:', error);
289
+ setNxtlinqAITServiceAccessToken('');
290
+ setMessages(prev => [...prev, {
291
+ id: Date.now().toString(),
292
+ content: 'Invalid wallet session. Please sign in again.',
293
+ role: 'assistant',
294
+ timestamp: new Date().toISOString(),
295
+ button: 'signIn'
296
+ }]);
297
+ return false;
298
+ }
299
+ if (!ait) {
300
+ // Show loading message if AIT is still loading
301
+ if (isAITLoading) {
302
+ setMessages(prev => [...prev, {
303
+ id: Date.now().toString(),
304
+ content: 'Loading your wallet configuration... Please wait a moment.',
305
+ role: 'assistant',
306
+ timestamp: new Date().toISOString()
307
+ }]);
308
+ return false;
309
+ }
310
+ setMessages(prev => [...prev, {
311
+ id: Date.now().toString(),
312
+ content: 'No AIT found for your wallet. Please click the settings button (⚙️) to configure your AIT permissions.',
313
+ role: 'assistant',
314
+ timestamp: new Date().toISOString()
315
+ }]);
316
+ return false;
317
+ }
318
+ const availablePermissionLabels = availablePermissions.map(p => p.label);
319
+ if (!availablePermissionLabels.includes(toolName)) {
320
+ setMessages(prev => [...prev, {
321
+ id: Date.now().toString(),
322
+ content: `This tool (${toolName}) is not available for your current identity provider.`,
323
+ role: 'assistant',
324
+ timestamp: new Date().toISOString()
325
+ }]);
326
+ return false;
327
+ }
328
+ if (!permissions.includes(toolName)) {
329
+ setMessages(prev => [...prev, {
330
+ id: Date.now().toString(),
331
+ content: `You do not have the required AIT permission: ${toolName}. Please click the settings button (⚙️) to update your permissions.`,
332
+ role: 'assistant',
333
+ timestamp: new Date().toISOString()
334
+ }]);
335
+ return false;
336
+ }
337
+ return true;
338
+ };
339
+ // Send message
340
+ const sendMessage = async (content, retryCount = 0) => {
341
+ try {
342
+ setIsLoading(true);
343
+ const response = await nxtlinqApi.agent.sendMessage({
344
+ message: content,
345
+ apiKey,
346
+ apiSecret,
347
+ });
348
+ if ('error' in response) {
349
+ throw new Error(response.error);
350
+ }
351
+ const novaResponse = response;
352
+ if (novaResponse.toolCall?.toolUse && novaResponse.result !== 'Authentication data retrieved') {
353
+ if (onToolUse) {
354
+ const isToolAllowed = await hasPermission(novaResponse.toolCall.toolUse.name);
355
+ if (!isToolAllowed) {
356
+ return;
357
+ }
358
+ const toolUseResult = await onToolUse(novaResponse.toolCall.toolUse);
359
+ if (toolUseResult) {
360
+ setMessages(prev => [...prev, toolUseResult]);
361
+ return;
362
+ }
363
+ }
364
+ }
365
+ if (!novaResponse.toolCall?.toolUse && novaResponse.reply) {
366
+ const replyText = novaResponse.reply
367
+ .map(item => item.text.replace(/<thinking>/g, '').replace(/<\/thinking>/g, ''))
368
+ .join(' ') || '';
369
+ if (replyText) {
370
+ const message = {
371
+ id: Date.now().toString(),
372
+ content: replyText,
373
+ role: 'assistant',
374
+ timestamp: new Date().toISOString()
375
+ };
376
+ setMessages(prev => [...prev, message]);
377
+ return;
378
+ }
379
+ }
380
+ return;
381
+ }
382
+ catch (error) {
383
+ if (retryCount < maxRetries) {
384
+ await new Promise(resolve => setTimeout(resolve, retryDelay));
385
+ return sendMessage(content, retryCount + 1);
386
+ }
387
+ throw error;
388
+ }
389
+ finally {
390
+ setIsLoading(false);
391
+ }
392
+ };
393
+ // Handle submit
394
+ const handleSubmit = async (e) => {
395
+ e.preventDefault();
396
+ if (!inputValue.trim() || isLoading)
397
+ return;
398
+ // Show loading message if AIT is still loading
399
+ if (isAITLoading) {
400
+ const loadingMessage = {
401
+ id: Date.now().toString(),
402
+ content: 'Loading your wallet configuration... Please wait a moment.',
403
+ role: 'assistant',
404
+ timestamp: new Date().toISOString()
405
+ };
406
+ setMessages(prev => [...prev, loadingMessage]);
407
+ return;
408
+ }
409
+ const userMessage = {
410
+ id: Date.now().toString(),
411
+ content: inputValue,
412
+ role: 'user',
413
+ timestamp: new Date().toISOString()
414
+ };
415
+ setMessages(prev => [...prev, userMessage]);
416
+ setInputValue('');
417
+ setIsLoading(true);
418
+ try {
419
+ await sendMessage(inputValue);
420
+ }
421
+ catch (error) {
422
+ console.error('Failed to send message:', error);
423
+ onError?.(error instanceof Error ? error : new Error('Failed to send message'));
424
+ const errorMessage = {
425
+ id: Date.now().toString(),
426
+ content: 'Sorry, there was an error processing your message. Please try again.',
427
+ role: 'assistant',
428
+ timestamp: new Date().toISOString()
429
+ };
430
+ setMessages(prev => [...prev, errorMessage]);
431
+ }
432
+ finally {
433
+ setIsLoading(false);
434
+ }
435
+ };
436
+ // Handle preset message
437
+ const handlePresetMessage = (message) => {
438
+ // Show loading message if AIT is still loading
439
+ if (isAITLoading) {
440
+ const loadingMessage = {
441
+ id: Date.now().toString(),
442
+ content: 'Loading your wallet configuration... Please wait a moment.',
443
+ role: 'assistant',
444
+ timestamp: new Date().toISOString()
445
+ };
446
+ setMessages(prev => [...prev, loadingMessage]);
447
+ return;
448
+ }
449
+ if (message.autoSend) {
450
+ setMessages(prev => [...prev, {
451
+ id: Date.now().toString(),
452
+ content: message.text,
453
+ role: 'user',
454
+ timestamp: new Date().toISOString()
455
+ }]);
456
+ sendMessage(message.text);
457
+ }
458
+ else {
459
+ setInputValue(message.text);
460
+ }
461
+ };
462
+ // Generate and register AIT
463
+ const generateAndRegisterAIT = async () => {
464
+ if (!signer || !hitAddress) {
465
+ throw new Error('Missing signer or wallet address');
466
+ }
467
+ const timestamp = Math.floor(Date.now() / 1000);
468
+ const aitId = `did:polygon:ike-dashboard:${hitAddress}:${timestamp}`;
469
+ const metadata = {
470
+ model: 'gpt-4',
471
+ permissions,
472
+ issuedBy: hitAddress,
473
+ };
474
+ const metadataStr = stringify(metadata);
475
+ const metadataHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(metadataStr));
476
+ const uploadResponse = await nxtlinqApi.metadata.createMetadata(metadata, nxtlinqAITServiceAccessToken || '');
477
+ if ('error' in uploadResponse) {
478
+ throw new Error(`Failed to upload metadata: ${uploadResponse.error}`);
479
+ }
480
+ const { metadataCid } = uploadResponse;
481
+ const createAITResponse = await nxtlinqApi.ait.createAIT({
482
+ aitId,
483
+ controller: hitAddress,
484
+ serviceId,
485
+ metadataHash,
486
+ metadataCid,
487
+ }, nxtlinqAITServiceAccessToken || '');
488
+ if ('error' in createAITResponse) {
489
+ throw new Error(`Failed to create AIT: ${createAITResponse.error}`);
490
+ }
491
+ const aitInfo = {
492
+ aitId,
493
+ controller: hitAddress,
494
+ metadata,
495
+ metadataHash,
496
+ metadataCid,
497
+ };
498
+ setAit(aitInfo);
499
+ setPermissions(permissions);
500
+ };
501
+ // Save permissions
502
+ const savePermissions = async () => {
503
+ setIsDisabled(true);
504
+ try {
505
+ await generateAndRegisterAIT();
506
+ showSuccess('AIT permissions saved successfully! You can now use the AI agent with your configured permissions.');
507
+ setShowPermissionForm(false);
508
+ setIsPermissionFormOpen(false);
509
+ await refreshAIT(true);
510
+ }
511
+ catch (error) {
512
+ console.error('Failed to generate AIT:', error);
513
+ setIsDisabled(false);
514
+ if (error instanceof Error) {
515
+ showError(error.message);
516
+ }
517
+ else {
518
+ showError('Failed to save permissions. Please try again.');
519
+ }
520
+ }
521
+ };
522
+ // Handle verify wallet click
523
+ const handleVerifyWalletClick = async () => {
524
+ if (!hitAddress) {
525
+ showError('Please connect your wallet first.');
526
+ return;
527
+ }
528
+ try {
529
+ if (onVerifyWallet) {
530
+ setIsLoading(true);
531
+ const result = await onVerifyWallet();
532
+ if (!result) {
533
+ setIsLoading(false);
534
+ return;
535
+ }
536
+ const { token } = result;
537
+ const address = hitAddress;
538
+ if (token && address) {
539
+ const payload = {
540
+ address: hitAddress,
541
+ token,
542
+ timestamp: Date.now(),
543
+ method: 'berifyme'
544
+ };
545
+ try {
546
+ const verifyWalletResponse = await nxtlinqApi.wallet.verifyWallet({ ...payload }, token);
547
+ if ('error' in verifyWalletResponse) {
548
+ if (verifyWalletResponse.error === 'Wallet already exists') {
549
+ setIsWalletLoading(true);
550
+ try {
551
+ const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
552
+ if (!('error' in walletResponse)) {
553
+ setWalletInfo(walletResponse);
554
+ const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({ serviceId, controller: address }, token);
555
+ if (!('error' in aitResponse)) {
556
+ setAit(aitResponse);
557
+ }
558
+ }
559
+ }
560
+ finally {
561
+ setIsWalletLoading(false);
562
+ }
563
+ if (typeof window !== 'undefined') {
564
+ try {
565
+ const url = new URL(window.location.href);
566
+ url.searchParams.delete('token');
567
+ url.searchParams.delete('isAutoConnect');
568
+ url.searchParams.delete('method');
569
+ url.searchParams.delete('returnUrl');
570
+ window.history.replaceState({}, '', url.toString());
571
+ }
572
+ catch (e) {
573
+ console.error('Failed to clean URL:', e);
574
+ }
575
+ }
576
+ setIsLoading(false);
577
+ showSuccess('Wallet verification completed successfully! Your wallet is now verified and ready to use.');
578
+ refreshAIT();
579
+ return;
580
+ }
581
+ showError(verifyWalletResponse.error);
582
+ setIsLoading(false);
583
+ return;
584
+ }
585
+ setIsWalletLoading(true);
586
+ try {
587
+ const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
588
+ if (!('error' in walletResponse)) {
589
+ setWalletInfo(walletResponse);
590
+ const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({ serviceId, controller: address }, token);
591
+ if (!('error' in aitResponse)) {
592
+ setAit(aitResponse);
593
+ }
594
+ }
595
+ }
596
+ finally {
597
+ setIsWalletLoading(false);
598
+ }
599
+ if (typeof window !== 'undefined') {
600
+ try {
601
+ const url = new URL(window.location.href);
602
+ url.searchParams.delete('token');
603
+ url.searchParams.delete('isAutoConnect');
604
+ url.searchParams.delete('method');
605
+ url.searchParams.delete('returnUrl');
606
+ window.history.replaceState({}, '', url.toString());
607
+ }
608
+ catch (e) {
609
+ console.error('Failed to clean URL:', e);
610
+ }
611
+ }
612
+ setIsLoading(false);
613
+ showSuccess('Wallet verification completed successfully! Your wallet is now verified and ready to use.');
614
+ refreshAIT();
615
+ return;
616
+ }
617
+ catch (error) {
618
+ let msg = 'Verification failed';
619
+ if (typeof error === 'object' && error !== null && 'response' in error) {
620
+ msg = error.response?.data?.error || error.message || msg;
621
+ }
622
+ else if (error instanceof Error) {
623
+ msg = error.message;
624
+ }
625
+ console.error('Wallet verification failed:', error);
626
+ showError(msg);
627
+ setIsLoading(false);
628
+ throw error;
629
+ }
630
+ }
631
+ setIsLoading(false);
632
+ return;
633
+ }
634
+ }
635
+ catch (error) {
636
+ console.error('Failed to verify wallet:', error);
637
+ setIsLoading(false);
638
+ showError('Failed to verify wallet. Please try again.');
639
+ throw error;
640
+ }
641
+ };
642
+ // Effects
643
+ React.useEffect(() => {
644
+ if (hitAddress && nxtlinqAITServiceAccessToken) {
645
+ refreshAIT();
646
+ }
647
+ }, [hitAddress, nxtlinqAITServiceAccessToken]);
648
+ React.useEffect(() => {
649
+ fetchAvailablePermissions();
650
+ }, [serviceId, permissionGroup]);
651
+ React.useEffect(() => {
652
+ if (typeof window !== 'undefined') {
653
+ try {
654
+ const urlParams = new URLSearchParams(window.location.search);
655
+ const token = urlParams.get('token');
656
+ if (token && hitAddress) {
657
+ handleVerifyWalletClick();
658
+ }
659
+ }
660
+ catch (e) {
661
+ console.error('Failed to get URL params:', e);
662
+ }
663
+ }
664
+ }, [hitAddress]);
665
+ React.useEffect(() => {
666
+ if (messages.length > 0) {
667
+ const lastMessage = messages[messages.length - 1];
668
+ onMessage?.(lastMessage);
669
+ }
670
+ }, [messages, onMessage]);
671
+ const contextValue = {
672
+ // State
673
+ messages,
674
+ inputValue,
675
+ isLoading,
676
+ isOpen,
677
+ hitAddress,
678
+ ait,
679
+ permissions,
680
+ availablePermissions,
681
+ showPermissionForm,
682
+ isPermissionFormOpen,
683
+ isAITLoading,
684
+ isDisabled,
685
+ walletInfo,
686
+ isWalletLoading,
687
+ notification,
688
+ // Actions
689
+ setInputValue,
690
+ setIsOpen,
691
+ setShowPermissionForm,
692
+ setIsPermissionFormOpen,
693
+ setPermissions,
694
+ setIsDisabled,
695
+ setIsWalletLoading,
696
+ setNotification,
697
+ // Functions
698
+ connectWallet,
699
+ signInWallet,
700
+ sendMessage,
701
+ handleSubmit,
702
+ handlePresetMessage,
703
+ savePermissions,
704
+ handleVerifyWalletClick,
705
+ showSuccess,
706
+ showError,
707
+ showWarning,
708
+ showInfo,
709
+ refreshAIT,
710
+ // Additional properties for PermissionForm
711
+ onSave: savePermissions,
712
+ onConnectWallet: () => connectWallet(false),
713
+ onSignIn: () => signInWallet(false),
714
+ isNeedSignInWithWallet,
715
+ onVerifyWallet: handleVerifyWalletClick,
716
+ serviceId,
717
+ permissionGroup,
718
+ // Props
719
+ props: {
720
+ onMessage,
721
+ onError,
722
+ onToolUse,
723
+ presetMessages,
724
+ placeholder,
725
+ className,
726
+ maxRetries,
727
+ retryDelay,
728
+ serviceId,
729
+ apiKey,
730
+ apiSecret,
731
+ onVerifyWallet,
732
+ permissionGroup
733
+ },
734
+ nxtlinqApi
735
+ };
736
+ return (_jsx(ChatBotContext.Provider, { value: contextValue, children: children }));
737
+ };