@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.4.3 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/authorizationLoadingState.d.ts +9 -0
- package/dist/authorizationLoadingState.d.ts.map +1 -0
- package/dist/authorizationLoadingState.js +15 -0
- package/dist/context/ChatBotContext.d.ts.map +1 -1
- package/dist/context/ChatBotContext.js +35 -2
- package/package.json +1 -1
- package/src/authorizationLoadingState.ts +21 -0
- package/src/context/ChatBotContext.tsx +39 -2
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class AuthorizationLoadingState {
|
|
2
|
+
private aitLoading;
|
|
3
|
+
private autoConnecting;
|
|
4
|
+
constructor(aitLoading?: boolean, autoConnecting?: boolean);
|
|
5
|
+
setAITLoading(value: boolean): void;
|
|
6
|
+
setAutoConnecting(value: boolean): void;
|
|
7
|
+
isLoading(): boolean;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=authorizationLoadingState.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorizationLoadingState.d.ts","sourceRoot":"","sources":["../src/authorizationLoadingState.ts"],"names":[],"mappings":"AAAA,qBAAa,yBAAyB;IACpC,OAAO,CAAC,UAAU,CAAU;IAC5B,OAAO,CAAC,cAAc,CAAU;gBAEpB,UAAU,UAAQ,EAAE,cAAc,UAAQ;IAKtD,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAInC,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAIvC,SAAS,IAAI,OAAO;CAGrB"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class AuthorizationLoadingState {
|
|
2
|
+
constructor(aitLoading = false, autoConnecting = false) {
|
|
3
|
+
this.aitLoading = aitLoading;
|
|
4
|
+
this.autoConnecting = autoConnecting;
|
|
5
|
+
}
|
|
6
|
+
setAITLoading(value) {
|
|
7
|
+
this.aitLoading = value;
|
|
8
|
+
}
|
|
9
|
+
setAutoConnecting(value) {
|
|
10
|
+
this.autoConnecting = value;
|
|
11
|
+
}
|
|
12
|
+
isLoading() {
|
|
13
|
+
return this.aitLoading || this.autoConnecting;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA8B/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA8B/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAQ/B,eAAO,MAAM,UAAU,0BAMtB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAw+FlD,CAAC"}
|
|
@@ -6,6 +6,7 @@ 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
8
|
import { authorizeTextFrontendTool, hasRecordedWalletVerification, validateWalletSession, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
|
|
9
|
+
import { AuthorizationLoadingState } from '../authorizationLoadingState';
|
|
9
10
|
import { PendingTextToolRetryController } from '../pendingTextToolRetry';
|
|
10
11
|
const MIC_ENABLED_SESSION_KEY = 'chatbot-mic-enabled';
|
|
11
12
|
const ChatBotContext = React.createContext(undefined);
|
|
@@ -145,6 +146,7 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
145
146
|
const permissionsRef = React.useRef(permissions);
|
|
146
147
|
const nxtlinqAITServiceAccessTokenRef = React.useRef(nxtlinqAITServiceAccessToken);
|
|
147
148
|
const signerRef = React.useRef(signer);
|
|
149
|
+
const authorizationLoadingStateRef = React.useRef(new AuthorizationLoadingState(isAITLoading, isAutoConnecting));
|
|
148
150
|
const pendingTextToolRetryRef = React.useRef(new PendingTextToolRetryController());
|
|
149
151
|
const sendMessageRef = React.useRef(async () => { });
|
|
150
152
|
const retryPendingTextTool = React.useCallback(() => {
|
|
@@ -483,6 +485,12 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
483
485
|
React.useEffect(() => {
|
|
484
486
|
permissionsRef.current = permissions;
|
|
485
487
|
}, [permissions]);
|
|
488
|
+
React.useEffect(() => {
|
|
489
|
+
authorizationLoadingStateRef.current.setAITLoading(isAITLoading);
|
|
490
|
+
}, [isAITLoading]);
|
|
491
|
+
React.useEffect(() => {
|
|
492
|
+
authorizationLoadingStateRef.current.setAutoConnecting(isAutoConnecting);
|
|
493
|
+
}, [isAutoConnecting]);
|
|
486
494
|
React.useEffect(() => {
|
|
487
495
|
nxtlinqAITServiceAccessTokenRef.current = nxtlinqAITServiceAccessToken;
|
|
488
496
|
}, [nxtlinqAITServiceAccessToken]);
|
|
@@ -875,12 +883,16 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
875
883
|
const currentHitAddress = hitAddressRef.current || hitAddress;
|
|
876
884
|
const currentToken = nxtlinqAITServiceAccessTokenRef.current || nxtlinqAITServiceAccessToken;
|
|
877
885
|
if (!currentHitAddress) {
|
|
886
|
+
aitRef.current = null;
|
|
887
|
+
permissionsRef.current = [];
|
|
878
888
|
setAit(null);
|
|
879
889
|
setPermissions([]);
|
|
880
890
|
setWalletInfo(null);
|
|
891
|
+
authorizationLoadingStateRef.current.setAITLoading(false);
|
|
881
892
|
setIsAITLoading(false);
|
|
882
893
|
return;
|
|
883
894
|
}
|
|
895
|
+
authorizationLoadingStateRef.current.setAITLoading(true);
|
|
884
896
|
setIsAITLoading(true);
|
|
885
897
|
try {
|
|
886
898
|
let walletAllowsAITLookup = !requireWalletIDVVerification;
|
|
@@ -910,6 +922,8 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
910
922
|
// AIT existence is not identity verification. In strict mode, stop before
|
|
911
923
|
// the legacy AIT lookup can synthesize a custom wallet record.
|
|
912
924
|
if (currentToken && !walletAllowsAITLookup) {
|
|
925
|
+
aitRef.current = null;
|
|
926
|
+
permissionsRef.current = [];
|
|
913
927
|
setAit(null);
|
|
914
928
|
setPermissions([]);
|
|
915
929
|
return;
|
|
@@ -923,28 +937,39 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
923
937
|
}, currentToken);
|
|
924
938
|
if ('error' in response) {
|
|
925
939
|
console.error('Failed to fetch AIT:', response.error);
|
|
940
|
+
aitRef.current = null;
|
|
941
|
+
permissionsRef.current = [];
|
|
926
942
|
setAit(null);
|
|
927
943
|
setPermissions([]);
|
|
928
944
|
return;
|
|
929
945
|
}
|
|
946
|
+
aitRef.current = response;
|
|
930
947
|
setAit(response);
|
|
931
948
|
if (!isPermissionFormOpen || forceUpdatePermissions) {
|
|
932
949
|
const newPermissions = response.metadata?.permissions || [];
|
|
950
|
+
permissionsRef.current = newPermissions;
|
|
933
951
|
setPermissions(newPermissions);
|
|
934
952
|
}
|
|
935
953
|
}
|
|
936
954
|
else {
|
|
937
955
|
// No token available, clear AIT data
|
|
956
|
+
aitRef.current = null;
|
|
957
|
+
permissionsRef.current = [];
|
|
938
958
|
setAit(null);
|
|
939
959
|
setPermissions([]);
|
|
940
960
|
}
|
|
941
961
|
}
|
|
942
962
|
catch (error) {
|
|
943
963
|
console.error('Failed to fetch AIT:', error);
|
|
964
|
+
aitRef.current = null;
|
|
965
|
+
permissionsRef.current = [];
|
|
944
966
|
setAit(null);
|
|
945
967
|
setPermissions([]);
|
|
946
968
|
}
|
|
947
969
|
finally {
|
|
970
|
+
// Keep the authorization snapshot current before refreshAIT resolves.
|
|
971
|
+
// React may not commit setState until the immediate pending-tool retry.
|
|
972
|
+
authorizationLoadingStateRef.current.setAITLoading(false);
|
|
948
973
|
setIsAITLoading(false);
|
|
949
974
|
}
|
|
950
975
|
};
|
|
@@ -1158,7 +1183,9 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
1158
1183
|
// wallet-address subject until issuance/migration supports it.
|
|
1159
1184
|
externalId: undefined,
|
|
1160
1185
|
requireWalletIDVVerification,
|
|
1161
|
-
|
|
1186
|
+
// Use synchronously maintained refs so a retry immediately following
|
|
1187
|
+
// refreshAIT() does not observe the previous React render's loading state.
|
|
1188
|
+
loading: authorizationLoadingStateRef.current.isLoading(),
|
|
1162
1189
|
},
|
|
1163
1190
|
...authFields(),
|
|
1164
1191
|
customUsername: (!requireWalletIDVVerification && customUsername)
|
|
@@ -2223,8 +2250,11 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
2223
2250
|
metadataHash,
|
|
2224
2251
|
metadataCid,
|
|
2225
2252
|
};
|
|
2253
|
+
const nextPermissions = newPermissions || permissions;
|
|
2254
|
+
aitRef.current = aitInfo;
|
|
2255
|
+
permissionsRef.current = nextPermissions;
|
|
2226
2256
|
setAit(aitInfo);
|
|
2227
|
-
setPermissions(
|
|
2257
|
+
setPermissions(nextPermissions);
|
|
2228
2258
|
};
|
|
2229
2259
|
// Auto enable AIT permission
|
|
2230
2260
|
const enableAIT = async (toolName) => {
|
|
@@ -2394,6 +2424,7 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
2394
2424
|
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
2395
2425
|
}, token);
|
|
2396
2426
|
if (!('error' in aitResponse)) {
|
|
2427
|
+
aitRef.current = aitResponse;
|
|
2397
2428
|
setAit(aitResponse);
|
|
2398
2429
|
}
|
|
2399
2430
|
}
|
|
@@ -2435,6 +2466,7 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
2435
2466
|
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
2436
2467
|
}, token);
|
|
2437
2468
|
if (!('error' in aitResponse)) {
|
|
2469
|
+
aitRef.current = aitResponse;
|
|
2438
2470
|
setAit(aitResponse);
|
|
2439
2471
|
}
|
|
2440
2472
|
}
|
|
@@ -2552,6 +2584,7 @@ customError, voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
|
|
|
2552
2584
|
// Set loading state when permission form opens
|
|
2553
2585
|
React.useEffect(() => {
|
|
2554
2586
|
if (isPermissionFormOpen && hitAddress) {
|
|
2587
|
+
authorizationLoadingStateRef.current.setAITLoading(true);
|
|
2555
2588
|
setIsAITLoading(true);
|
|
2556
2589
|
}
|
|
2557
2590
|
}, [isPermissionFormOpen, hitAddress]);
|
package/package.json
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export class AuthorizationLoadingState {
|
|
2
|
+
private aitLoading: boolean;
|
|
3
|
+
private autoConnecting: boolean;
|
|
4
|
+
|
|
5
|
+
constructor(aitLoading = false, autoConnecting = false) {
|
|
6
|
+
this.aitLoading = aitLoading;
|
|
7
|
+
this.autoConnecting = autoConnecting;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
setAITLoading(value: boolean): void {
|
|
11
|
+
this.aitLoading = value;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
setAutoConnecting(value: boolean): void {
|
|
15
|
+
this.autoConnecting = value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
isLoading(): boolean {
|
|
19
|
+
return this.aitLoading || this.autoConnecting;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -36,6 +36,7 @@ import {
|
|
|
36
36
|
ChatBotProps,
|
|
37
37
|
PresetMessage
|
|
38
38
|
} from '../types/ChatBotTypes';
|
|
39
|
+
import { AuthorizationLoadingState } from '../authorizationLoadingState';
|
|
39
40
|
import { PendingTextToolRetryController } from '../pendingTextToolRetry';
|
|
40
41
|
|
|
41
42
|
const MIC_ENABLED_SESSION_KEY = 'chatbot-mic-enabled';
|
|
@@ -218,6 +219,9 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
218
219
|
const permissionsRef = React.useRef(permissions);
|
|
219
220
|
const nxtlinqAITServiceAccessTokenRef = React.useRef(nxtlinqAITServiceAccessToken);
|
|
220
221
|
const signerRef = React.useRef(signer);
|
|
222
|
+
const authorizationLoadingStateRef = React.useRef(
|
|
223
|
+
new AuthorizationLoadingState(isAITLoading, isAutoConnecting),
|
|
224
|
+
);
|
|
221
225
|
const pendingTextToolRetryRef = React.useRef(new PendingTextToolRetryController());
|
|
222
226
|
const sendMessageRef = React.useRef<ChatBotContextType['sendMessage']>(async () => {});
|
|
223
227
|
const retryPendingTextTool = React.useCallback(() => {
|
|
@@ -578,6 +582,14 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
578
582
|
permissionsRef.current = permissions;
|
|
579
583
|
}, [permissions]);
|
|
580
584
|
|
|
585
|
+
React.useEffect(() => {
|
|
586
|
+
authorizationLoadingStateRef.current.setAITLoading(isAITLoading);
|
|
587
|
+
}, [isAITLoading]);
|
|
588
|
+
|
|
589
|
+
React.useEffect(() => {
|
|
590
|
+
authorizationLoadingStateRef.current.setAutoConnecting(isAutoConnecting);
|
|
591
|
+
}, [isAutoConnecting]);
|
|
592
|
+
|
|
581
593
|
React.useEffect(() => {
|
|
582
594
|
nxtlinqAITServiceAccessTokenRef.current = nxtlinqAITServiceAccessToken;
|
|
583
595
|
}, [nxtlinqAITServiceAccessToken]);
|
|
@@ -1021,13 +1033,17 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
1021
1033
|
const currentHitAddress = hitAddressRef.current || hitAddress;
|
|
1022
1034
|
const currentToken = nxtlinqAITServiceAccessTokenRef.current || nxtlinqAITServiceAccessToken;
|
|
1023
1035
|
if (!currentHitAddress) {
|
|
1036
|
+
aitRef.current = null;
|
|
1037
|
+
permissionsRef.current = [];
|
|
1024
1038
|
setAit(null);
|
|
1025
1039
|
setPermissions([]);
|
|
1026
1040
|
setWalletInfo(null);
|
|
1041
|
+
authorizationLoadingStateRef.current.setAITLoading(false);
|
|
1027
1042
|
setIsAITLoading(false);
|
|
1028
1043
|
return;
|
|
1029
1044
|
}
|
|
1030
1045
|
|
|
1046
|
+
authorizationLoadingStateRef.current.setAITLoading(true);
|
|
1031
1047
|
setIsAITLoading(true);
|
|
1032
1048
|
try {
|
|
1033
1049
|
let walletAllowsAITLookup = !requireWalletIDVVerification;
|
|
@@ -1057,6 +1073,8 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
1057
1073
|
// AIT existence is not identity verification. In strict mode, stop before
|
|
1058
1074
|
// the legacy AIT lookup can synthesize a custom wallet record.
|
|
1059
1075
|
if (currentToken && !walletAllowsAITLookup) {
|
|
1076
|
+
aitRef.current = null;
|
|
1077
|
+
permissionsRef.current = [];
|
|
1060
1078
|
setAit(null);
|
|
1061
1079
|
setPermissions([]);
|
|
1062
1080
|
return;
|
|
@@ -1072,26 +1090,37 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
1072
1090
|
|
|
1073
1091
|
if ('error' in response) {
|
|
1074
1092
|
console.error('Failed to fetch AIT:', response.error);
|
|
1093
|
+
aitRef.current = null;
|
|
1094
|
+
permissionsRef.current = [];
|
|
1075
1095
|
setAit(null);
|
|
1076
1096
|
setPermissions([]);
|
|
1077
1097
|
return;
|
|
1078
1098
|
}
|
|
1079
1099
|
|
|
1100
|
+
aitRef.current = response;
|
|
1080
1101
|
setAit(response);
|
|
1081
1102
|
if (!isPermissionFormOpen || forceUpdatePermissions) {
|
|
1082
1103
|
const newPermissions = response.metadata?.permissions || [];
|
|
1104
|
+
permissionsRef.current = newPermissions;
|
|
1083
1105
|
setPermissions(newPermissions);
|
|
1084
1106
|
}
|
|
1085
1107
|
} else {
|
|
1086
1108
|
// No token available, clear AIT data
|
|
1109
|
+
aitRef.current = null;
|
|
1110
|
+
permissionsRef.current = [];
|
|
1087
1111
|
setAit(null);
|
|
1088
1112
|
setPermissions([]);
|
|
1089
1113
|
}
|
|
1090
1114
|
} catch (error) {
|
|
1091
1115
|
console.error('Failed to fetch AIT:', error);
|
|
1116
|
+
aitRef.current = null;
|
|
1117
|
+
permissionsRef.current = [];
|
|
1092
1118
|
setAit(null);
|
|
1093
1119
|
setPermissions([]);
|
|
1094
1120
|
} finally {
|
|
1121
|
+
// Keep the authorization snapshot current before refreshAIT resolves.
|
|
1122
|
+
// React may not commit setState until the immediate pending-tool retry.
|
|
1123
|
+
authorizationLoadingStateRef.current.setAITLoading(false);
|
|
1095
1124
|
setIsAITLoading(false);
|
|
1096
1125
|
}
|
|
1097
1126
|
};
|
|
@@ -1329,7 +1358,9 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
1329
1358
|
// wallet-address subject until issuance/migration supports it.
|
|
1330
1359
|
externalId: undefined,
|
|
1331
1360
|
requireWalletIDVVerification,
|
|
1332
|
-
|
|
1361
|
+
// Use synchronously maintained refs so a retry immediately following
|
|
1362
|
+
// refreshAIT() does not observe the previous React render's loading state.
|
|
1363
|
+
loading: authorizationLoadingStateRef.current.isLoading(),
|
|
1333
1364
|
},
|
|
1334
1365
|
...authFields(),
|
|
1335
1366
|
customUsername: (!requireWalletIDVVerification && customUsername)
|
|
@@ -2502,8 +2533,11 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
2502
2533
|
metadataCid,
|
|
2503
2534
|
};
|
|
2504
2535
|
|
|
2536
|
+
const nextPermissions = newPermissions || permissions;
|
|
2537
|
+
aitRef.current = aitInfo;
|
|
2538
|
+
permissionsRef.current = nextPermissions;
|
|
2505
2539
|
setAit(aitInfo);
|
|
2506
|
-
setPermissions(
|
|
2540
|
+
setPermissions(nextPermissions);
|
|
2507
2541
|
};
|
|
2508
2542
|
|
|
2509
2543
|
|
|
@@ -2691,6 +2725,7 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
2691
2725
|
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
2692
2726
|
}, token);
|
|
2693
2727
|
if (!('error' in aitResponse)) {
|
|
2728
|
+
aitRef.current = aitResponse;
|
|
2694
2729
|
setAit(aitResponse);
|
|
2695
2730
|
}
|
|
2696
2731
|
}
|
|
@@ -2730,6 +2765,7 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
2730
2765
|
customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
|
|
2731
2766
|
}, token);
|
|
2732
2767
|
if (!('error' in aitResponse)) {
|
|
2768
|
+
aitRef.current = aitResponse;
|
|
2733
2769
|
setAit(aitResponse);
|
|
2734
2770
|
}
|
|
2735
2771
|
}
|
|
@@ -2846,6 +2882,7 @@ export const ChatBotProvider: React.FC<ChatBotProps> = ({
|
|
|
2846
2882
|
// Set loading state when permission form opens
|
|
2847
2883
|
React.useEffect(() => {
|
|
2848
2884
|
if (isPermissionFormOpen && hitAddress) {
|
|
2885
|
+
authorizationLoadingStateRef.current.setAITLoading(true);
|
|
2849
2886
|
setIsAITLoading(true);
|
|
2850
2887
|
}
|
|
2851
2888
|
}, [isPermissionFormOpen, hitAddress]);
|