@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.4.0 → 0.4.2

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 (146) hide show
  1. package/dist/context/ChatBotContext.d.ts.map +1 -1
  2. package/dist/context/ChatBotContext.js +84 -405
  3. package/dist/index.d.ts +2 -2
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/index.js +1 -1
  6. package/dist/permissionState.d.ts +53 -0
  7. package/dist/permissionState.d.ts.map +1 -0
  8. package/dist/permissionState.js +217 -0
  9. package/dist/types/ChatBotTypes.d.ts +0 -5
  10. package/dist/types/ChatBotTypes.d.ts.map +1 -1
  11. package/dist/ui/ChatBotHeader.d.ts.map +1 -1
  12. package/dist/ui/ChatBotHeader.js +6 -2
  13. package/dist/ui/ChatBotUI.d.ts.map +1 -1
  14. package/dist/ui/ChatBotUI.js +13 -4
  15. package/dist/ui/MessageList.d.ts.map +1 -1
  16. package/dist/ui/MessageList.js +11 -6
  17. package/dist/ui/PermissionForm.d.ts.map +1 -1
  18. package/dist/ui/PermissionForm.js +6 -9
  19. package/dist/ui/styles/isolatedStyles.d.ts.map +1 -1
  20. package/dist/ui/styles/isolatedStyles.js +1 -0
  21. package/package.json +3 -3
  22. package/src/context/ChatBotContext.tsx +92 -437
  23. package/src/index.ts +5 -0
  24. package/src/types/ChatBotTypes.ts +2 -6
  25. package/src/ui/ChatBotHeader.tsx +9 -3
  26. package/src/ui/ChatBotUI.tsx +14 -5
  27. package/src/ui/MessageList.tsx +6 -0
  28. package/src/ui/PermissionForm.tsx +7 -12
  29. package/src/ui/styles/isolatedStyles.ts +1 -0
  30. package/dist/NxtlinqAgentChat.d.ts +0 -26
  31. package/dist/NxtlinqAgentChat.d.ts.map +0 -1
  32. package/dist/NxtlinqAgentChat.js +0 -28
  33. package/dist/components/AgentAssistantShell.d.ts +0 -5
  34. package/dist/components/AgentAssistantShell.d.ts.map +0 -1
  35. package/dist/components/AgentAssistantShell.js +0 -52
  36. package/dist/components/AgentComposer.d.ts +0 -3
  37. package/dist/components/AgentComposer.d.ts.map +0 -1
  38. package/dist/components/AgentComposer.js +0 -60
  39. package/dist/components/AgentMessageList.d.ts +0 -3
  40. package/dist/components/AgentMessageList.d.ts.map +0 -1
  41. package/dist/components/AgentMessageList.js +0 -37
  42. package/dist/components/AgentRemoteAudio.d.ts +0 -4
  43. package/dist/components/AgentRemoteAudio.d.ts.map +0 -1
  44. package/dist/components/AgentRemoteAudio.js +0 -34
  45. package/dist/components/AgentVoiceBar.d.ts +0 -3
  46. package/dist/components/AgentVoiceBar.d.ts.map +0 -1
  47. package/dist/components/AgentVoiceBar.js +0 -91
  48. package/dist/components/PresetMessageChips.d.ts +0 -3
  49. package/dist/components/PresetMessageChips.d.ts.map +0 -1
  50. package/dist/components/PresetMessageChips.js +0 -23
  51. package/dist/context/AgentAssistantContext.d.ts +0 -32
  52. package/dist/context/AgentAssistantContext.d.ts.map +0 -1
  53. package/dist/context/AgentAssistantContext.js +0 -179
  54. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts +0 -2
  55. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts.map +0 -1
  56. package/dist/legacy/assets/images/adiSideItalicDataUri.js +0 -1
  57. package/dist/legacy/chatbot/ChatBot.d.ts +0 -5
  58. package/dist/legacy/chatbot/ChatBot.d.ts.map +0 -1
  59. package/dist/legacy/chatbot/ChatBot.js +0 -35
  60. package/dist/legacy/chatbot/context/ChatBotContext.d.ts +0 -5
  61. package/dist/legacy/chatbot/context/ChatBotContext.d.ts.map +0 -1
  62. package/dist/legacy/chatbot/context/ChatBotContext.js +0 -2922
  63. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts +0 -166
  64. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts.map +0 -1
  65. package/dist/legacy/chatbot/types/ChatBotTypes.js +0 -1
  66. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts +0 -17
  67. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts.map +0 -1
  68. package/dist/legacy/chatbot/ui/BerifyMeModal.js +0 -110
  69. package/dist/legacy/chatbot/ui/ChatBotHeader.d.ts +0 -15
  70. package/dist/legacy/chatbot/ui/ChatBotHeader.d.ts.map +0 -1
  71. package/dist/legacy/chatbot/ui/ChatBotHeader.js +0 -62
  72. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts +0 -3
  73. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts.map +0 -1
  74. package/dist/legacy/chatbot/ui/ChatBotUI.js +0 -557
  75. package/dist/legacy/chatbot/ui/MessageInput.d.ts +0 -3
  76. package/dist/legacy/chatbot/ui/MessageInput.d.ts.map +0 -1
  77. package/dist/legacy/chatbot/ui/MessageInput.js +0 -321
  78. package/dist/legacy/chatbot/ui/MessageList.d.ts +0 -4
  79. package/dist/legacy/chatbot/ui/MessageList.d.ts.map +0 -1
  80. package/dist/legacy/chatbot/ui/MessageList.js +0 -455
  81. package/dist/legacy/chatbot/ui/ModelSelector.d.ts +0 -4
  82. package/dist/legacy/chatbot/ui/ModelSelector.d.ts.map +0 -1
  83. package/dist/legacy/chatbot/ui/ModelSelector.js +0 -122
  84. package/dist/legacy/chatbot/ui/NotificationModal.d.ts +0 -15
  85. package/dist/legacy/chatbot/ui/NotificationModal.d.ts.map +0 -1
  86. package/dist/legacy/chatbot/ui/NotificationModal.js +0 -53
  87. package/dist/legacy/chatbot/ui/PermissionForm.d.ts +0 -8
  88. package/dist/legacy/chatbot/ui/PermissionForm.d.ts.map +0 -1
  89. package/dist/legacy/chatbot/ui/PermissionForm.js +0 -465
  90. package/dist/legacy/chatbot/ui/PresetMessages.d.ts +0 -4
  91. package/dist/legacy/chatbot/ui/PresetMessages.d.ts.map +0 -1
  92. package/dist/legacy/chatbot/ui/PresetMessages.js +0 -33
  93. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts +0 -3
  94. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts.map +0 -1
  95. package/dist/legacy/chatbot/ui/VoiceModePanel.js +0 -95
  96. package/dist/legacy/chatbot/ui/chatBotHeaderParts.d.ts +0 -15
  97. package/dist/legacy/chatbot/ui/chatBotHeaderParts.d.ts.map +0 -1
  98. package/dist/legacy/chatbot/ui/chatBotHeaderParts.js +0 -50
  99. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts +0 -73
  100. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts.map +0 -1
  101. package/dist/legacy/chatbot/ui/styles/isolatedStyles.js +0 -985
  102. package/dist/legacy/index.d.ts +0 -14
  103. package/dist/legacy/index.d.ts.map +0 -1
  104. package/dist/legacy/index.js +0 -12
  105. package/dist/theme/defaultTheme.d.ts +0 -3
  106. package/dist/theme/defaultTheme.d.ts.map +0 -1
  107. package/dist/theme/defaultTheme.js +0 -20
  108. package/dist/types.d.ts +0 -62
  109. package/dist/types.d.ts.map +0 -1
  110. package/dist/types.js +0 -1
  111. package/dist/voice/useVoiceConnectOrchestration.d.ts +0 -21
  112. package/dist/voice/useVoiceConnectOrchestration.d.ts.map +0 -1
  113. package/dist/voice/useVoiceConnectOrchestration.js +0 -86
  114. package/dist/voice/useVoiceMicState.d.ts +0 -15
  115. package/dist/voice/useVoiceMicState.d.ts.map +0 -1
  116. package/dist/voice/useVoiceMicState.js +0 -94
  117. package/dist/voice/useVoiceSilenceCommit.d.ts +0 -10
  118. package/dist/voice/useVoiceSilenceCommit.d.ts.map +0 -1
  119. package/dist/voice/useVoiceSilenceCommit.js +0 -67
  120. package/dist/voice/useVoiceTranscriptMessages.d.ts +0 -18
  121. package/dist/voice/useVoiceTranscriptMessages.d.ts.map +0 -1
  122. package/dist/voice/useVoiceTranscriptMessages.js +0 -132
  123. package/dist/voice/useWsRealtimeAudio.d.ts +0 -18
  124. package/dist/voice/useWsRealtimeAudio.d.ts.map +0 -1
  125. package/dist/voice/useWsRealtimeAudio.js +0 -102
  126. package/dist/voice/voiceMicConstants.d.ts +0 -4
  127. package/dist/voice/voiceMicConstants.d.ts.map +0 -1
  128. package/dist/voice/voiceMicConstants.js +0 -10
  129. package/dist/voice/voiceUserBubble.d.ts +0 -10
  130. package/dist/voice/voiceUserBubble.d.ts.map +0 -1
  131. package/dist/voice/voiceUserBubble.js +0 -52
  132. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts +0 -23
  133. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts.map +0 -1
  134. package/dist/voice/ws/BrowserWsPcmPlayer.js +0 -137
  135. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts +0 -17
  136. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts.map +0 -1
  137. package/dist/voice/ws/BrowserWsPcmRecorder.js +0 -71
  138. package/dist/voice/ws/float32ToPcm16.d.ts +0 -2
  139. package/dist/voice/ws/float32ToPcm16.d.ts.map +0 -1
  140. package/dist/voice/ws/float32ToPcm16.js +0 -8
  141. package/dist/voice/ws/voiceSilenceConstants.d.ts +0 -5
  142. package/dist/voice/ws/voiceSilenceConstants.d.ts.map +0 -1
  143. package/dist/voice/ws/voiceSilenceConstants.js +0 -4
  144. package/dist/voice/ws/wsRealtimeConstants.d.ts +0 -2
  145. package/dist/voice/ws/wsRealtimeConstants.d.ts.map +0 -1
  146. package/dist/voice/ws/wsRealtimeConstants.js +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAyB/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAM/B,eAAO,MAAM,UAAU,0BAMtB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAwvGlD,CAAC"}
1
+ {"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA6B/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAM/B,eAAO,MAAM,UAAU,0BAMtB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CA25FlD,CAAC"}
@@ -5,6 +5,7 @@ import * as React from 'react';
5
5
  import { flushSync } from 'react-dom';
6
6
  import { v4 as uuidv4 } from 'uuid';
7
7
  import { createNxtlinqApi, setApiHosts, synthesizeSpeechToBuffer, streamSpeechToAudioContext, useLocalStorage, useSessionStorage, useSpeechToTextFromMic, useVoiceMode, metakeepClient, getEthers, sleep, walletTextUtils, } from '@bytexbyte/nxtlinq-ai-agent-web-development';
8
+ import { authorizeTextFrontendTool, hasRecordedWalletVerification, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
8
9
  const MIC_ENABLED_SESSION_KEY = 'chatbot-mic-enabled';
9
10
  const ChatBotContext = React.createContext(undefined);
10
11
  export const useChatBot = () => {
@@ -30,9 +31,7 @@ idvBannerDismissSeconds = 86400,
30
31
  // 24 hours in seconds
31
32
  isStopRecordingOnSend = false,
32
33
  // Custom error message to display in chat
33
- customError,
34
- // PII display mode
35
- piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
34
+ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
36
35
  // Set API hosts immediately based on environment (before any API calls)
37
36
  setApiHosts(environment);
38
37
  const nxtlinqApi = React.useMemo(() => (serviceToken || getAuthToken
@@ -769,6 +768,11 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
769
768
  // AI Model related state
770
769
  const [modelsFromApi, setModelsFromApi] = React.useState([]);
771
770
  const [selectedModelIndex, setSelectedModelIndex] = useLocalStorage('selectedAIModelIndex', 0);
771
+ // PII protection status: fetched from the service's own config (via serviceId + credentials
772
+ // already provided to the SDK), not passed in by the host app. Defaults to off until the fetch
773
+ // below resolves, matching how modelsFromApi starts empty.
774
+ const [enablePiiProtection, setEnablePiiProtection] = React.useState(false);
775
+ const piiDisplayMode = enablePiiProtection ? 'redacted' : 'plain';
772
776
  // Use models from API only (no default fallback)
773
777
  // This ensures SDK always uses Dashboard-configured models
774
778
  const effectiveAvailableModels = React.useMemo(() => {
@@ -787,6 +791,9 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
787
791
  if ('availableModels' in result && Array.isArray(result.availableModels)) {
788
792
  setModelsFromApi(result.availableModels);
789
793
  }
794
+ if ('enablePiiProtection' in result) {
795
+ setEnablePiiProtection(!!result.enablePiiProtection);
796
+ }
790
797
  }
791
798
  catch (error) {
792
799
  console.error('Failed to fetch available models from API:', error);
@@ -862,14 +869,18 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
862
869
  }
863
870
  setIsAITLoading(true);
864
871
  try {
872
+ let walletAllowsAITLookup = !requireWalletIDVVerification;
865
873
  // Get wallet info first - always try to get wallet info if we have a token
866
874
  if (nxtlinqAITServiceAccessToken) {
867
875
  try {
868
876
  const walletResponse = await nxtlinqApi.wallet.getWallet({ address: hitAddress }, nxtlinqAITServiceAccessToken);
869
877
  if (!('error' in walletResponse)) {
870
878
  setWalletInfo(walletResponse);
879
+ walletAllowsAITLookup = !requireWalletIDVVerification
880
+ || hasRecordedWalletVerification(walletResponse);
871
881
  }
872
882
  else {
883
+ setWalletInfo(null);
873
884
  // Check if the error is due to invalid/expired token
874
885
  if (walletResponse.error.includes('Invalid or expired token')) {
875
886
  console.log('Token appears to be invalid during wallet info fetch, clearing it');
@@ -878,9 +889,17 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
878
889
  }
879
890
  }
880
891
  catch (error) {
892
+ setWalletInfo(null);
881
893
  console.error('Failed to fetch wallet info:', error);
882
894
  }
883
895
  }
896
+ // AIT existence is not identity verification. In strict mode, stop before
897
+ // the legacy AIT lookup can synthesize a custom wallet record.
898
+ if (nxtlinqAITServiceAccessToken && !walletAllowsAITLookup) {
899
+ setAit(null);
900
+ setPermissions([]);
901
+ return;
902
+ }
884
903
  // Only try to fetch AIT if we have a token
885
904
  if (nxtlinqAITServiceAccessToken) {
886
905
  const response = await nxtlinqApi.ait.getAITByServiceIdAndController({
@@ -1112,338 +1131,67 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
1112
1131
  }
1113
1132
  };
1114
1133
  // Check permissions
1115
- const hasPermission = async (requiredPermission, autoRetry = true, onAutoConnect, onAutoSignIn) => {
1134
+ const hasPermission = async (requiredPermission) => {
1116
1135
  // Use refs to get latest state values
1117
1136
  const currentHitAddress = hitAddressRef.current;
1118
- const currentAit = aitRef.current;
1119
- const currentPermissions = permissionsRef.current;
1120
1137
  const currentToken = nxtlinqAITServiceAccessTokenRef.current;
1121
- if (!currentHitAddress) {
1122
- if (autoRetry) {
1123
- setIsLoading(false); // Stop thinking before showing message
1124
- setMessages(prev => [...prev, {
1125
- id: Date.now().toString(),
1126
- content: walletTextUtils.getWalletText('Please connect your HIT wallet to continue.', serviceId),
1127
- role: 'assistant',
1128
- timestamp: new Date().toISOString(),
1129
- button: 'connectWallet'
1130
- }]);
1131
- try {
1132
- setIsAutoConnecting(true); // Mark as auto-connecting
1133
- await connectWallet(false); // Don't show sign-in message yet
1134
- setIsAutoConnecting(false); // Clear auto-connecting state
1135
- // Show brief success message for auto-connect
1136
- showSuccess(walletTextUtils.getWalletText('Auto wallet connection successful', serviceId));
1137
- onAutoConnect?.(); // Call callback if provided
1138
- await new Promise(resolve => setTimeout(resolve, 2000));
1139
- // After auto connect, if not signed in, then auto sign-in
1140
- const tokenAfterConnect = nxtlinqAITServiceAccessTokenRef.current;
1141
- if (!tokenAfterConnect) {
1142
- setIsAutoConnecting(true);
1143
- await signInWallet(false);
1144
- onAutoSignIn?.(); // Call callback if provided
1145
- setIsAutoConnecting(false);
1146
- showSuccess(walletTextUtils.getWalletText('Auto sign-in successful after wallet connect', serviceId));
1147
- await refreshAIT();
1148
- // Wait for AIT to be fully loaded with polling
1149
- let attempts = 0;
1150
- const maxAttempts = 5;
1151
- while (!aitRef.current && attempts < maxAttempts) {
1152
- await new Promise(resolve => setTimeout(resolve, 2000));
1153
- attempts++;
1154
- }
1155
- }
1156
- // If connection (and sign-in if needed) successful, continue with permission check
1157
- const result = await hasPermission(requiredPermission, false);
1158
- return result;
1159
- }
1160
- catch (error) {
1161
- console.error('Failed to auto-connect wallet:', error);
1162
- setIsAutoConnecting(false); // Clear auto-connecting state on error
1163
- return false;
1164
- }
1165
- }
1166
- // If autoRetry is false, don't show message again, just return false
1167
- return false;
1168
- }
1169
- if (!currentToken) {
1170
- if (autoRetry) {
1171
- setIsLoading(false); // Stop thinking before showing message
1172
- setMessages(prev => [...prev, {
1173
- id: Date.now().toString(),
1174
- content: walletTextUtils.getWalletText('Please sign in with your HIT wallet to continue.', serviceId),
1175
- role: 'assistant',
1176
- timestamp: new Date().toISOString(),
1177
- button: 'signIn'
1178
- }]);
1179
- try {
1180
- setIsAutoConnecting(true); // Mark as auto-signing
1181
- await signInWallet(false); // Don't show success message yet
1182
- onAutoSignIn?.(); // Call callback if provided
1183
- setIsAutoConnecting(false); // Clear auto-signing state
1184
- // Show brief success message for auto-sign-in
1185
- showSuccess('Auto sign-in successful');
1186
- // Ensure AIT is refreshed after sign-in
1187
- await refreshAIT();
1188
- // Wait for AIT to be fully loaded with polling
1189
- let attempts = 0;
1190
- const maxAttempts = 5; // Wait up to 10 seconds (5 * 2000ms)
1191
- while (!aitRef.current && attempts < maxAttempts) {
1192
- await new Promise(resolve => setTimeout(resolve, 2000));
1193
- attempts++;
1194
- }
1195
- // Only continue if AIT is actually loaded
1196
- if (aitRef.current) {
1197
- // Wait a bit more to ensure permissions are also loaded
1198
- await new Promise(resolve => setTimeout(resolve, 2000));
1199
- // If sign-in successful, continue with permission check
1200
- const result = await hasPermission(requiredPermission, false);
1201
- return result;
1202
- }
1203
- else {
1204
- return false;
1205
- }
1206
- }
1207
- catch (error) {
1208
- console.error('Failed to auto-sign-in wallet:', error);
1209
- setIsAutoConnecting(false); // Clear auto-signing state on error
1210
- return false;
1211
- }
1212
- }
1213
- // If autoRetry is false, don't show message again, just return false
1214
- return false;
1215
- }
1216
- try {
1217
- const payload = JSON.parse(atob(currentToken.split('.')[1]));
1218
- const address = payload.address;
1219
- if (address !== currentHitAddress) {
1220
- setNxtlinqAITServiceAccessToken('');
1221
- if (autoRetry) {
1222
- setIsLoading(false); // Stop thinking before showing message
1223
- setMessages(prev => [...prev, {
1224
- id: Date.now().toString(),
1225
- content: walletTextUtils.getWalletText('Wallet address mismatch. Please sign in with the correct wallet.', serviceId),
1226
- role: 'assistant',
1227
- timestamp: new Date().toISOString(),
1228
- button: 'signIn'
1229
- }]);
1230
- try {
1231
- setIsAutoConnecting(true); // Mark as auto-signing
1232
- await signInWallet(false); // Don't show success message yet
1233
- onAutoSignIn?.(); // Call callback if provided
1234
- setIsAutoConnecting(false); // Clear auto-signing state
1235
- // Show brief success message for auto-sign-in after address mismatch
1236
- showSuccess('Auto sign-in successful after address mismatch');
1237
- // Ensure AIT is refreshed after sign-in
1238
- await refreshAIT();
1239
- // Wait for AIT to be fully loaded with polling
1240
- let attempts = 0;
1241
- const maxAttempts = 5; // Wait up to 10 seconds (5 * 2000ms)
1242
- while (!aitRef.current && attempts < maxAttempts) {
1243
- await new Promise(resolve => setTimeout(resolve, 2000));
1244
- attempts++;
1245
- }
1246
- // Only continue if AIT is actually loaded
1247
- if (aitRef.current) {
1248
- // Wait a bit more to ensure permissions are also loaded
1249
- await new Promise(resolve => setTimeout(resolve, 2000));
1250
- // If sign-in successful, continue with permission check
1251
- const result = await hasPermission(requiredPermission, false);
1252
- return result;
1253
- }
1254
- else {
1255
- return false;
1256
- }
1257
- }
1258
- catch (error) {
1259
- console.error('Failed to auto-sign-in after address mismatch:', error);
1260
- setIsAutoConnecting(false); // Clear auto-signing state on error
1261
- return false;
1262
- }
1263
- }
1264
- // If autoRetry is false, don't show message again, just return false
1265
- return false;
1266
- }
1267
- }
1268
- catch (error) {
1269
- console.error('Error parsing token:', error);
1270
- setNxtlinqAITServiceAccessToken('');
1271
- if (autoRetry) {
1272
- setIsLoading(false); // Stop thinking before showing message
1273
- setMessages(prev => [...prev, {
1274
- id: Date.now().toString(),
1275
- content: walletTextUtils.getWalletText('Invalid wallet session. Please sign in again.', serviceId),
1276
- role: 'assistant',
1277
- timestamp: new Date().toISOString(),
1278
- button: 'signIn'
1279
- }]);
1280
- try {
1281
- setIsAutoConnecting(true); // Mark as auto-signing
1282
- await signInWallet(false); // Don't show success message yet
1283
- onAutoSignIn?.(); // Call callback if provided
1284
- setIsAutoConnecting(false); // Clear auto-signing state
1285
- // Show brief success message for auto-sign-in after token parse error
1286
- showSuccess('Auto sign-in successful after token error');
1287
- // Ensure AIT is refreshed after sign-in
1288
- await refreshAIT();
1289
- // Wait for AIT to be fully loaded with polling
1290
- let attempts = 0;
1291
- const maxAttempts = 5; // Wait up to 10 seconds (5 * 2000ms)
1292
- while (!aitRef.current && attempts < maxAttempts) {
1293
- await new Promise(resolve => setTimeout(resolve, 2000));
1294
- attempts++;
1295
- }
1296
- // Only continue if AIT is actually loaded
1297
- if (aitRef.current) {
1298
- // Wait a bit more to ensure permissions are also loaded
1299
- await new Promise(resolve => setTimeout(resolve, 2000));
1300
- // If sign-in successful, continue with permission check
1301
- const result = await hasPermission(requiredPermission, false);
1302
- return result;
1303
- }
1304
- else {
1305
- return false;
1306
- }
1307
- }
1308
- catch (signInError) {
1309
- console.error('Failed to auto-sign-in after token parse error:', signInError);
1310
- setIsAutoConnecting(false); // Clear auto-signing state on error
1311
- return false;
1312
- }
1313
- }
1314
- // If autoRetry is false, don't show message again, just return false
1315
- return false;
1316
- }
1317
- if (!currentAit) {
1318
- // Show loading message if AIT is still loading
1319
- if (isAITLoading) {
1320
- setIsLoading(false); // Stop thinking before showing message
1321
- setMessages(prev => [...prev, {
1322
- id: Date.now().toString(),
1323
- content: walletTextUtils.getWalletText('Loading your wallet configuration... Please wait a moment.', serviceId),
1324
- role: 'assistant',
1325
- timestamp: new Date().toISOString()
1326
- }]);
1327
- return false;
1328
- }
1329
- // If AIT is not loaded but we have a token, try to refresh it once
1330
- if (currentToken && !isAITLoading) {
1331
- try {
1332
- await refreshAIT();
1333
- // Wait for AIT to be loaded with polling
1334
- let attempts = 0;
1335
- const maxAttempts = 5; // Wait up to 10 seconds (5 * 2000ms)
1336
- while (!aitRef.current && attempts < maxAttempts) {
1337
- await new Promise(resolve => setTimeout(resolve, 2000));
1338
- attempts++;
1339
- }
1340
- // Check again after refresh
1341
- if (!aitRef.current) {
1342
- setIsLoading(false); // Stop thinking before showing message
1343
- setMessages(prev => [...prev, {
1344
- id: Date.now().toString(),
1345
- content: walletTextUtils.getWalletText('No AIT found for your wallet. Please click the settings button (⚙️) to configure your AIT permissions.', serviceId),
1346
- role: 'assistant',
1347
- timestamp: new Date().toISOString()
1348
- }]);
1349
- return false;
1350
- }
1351
- }
1352
- catch (error) {
1353
- console.error('Failed to refresh AIT during permission check:', error);
1354
- setIsLoading(false); // Stop thinking before showing message
1355
- setMessages(prev => [...prev, {
1356
- id: Date.now().toString(),
1357
- content: 'No AIT found for your wallet. Please click the settings button (⚙️) to configure your AIT permissions.',
1358
- role: 'assistant',
1359
- timestamp: new Date().toISOString()
1360
- }]);
1361
- return false;
1362
- }
1363
- }
1364
- else {
1365
- setIsLoading(false); // Stop thinking before showing message
1366
- setMessages(prev => [...prev, {
1367
- id: Date.now().toString(),
1368
- content: 'No AIT found for your wallet. Please click the settings button (⚙️) to configure your AIT permissions.',
1369
- role: 'assistant',
1370
- timestamp: new Date().toISOString()
1371
- }]);
1372
- return false;
1373
- }
1374
- }
1375
- if (availablePermissions.length === 0) {
1376
- setIsLoading(false); // Stop thinking before showing message
1377
- setMessages(prev => [...prev, {
1378
- id: Date.now().toString(),
1379
- content: `No permissions available for your current identity provider. Please check your service configuration or contact support. Service ID: ${serviceId}, Permission Group: ${permissionGroup || 'None'}`,
1380
- role: 'assistant',
1381
- timestamp: new Date().toISOString()
1382
- }]);
1383
- return false;
1384
- }
1385
- const checkToolPermissionResult = await nxtlinqApi.agent.checkToolPermission({
1138
+ const authorization = await authorizeTextFrontendTool({
1139
+ api: nxtlinqApi,
1140
+ serviceId,
1141
+ toolName: requiredPermission,
1142
+ snapshot: {
1143
+ walletAddress: currentHitAddress,
1144
+ walletToken: currentToken,
1145
+ // Legacy AIT issuance is unscoped (`externalId=''`). Do not impose a
1146
+ // wallet-address subject until issuance/migration supports it.
1147
+ externalId: undefined,
1148
+ requireWalletIDVVerification,
1149
+ loading: isAITLoading || isAutoConnecting,
1150
+ },
1386
1151
  ...authFields(),
1387
- aitToken: currentToken,
1388
- controller: currentHitAddress,
1389
- toolName: requiredPermission
1152
+ customUsername: (!requireWalletIDVVerification && customUsername)
1153
+ ? getFinalCustomUsername(customUsername)
1154
+ : undefined,
1390
1155
  });
1391
- if ('error' in checkToolPermissionResult) {
1392
- // Check if AIT is still loading or if we just auto-connected
1393
- if (isAITLoading || isAutoConnecting) {
1394
- setIsLoading(false); // Stop thinking before showing message
1395
- setMessages(prev => [...prev, {
1396
- id: Date.now().toString(),
1397
- content: walletTextUtils.getWalletText('Loading your wallet configuration... Please wait a moment.', serviceId),
1398
- role: 'assistant',
1399
- timestamp: new Date().toISOString()
1400
- }]);
1401
- return false;
1402
- }
1403
- // Refresh service permissions before judging; use latest result to decide message
1404
- const freshAvailablePermissions = await fetchAvailablePermissions();
1405
- const latestAvailablePermissions = freshAvailablePermissions ?? availablePermissions;
1406
- const requiredPermission = checkToolPermissionResult.requiredPermission;
1407
- const isInServiceList = latestAvailablePermissions.some((p) => p.label === requiredPermission);
1408
- // Permission not in service's available list → "not available for your current identity provider"
1409
- if (!isInServiceList) {
1410
- setIsLoading(false); // Stop thinking before showing message
1411
- setMessages(prev => [...prev, {
1412
- id: Date.now().toString(),
1413
- content: `This permission (${requiredPermission}) is not available for your current identity provider.`,
1414
- role: 'assistant',
1415
- timestamp: new Date().toISOString()
1416
- }]);
1417
- return false;
1418
- }
1419
- // AIT loaded but permissions empty (no AIT found)
1420
- if (currentAit && currentPermissions.length === 0) {
1421
- setIsLoading(false); // Stop thinking before showing message
1422
- setMessages(prev => [...prev, {
1423
- id: Date.now().toString(),
1424
- content: 'No AIT found for your wallet. Please click the settings button (⚙️) to configure your AIT permissions.',
1425
- role: 'assistant',
1426
- timestamp: new Date().toISOString()
1427
- }]);
1428
- return false;
1429
- }
1430
- // User has AIT but hasn't enabled this permission → prompt to enable
1431
- setIsLoading(false); // Stop thinking before showing message
1432
- const permissionMsg = `You don't have the required AIT permission: ${requiredPermission}. Would you like to enable AIT permission?`;
1433
- setMessages(prev => [
1434
- ...prev,
1435
- {
1436
- id: Date.now().toString(),
1437
- content: permissionMsg,
1438
- role: 'assistant',
1439
- timestamp: new Date().toISOString(),
1440
- button: 'enableAIT',
1441
- metadata: { requiredPermission }
1442
- }
1443
- ]);
1444
- return false;
1445
- }
1446
- return true;
1156
+ if (authorization.status === 'allowed')
1157
+ return true;
1158
+ setIsLoading(false);
1159
+ const recovery = {
1160
+ id: Date.now().toString(),
1161
+ content: 'Authorization is temporarily unavailable. Please try again.',
1162
+ role: 'assistant',
1163
+ timestamp: new Date().toISOString(),
1164
+ };
1165
+ switch (authorization.status) {
1166
+ case 'wallet_disconnected':
1167
+ recovery.content = walletTextUtils.getWalletText('Please connect your HIT wallet to continue.', serviceId);
1168
+ recovery.button = 'connectWallet';
1169
+ break;
1170
+ case 'wallet_signed_out':
1171
+ recovery.content = walletTextUtils.getWalletText('Please sign in with your HIT wallet to continue.', serviceId);
1172
+ recovery.button = 'signIn';
1173
+ break;
1174
+ case 'wallet_session_invalid':
1175
+ recovery.content = walletTextUtils.getWalletText('Invalid wallet session. Please sign in again.', serviceId);
1176
+ recovery.button = 'signIn';
1177
+ break;
1178
+ case 'wallet_verification_required':
1179
+ recovery.content = 'Please verify your wallet identity before using this tool.';
1180
+ recovery.button = 'verifyWallet';
1181
+ break;
1182
+ case 'ait_not_found':
1183
+ recovery.content = 'No AIT found for your wallet. Please open settings to configure your AIT.';
1184
+ break;
1185
+ case 'permission_denied':
1186
+ recovery.content = `You don't have the required AIT permission: ${authorization.requiredPermission}. Would you like to enable AIT permission?`;
1187
+ recovery.button = 'enableAIT';
1188
+ recovery.metadata = { requiredPermission: authorization.requiredPermission };
1189
+ break;
1190
+ case 'authorization_unavailable':
1191
+ break;
1192
+ }
1193
+ setMessages(prev => [...prev, recovery]);
1194
+ return false;
1447
1195
  };
1448
1196
  // AI Model related functions
1449
1197
  const handleModelChange = React.useCallback((modelIndex) => {
@@ -1485,6 +1233,9 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
1485
1233
  if (!hasContent || isLoading)
1486
1234
  return;
1487
1235
  setPendingAutoTts(null);
1236
+ const turnExternalId = typeof window !== 'undefined'
1237
+ ? localStorage.getItem('walletAddress') || undefined
1238
+ : hitAddressRef.current || undefined;
1488
1239
  const currentModel = getCurrentModel();
1489
1240
  // Initialize with current model, will be updated with actual model from backend response
1490
1241
  let actualModelUsed = currentModel.value;
@@ -1556,7 +1307,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
1556
1307
  model: currentModel.value,
1557
1308
  ...authFields(),
1558
1309
  pseudoId: pseudoId,
1559
- externalId: localStorage.getItem('walletAddress') || undefined,
1310
+ externalId: turnExternalId,
1560
1311
  customUserInfo,
1561
1312
  customUsername,
1562
1313
  message: content || (attachments && attachments.length > 0 ? `Uploaded ${attachments.length} file(s)` : ''),
@@ -1770,82 +1521,10 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
1770
1521
  const toolUse = response.toolCall.toolUse;
1771
1522
  let toolMsg = '';
1772
1523
  if (onToolUse) {
1773
- let wasAutoConnected = false;
1774
- let wasAutoSignedIn = false;
1775
- // Added: Mark if permission denied due to missing AIT permission
1776
- let permissionDenied = false;
1777
- // Use requiredPermission from response if available, otherwise fall back to toolUse.name
1778
- const permissionToCheck = response?.requiredPermission || toolUse.name;
1779
- const isToolAllowed = await hasPermission(permissionToCheck, true, () => { wasAutoConnected = true; }, () => { wasAutoSignedIn = true; });
1780
- // If currentPermissions does not include permissionToCheck and availablePermissionLabels includes permissionToCheck, it means AIT permission is missing
1781
- if (!isToolAllowed && !permissions.includes(permissionToCheck) && availablePermissions.map(p => p.label).includes(permissionToCheck)) {
1782
- permissionDenied = true;
1783
- }
1524
+ const isToolAllowed = await hasPermission(toolUse.name);
1525
+ // Typed preflight already emitted the only permitted recovery UI.
1784
1526
  if (!isToolAllowed) {
1785
- // If permission denied due to missing AIT permission return
1786
- if (permissionDenied) {
1787
- setIsLoading(false);
1788
- return;
1789
- }
1790
- if (isSemiAutomaticMode) {
1791
- setIsLoading(false);
1792
- setMessages(prev => [...prev, {
1793
- id: Date.now().toString(),
1794
- content: 'Click button to continue using tool',
1795
- role: 'assistant',
1796
- timestamp: new Date().toISOString(),
1797
- button: 'continue'
1798
- }]);
1799
- return;
1800
- }
1801
- else {
1802
- // Only retry for auto-connect/auto-sign-in scenarios
1803
- if (wasAutoConnected && retryCount < 1) {
1804
- // Clear loading state and retry immediately
1805
- setIsLoading(false);
1806
- // Check if wallet is already signed in
1807
- const currentToken = nxtlinqAITServiceAccessTokenRef.current;
1808
- if (!currentToken) {
1809
- // If not signed in, directly retry the message without waiting for AIT
1810
- setTimeout(() => {
1811
- sendMessage(content, retryCount + 1, isPresetMessage);
1812
- }, 2000);
1813
- }
1814
- else {
1815
- // If already signed in, wait for AIT to be fully loaded before retrying
1816
- setTimeout(async () => {
1817
- // Wait for AIT to be loaded if needed
1818
- if (!aitRef.current && nxtlinqAITServiceAccessTokenRef.current) {
1819
- await refreshAIT();
1820
- }
1821
- // Wait for AIT to be fully loaded with polling
1822
- let attempts = 0;
1823
- const maxAttempts = 5; // Wait up to 10 seconds (5 * 2000ms)
1824
- while (!aitRef.current && attempts < maxAttempts) {
1825
- await new Promise(resolve => setTimeout(resolve, 2000));
1826
- attempts++;
1827
- }
1828
- // Only retry if AIT is actually loaded
1829
- if (aitRef.current) {
1830
- // Wait a bit more to ensure permissions are also loaded
1831
- await new Promise(resolve => setTimeout(resolve, 3000));
1832
- sendMessage(content, retryCount + 1, isPresetMessage);
1833
- }
1834
- }, 2000);
1835
- }
1836
- }
1837
- return;
1838
- }
1839
- }
1840
- if (isSemiAutomaticMode && wasAutoSignedIn) {
1841
1527
  setIsLoading(false);
1842
- setMessages(prev => [...prev, {
1843
- id: Date.now().toString(),
1844
- content: 'Click button to continue using tool',
1845
- role: 'assistant',
1846
- timestamp: new Date().toISOString(),
1847
- button: 'continue'
1848
- }]);
1849
1528
  return;
1850
1529
  }
1851
1530
  // Create streaming message for tool execution
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { ChatBot } from './ChatBot';
2
2
  export { ChatBotProvider, useChatBot } from './context/ChatBotContext';
3
3
  export { ChatBotUI, MessageInput, MessageList, ModelSelector, NotificationModal, PermissionForm, PresetMessages, BerifyMeModal, } from './ui/index';
4
4
  export type { AIModel, AITMetadata, ChatBotContextType, ChatBotProps, NovaError, NovaResponse, ToolCall, ToolUse, PresetMessage, } from './types/ChatBotTypes';
5
- export type { AgentEnvironment, AgentConfig, Attachment, AgentResponse, Message, SendMessageOptions, NxtlinqAgentSnapshot, VoiceSession, VoiceStatus, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
6
- export { NxtlinqAgent, setApiHosts, VoiceNotSupportedError, STORAGE_KEYS, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
5
+ export type { AgentEnvironment, AgentConfig, Attachment, AgentResponse, Message, SendMessageOptions, NxtlinqAgentSnapshot, TextToolAuthorizationSnapshot, TextToolAuthorizationOutcome, VoiceSession, VoiceStatus, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
6
+ export { NxtlinqAgent, setApiHosts, VoiceNotSupportedError, STORAGE_KEYS, authorizeTextFrontendTool, hasRecordedWalletVerification, validateWalletSession, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
7
7
  export { createNxtlinqApi, useLocalStorage, useSessionStorage, useSpeechToTextFromMic, useVoiceMode, metakeepClient, getEthers, sleep, walletTextUtils, } from '@bytexbyte/nxtlinq-ai-agent-web-development';
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EACL,SAAS,EACT,YAAY,EACZ,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,aAAa,GACd,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,oBAAoB,EACpB,YAAY,EACZ,WAAW,GACZ,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,YAAY,GACb,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,SAAS,EACT,KAAK,EACL,eAAe,GAChB,MAAM,6CAA6C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EACL,SAAS,EACT,YAAY,EACZ,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,aAAa,GACd,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,aAAa,EACb,OAAO,EACP,kBAAkB,EAClB,oBAAoB,EACpB,6BAA6B,EAC7B,4BAA4B,EAC5B,YAAY,EACZ,WAAW,GACZ,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EACL,YAAY,EACZ,WAAW,EACX,sBAAsB,EACtB,YAAY,EACZ,yBAAyB,EACzB,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,8CAA8C,CAAC;AAEtD,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACtB,YAAY,EACZ,cAAc,EACd,SAAS,EACT,KAAK,EACL,eAAe,GAChB,MAAM,6CAA6C,CAAC"}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ChatBot } from './ChatBot';
2
2
  export { ChatBotProvider, useChatBot } from './context/ChatBotContext';
3
3
  export { ChatBotUI, MessageInput, MessageList, ModelSelector, NotificationModal, PermissionForm, PresetMessages, BerifyMeModal, } from './ui/index';
4
- export { NxtlinqAgent, setApiHosts, VoiceNotSupportedError, STORAGE_KEYS, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
4
+ export { NxtlinqAgent, setApiHosts, VoiceNotSupportedError, STORAGE_KEYS, authorizeTextFrontendTool, hasRecordedWalletVerification, validateWalletSession, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
5
5
  export { createNxtlinqApi, useLocalStorage, useSessionStorage, useSpeechToTextFromMic, useVoiceMode, metakeepClient, getEthers, sleep, walletTextUtils, } from '@bytexbyte/nxtlinq-ai-agent-web-development';