@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.3.4 → 2.0.0

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 (136) hide show
  1. package/dist/context/ChatBotContext.d.ts.map +1 -1
  2. package/dist/context/ChatBotContext.js +179 -160
  3. package/dist/index.d.ts +1 -1
  4. package/dist/index.d.ts.map +1 -1
  5. package/dist/permissionState.d.ts +53 -0
  6. package/dist/permissionState.d.ts.map +1 -0
  7. package/dist/permissionState.js +217 -0
  8. package/dist/types/ChatBotTypes.d.ts +6 -5
  9. package/dist/types/ChatBotTypes.d.ts.map +1 -1
  10. package/dist/ui/ModelSelector.js +2 -2
  11. package/dist/ui/PermissionForm.d.ts.map +1 -1
  12. package/dist/ui/PermissionForm.js +14 -28
  13. package/package.json +3 -3
  14. package/src/context/ChatBotContext.tsx +252 -195
  15. package/src/index.ts +0 -1
  16. package/src/permissionState.ts +313 -0
  17. package/src/types/ChatBotTypes.ts +7 -7
  18. package/src/ui/ModelSelector.tsx +5 -5
  19. package/src/ui/PermissionForm.tsx +20 -31
  20. package/dist/NxtlinqAgentChat.d.ts +0 -26
  21. package/dist/NxtlinqAgentChat.d.ts.map +0 -1
  22. package/dist/NxtlinqAgentChat.js +0 -28
  23. package/dist/components/AgentAssistantShell.d.ts +0 -5
  24. package/dist/components/AgentAssistantShell.d.ts.map +0 -1
  25. package/dist/components/AgentAssistantShell.js +0 -52
  26. package/dist/components/AgentComposer.d.ts +0 -3
  27. package/dist/components/AgentComposer.d.ts.map +0 -1
  28. package/dist/components/AgentComposer.js +0 -60
  29. package/dist/components/AgentMessageList.d.ts +0 -3
  30. package/dist/components/AgentMessageList.d.ts.map +0 -1
  31. package/dist/components/AgentMessageList.js +0 -37
  32. package/dist/components/AgentRemoteAudio.d.ts +0 -4
  33. package/dist/components/AgentRemoteAudio.d.ts.map +0 -1
  34. package/dist/components/AgentRemoteAudio.js +0 -34
  35. package/dist/components/AgentVoiceBar.d.ts +0 -3
  36. package/dist/components/AgentVoiceBar.d.ts.map +0 -1
  37. package/dist/components/AgentVoiceBar.js +0 -91
  38. package/dist/components/PresetMessageChips.d.ts +0 -3
  39. package/dist/components/PresetMessageChips.d.ts.map +0 -1
  40. package/dist/components/PresetMessageChips.js +0 -23
  41. package/dist/context/AgentAssistantContext.d.ts +0 -32
  42. package/dist/context/AgentAssistantContext.d.ts.map +0 -1
  43. package/dist/context/AgentAssistantContext.js +0 -179
  44. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts +0 -2
  45. package/dist/legacy/assets/images/adiSideItalicDataUri.d.ts.map +0 -1
  46. package/dist/legacy/assets/images/adiSideItalicDataUri.js +0 -1
  47. package/dist/legacy/chatbot/ChatBot.d.ts +0 -5
  48. package/dist/legacy/chatbot/ChatBot.d.ts.map +0 -1
  49. package/dist/legacy/chatbot/ChatBot.js +0 -35
  50. package/dist/legacy/chatbot/context/ChatBotContext.d.ts +0 -5
  51. package/dist/legacy/chatbot/context/ChatBotContext.d.ts.map +0 -1
  52. package/dist/legacy/chatbot/context/ChatBotContext.js +0 -2922
  53. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts +0 -166
  54. package/dist/legacy/chatbot/types/ChatBotTypes.d.ts.map +0 -1
  55. package/dist/legacy/chatbot/types/ChatBotTypes.js +0 -1
  56. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts +0 -17
  57. package/dist/legacy/chatbot/ui/BerifyMeModal.d.ts.map +0 -1
  58. package/dist/legacy/chatbot/ui/BerifyMeModal.js +0 -110
  59. package/dist/legacy/chatbot/ui/ChatBotHeader.d.ts +0 -15
  60. package/dist/legacy/chatbot/ui/ChatBotHeader.d.ts.map +0 -1
  61. package/dist/legacy/chatbot/ui/ChatBotHeader.js +0 -62
  62. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts +0 -3
  63. package/dist/legacy/chatbot/ui/ChatBotUI.d.ts.map +0 -1
  64. package/dist/legacy/chatbot/ui/ChatBotUI.js +0 -557
  65. package/dist/legacy/chatbot/ui/MessageInput.d.ts +0 -3
  66. package/dist/legacy/chatbot/ui/MessageInput.d.ts.map +0 -1
  67. package/dist/legacy/chatbot/ui/MessageInput.js +0 -321
  68. package/dist/legacy/chatbot/ui/MessageList.d.ts +0 -4
  69. package/dist/legacy/chatbot/ui/MessageList.d.ts.map +0 -1
  70. package/dist/legacy/chatbot/ui/MessageList.js +0 -455
  71. package/dist/legacy/chatbot/ui/ModelSelector.d.ts +0 -4
  72. package/dist/legacy/chatbot/ui/ModelSelector.d.ts.map +0 -1
  73. package/dist/legacy/chatbot/ui/ModelSelector.js +0 -122
  74. package/dist/legacy/chatbot/ui/NotificationModal.d.ts +0 -15
  75. package/dist/legacy/chatbot/ui/NotificationModal.d.ts.map +0 -1
  76. package/dist/legacy/chatbot/ui/NotificationModal.js +0 -53
  77. package/dist/legacy/chatbot/ui/PermissionForm.d.ts +0 -8
  78. package/dist/legacy/chatbot/ui/PermissionForm.d.ts.map +0 -1
  79. package/dist/legacy/chatbot/ui/PermissionForm.js +0 -465
  80. package/dist/legacy/chatbot/ui/PresetMessages.d.ts +0 -4
  81. package/dist/legacy/chatbot/ui/PresetMessages.d.ts.map +0 -1
  82. package/dist/legacy/chatbot/ui/PresetMessages.js +0 -33
  83. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts +0 -3
  84. package/dist/legacy/chatbot/ui/VoiceModePanel.d.ts.map +0 -1
  85. package/dist/legacy/chatbot/ui/VoiceModePanel.js +0 -95
  86. package/dist/legacy/chatbot/ui/chatBotHeaderParts.d.ts +0 -15
  87. package/dist/legacy/chatbot/ui/chatBotHeaderParts.d.ts.map +0 -1
  88. package/dist/legacy/chatbot/ui/chatBotHeaderParts.js +0 -50
  89. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts +0 -73
  90. package/dist/legacy/chatbot/ui/styles/isolatedStyles.d.ts.map +0 -1
  91. package/dist/legacy/chatbot/ui/styles/isolatedStyles.js +0 -985
  92. package/dist/legacy/index.d.ts +0 -14
  93. package/dist/legacy/index.d.ts.map +0 -1
  94. package/dist/legacy/index.js +0 -12
  95. package/dist/theme/defaultTheme.d.ts +0 -3
  96. package/dist/theme/defaultTheme.d.ts.map +0 -1
  97. package/dist/theme/defaultTheme.js +0 -20
  98. package/dist/types.d.ts +0 -62
  99. package/dist/types.d.ts.map +0 -1
  100. package/dist/types.js +0 -1
  101. package/dist/voice/useVoiceConnectOrchestration.d.ts +0 -21
  102. package/dist/voice/useVoiceConnectOrchestration.d.ts.map +0 -1
  103. package/dist/voice/useVoiceConnectOrchestration.js +0 -86
  104. package/dist/voice/useVoiceMicState.d.ts +0 -15
  105. package/dist/voice/useVoiceMicState.d.ts.map +0 -1
  106. package/dist/voice/useVoiceMicState.js +0 -94
  107. package/dist/voice/useVoiceSilenceCommit.d.ts +0 -10
  108. package/dist/voice/useVoiceSilenceCommit.d.ts.map +0 -1
  109. package/dist/voice/useVoiceSilenceCommit.js +0 -67
  110. package/dist/voice/useVoiceTranscriptMessages.d.ts +0 -18
  111. package/dist/voice/useVoiceTranscriptMessages.d.ts.map +0 -1
  112. package/dist/voice/useVoiceTranscriptMessages.js +0 -132
  113. package/dist/voice/useWsRealtimeAudio.d.ts +0 -18
  114. package/dist/voice/useWsRealtimeAudio.d.ts.map +0 -1
  115. package/dist/voice/useWsRealtimeAudio.js +0 -102
  116. package/dist/voice/voiceMicConstants.d.ts +0 -4
  117. package/dist/voice/voiceMicConstants.d.ts.map +0 -1
  118. package/dist/voice/voiceMicConstants.js +0 -10
  119. package/dist/voice/voiceUserBubble.d.ts +0 -10
  120. package/dist/voice/voiceUserBubble.d.ts.map +0 -1
  121. package/dist/voice/voiceUserBubble.js +0 -52
  122. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts +0 -23
  123. package/dist/voice/ws/BrowserWsPcmPlayer.d.ts.map +0 -1
  124. package/dist/voice/ws/BrowserWsPcmPlayer.js +0 -137
  125. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts +0 -17
  126. package/dist/voice/ws/BrowserWsPcmRecorder.d.ts.map +0 -1
  127. package/dist/voice/ws/BrowserWsPcmRecorder.js +0 -71
  128. package/dist/voice/ws/float32ToPcm16.d.ts +0 -2
  129. package/dist/voice/ws/float32ToPcm16.d.ts.map +0 -1
  130. package/dist/voice/ws/float32ToPcm16.js +0 -8
  131. package/dist/voice/ws/voiceSilenceConstants.d.ts +0 -5
  132. package/dist/voice/ws/voiceSilenceConstants.d.ts.map +0 -1
  133. package/dist/voice/ws/voiceSilenceConstants.js +0 -4
  134. package/dist/voice/ws/wsRealtimeConstants.d.ts +0 -2
  135. package/dist/voice/ws/wsRealtimeConstants.d.ts.map +0 -1
  136. 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,CA4vGlD,CAAC"}
1
+ {"version":3,"file":"ChatBotContext.d.ts","sourceRoot":"","sources":["../../src/context/ChatBotContext.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA0B/B,OAAO,EAEL,kBAAkB,EAClB,YAAY,EAEb,MAAM,uBAAuB,CAAC;AAsB/B,eAAO,MAAM,UAAU,0BAMtB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,YAAY,CAoyGlD,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 { dispatchRuntimeAITCompleteReplacement, removeOneDeniedPermission, replaceCurrentMaximumDenyList, RuntimeAITMutationQueue, RuntimeAITRecomputeCoordinator, StaleRuntimeAITResponseError, runtimeAITContextKey, runtimeAITSubjectKey, runtimeAuthorizationMatchesContext, runtimeAuthorizationState, unavailableRuntimeAuthorization, useProviderRuntimeCommit, useRuntimeAITContextCommit, } from '../permissionState';
8
9
  const MIC_ENABLED_SESSION_KEY = 'chatbot-mic-enabled';
9
10
  const ChatBotContext = React.createContext(undefined);
10
11
  export const useChatBot = () => {
@@ -14,7 +15,7 @@ export const useChatBot = () => {
14
15
  }
15
16
  return context;
16
17
  };
17
- export const ChatBotProvider = ({ onMessage, onError, onToolUse, presetMessages = [], placeholder = 'Type a message...', className = '', maxRetries = 3, retryDelay = 2000, serviceId, apiKey, apiSecret, serviceToken, getAuthToken, environment = 'production', onVerifyWallet, permissionGroup, children,
18
+ export const ChatBotProvider = ({ onMessage, onError, onToolUse, presetMessages = [], placeholder = 'Type a message...', className = '', maxRetries = 3, retryDelay = 2000, serviceId, apiKey, apiSecret, serviceToken, getAuthToken, environment = 'production', onVerifyWallet, permissionGroup, roles, children,
18
19
  // AI Model related attributes
19
20
  onModelChange,
20
21
  // Storage mode configuration
@@ -33,8 +34,6 @@ isStopRecordingOnSend = false,
33
34
  customError,
34
35
  // PII display mode
35
36
  piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary, }) => {
36
- // Set API hosts immediately based on environment (before any API calls)
37
- setApiHosts(environment);
38
37
  const nxtlinqApi = React.useMemo(() => (serviceToken || getAuthToken
39
38
  ? createNxtlinqApi({ apiKey, apiSecret, serviceToken, getAuthToken })
40
39
  : createNxtlinqApi(apiKey ?? '', apiSecret ?? '')), [apiKey, apiSecret, serviceToken, getAuthToken]);
@@ -86,7 +85,17 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
86
85
  const [hitAddress, setHitAddress] = React.useState(null);
87
86
  const [ait, setAit] = React.useState(null);
88
87
  const [permissions, setPermissions] = React.useState([]);
89
- const [availablePermissions, setAvailablePermissions] = React.useState([]);
88
+ const [maximumPermissions, setMaximumPermissions] = React.useState([]);
89
+ const [deniedPermissions, setDeniedPermissions] = React.useState([]);
90
+ const [runtimePermissionsUnavailable, setRuntimePermissionsUnavailable] = React.useState(false);
91
+ const [runtimeAuthorizationContextKey, setRuntimeAuthorizationContextKey] = React.useState(null);
92
+ const [servicePermissionCatalog, setServicePermissionCatalog] = React.useState([]);
93
+ const availablePermissions = React.useMemo(() => maximumPermissions.map((label) => servicePermissionCatalog.find((permission) => permission.label === label) ?? {
94
+ id: label,
95
+ label,
96
+ description: '',
97
+ groups: [],
98
+ }), [maximumPermissions, servicePermissionCatalog]);
90
99
  const [showPermissionForm, setShowPermissionForm] = React.useState(false);
91
100
  const [isPermissionFormOpen, setIsPermissionFormOpen] = React.useState(false);
92
101
  const [isAITLoading, setIsAITLoading] = React.useState(false);
@@ -95,6 +104,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
95
104
  const [walletInfo, setWalletInfo] = React.useState(null);
96
105
  const [isWalletLoading, setIsWalletLoading] = React.useState(false);
97
106
  const [isAutoConnecting, setIsAutoConnecting] = React.useState(false);
107
+ const runtimeRolesKey = JSON.stringify(roles ?? null);
98
108
  // Persistent data (always use localStorage)
99
109
  const [nxtlinqAITServiceAccessToken, setNxtlinqAITServiceAccessToken] = useLocalStorage('nxtlinqAITServiceAccessToken', '');
100
110
  const [pseudoId, setPseudoId] = useLocalStorage('pseudoId', uuidv4());
@@ -143,8 +153,12 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
143
153
  const hitAddressRef = React.useRef(hitAddress);
144
154
  const aitRef = React.useRef(ait);
145
155
  const permissionsRef = React.useRef(permissions);
156
+ const deniedPermissionsRef = React.useRef(deniedPermissions);
146
157
  const nxtlinqAITServiceAccessTokenRef = React.useRef(nxtlinqAITServiceAccessToken);
147
158
  const signerRef = React.useRef(signer);
159
+ const runtimeRecomputeCoordinatorRef = React.useRef(new RuntimeAITRecomputeCoordinator());
160
+ const runtimeMutationQueueRef = React.useRef(new RuntimeAITMutationQueue());
161
+ useProviderRuntimeCommit(hitAddressRef, hitAddress, environment, setApiHosts);
148
162
  // Helper function to combine customUsername with Adilas customUserInfo
149
163
  const getFinalCustomUsername = React.useCallback((username) => {
150
164
  if (!username)
@@ -463,15 +477,15 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
463
477
  }
464
478
  }, []);
465
479
  // Update refs when state changes
466
- React.useEffect(() => {
467
- hitAddressRef.current = hitAddress;
468
- }, [hitAddress]);
469
480
  React.useEffect(() => {
470
481
  aitRef.current = ait;
471
482
  }, [ait]);
472
483
  React.useEffect(() => {
473
484
  permissionsRef.current = permissions;
474
485
  }, [permissions]);
486
+ React.useEffect(() => {
487
+ deniedPermissionsRef.current = deniedPermissions;
488
+ }, [deniedPermissions]);
475
489
  React.useEffect(() => {
476
490
  nxtlinqAITServiceAccessTokenRef.current = nxtlinqAITServiceAccessToken;
477
491
  }, [nxtlinqAITServiceAccessToken]);
@@ -843,7 +857,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
843
857
  console.error('Failed to fetch permissions:', result.error);
844
858
  return undefined;
845
859
  }
846
- setAvailablePermissions(result.permissions);
860
+ setServicePermissionCatalog(result.permissions);
847
861
  return result.permissions;
848
862
  }
849
863
  catch (error) {
@@ -851,12 +865,81 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
851
865
  return undefined;
852
866
  }
853
867
  };
854
- // Refresh AIT
868
+ const clearRuntimeAuthorization = React.useCallback(() => {
869
+ const cleared = unavailableRuntimeAuthorization(deniedPermissionsRef.current);
870
+ const activeContext = runtimeRecomputeCoordinatorRef.current.getActiveContext();
871
+ aitRef.current = null;
872
+ permissionsRef.current = [];
873
+ setAit(cleared.ait);
874
+ setPermissions(cleared.effectivePermissions);
875
+ setMaximumPermissions(cleared.maximumPermissions);
876
+ setRuntimePermissionsUnavailable(cleared.unavailable);
877
+ setRuntimeAuthorizationContextKey(activeContext ? runtimeAITContextKey(activeContext) : null);
878
+ }, []);
879
+ const applyRuntimeResult = React.useCallback((result, context) => {
880
+ const next = runtimeAuthorizationState(result, context.controller, context.serviceId);
881
+ aitRef.current = next.ait;
882
+ permissionsRef.current = next.effectivePermissions;
883
+ setAit(next.ait);
884
+ setPermissions(next.effectivePermissions);
885
+ setMaximumPermissions(next.maximumPermissions);
886
+ setDeniedPermissions(next.deniedPermissions);
887
+ deniedPermissionsRef.current = next.deniedPermissions;
888
+ setRuntimePermissionsUnavailable(false);
889
+ setRuntimeAuthorizationContextKey(runtimeAITContextKey(context));
890
+ return result;
891
+ }, []);
892
+ const runtimeContext = React.useMemo(() => hitAddress ? {
893
+ controller: hitAddress,
894
+ serviceId,
895
+ ...(roles !== undefined ? { roles: [...roles] } : {}),
896
+ ...(permissionGroup !== undefined ? { permissionGroup } : {}),
897
+ } : null, [hitAddress, permissionGroup, runtimeRolesKey, serviceId]);
898
+ const invalidateCommittedRuntimeContext = React.useCallback(() => {
899
+ const activeContext = runtimeRecomputeCoordinatorRef.current.getActiveContext();
900
+ aitRef.current = null;
901
+ permissionsRef.current = [];
902
+ deniedPermissionsRef.current = [];
903
+ setAit(null);
904
+ setPermissions([]);
905
+ setMaximumPermissions([]);
906
+ setDeniedPermissions([]);
907
+ setRuntimePermissionsUnavailable(activeContext !== null);
908
+ setRuntimeAuthorizationContextKey(activeContext ? runtimeAITContextKey(activeContext) : null);
909
+ }, []);
910
+ useRuntimeAITContextCommit(runtimeRecomputeCoordinatorRef.current, runtimeContext, invalidateCommittedRuntimeContext);
911
+ const recomputeRuntimeAIT = React.useCallback(async (context) => {
912
+ const capturedContext = {
913
+ controller: context.controller,
914
+ serviceId: context.serviceId,
915
+ ...(context.roles !== undefined ? { roles: [...context.roles] } : {}),
916
+ ...(context.permissionGroup !== undefined ? { permissionGroup: context.permissionGroup } : {}),
917
+ };
918
+ return runtimeRecomputeCoordinatorRef.current.run(capturedContext, () => nxtlinqApi.ait.recomputeAIT(capturedContext), applyRuntimeResult, clearRuntimeAuthorization);
919
+ }, [applyRuntimeResult, clearRuntimeAuthorization, nxtlinqApi]);
920
+ const queueRuntimeAITRefresh = React.useCallback((context) => runtimeMutationQueueRef.current.run(runtimeAITSubjectKey(context), async () => {
921
+ runtimeRecomputeCoordinatorRef.current.assertContextActive(context);
922
+ return recomputeRuntimeAIT(context);
923
+ }), [recomputeRuntimeAIT]);
924
+ const convergeRuntimeAITSubject = React.useCallback(async (subjectKey) => {
925
+ const activeContext = runtimeRecomputeCoordinatorRef.current.getActiveContext();
926
+ if (!activeContext || runtimeAITSubjectKey(activeContext) !== subjectKey) {
927
+ return;
928
+ }
929
+ await recomputeRuntimeAIT(activeContext);
930
+ }, [recomputeRuntimeAIT]);
931
+ const dispatchRuntimeDenyListReplacement = React.useCallback(async (context, nextDeniedPermissions) => dispatchRuntimeAITCompleteReplacement(runtimeRecomputeCoordinatorRef.current, context, () => nxtlinqApi.ait.updatePermissionDenyList({
932
+ ...context,
933
+ deniedPermissions: nextDeniedPermissions,
934
+ }), convergeRuntimeAITSubject, clearRuntimeAuthorization), [clearRuntimeAuthorization, convergeRuntimeAITSubject, nxtlinqApi]);
935
+ // Refresh the authoritative runtime AIT state.
855
936
  const refreshAIT = async (forceUpdatePermissions = false) => {
856
937
  if (!hitAddress) {
857
938
  setAit(null);
858
939
  setPermissions([]);
940
+ setMaximumPermissions([]);
859
941
  setWalletInfo(null);
942
+ setRuntimePermissionsUnavailable(false);
860
943
  setIsAITLoading(false);
861
944
  return;
862
945
  }
@@ -881,35 +964,20 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
881
964
  console.error('Failed to fetch wallet info:', error);
882
965
  }
883
966
  }
884
- // Only try to fetch AIT if we have a token
967
+ // Recompute is the sole mint/reuse path and the only permission authority.
885
968
  if (nxtlinqAITServiceAccessToken) {
886
- const response = await nxtlinqApi.ait.getAITByServiceIdAndController({
887
- serviceId,
888
- controller: hitAddress,
889
- customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
890
- }, nxtlinqAITServiceAccessToken);
891
- if ('error' in response) {
892
- console.error('Failed to fetch AIT:', response.error);
893
- setAit(null);
894
- setPermissions([]);
895
- return;
896
- }
897
- setAit(response);
898
- if (!isPermissionFormOpen || forceUpdatePermissions) {
899
- const newPermissions = response.metadata?.permissions || [];
900
- setPermissions(newPermissions);
969
+ if (runtimeContext) {
970
+ await queueRuntimeAITRefresh(runtimeContext);
901
971
  }
902
972
  }
903
973
  else {
904
- // No token available, clear AIT data
905
- setAit(null);
906
- setPermissions([]);
974
+ clearRuntimeAuthorization();
907
975
  }
908
976
  }
909
977
  catch (error) {
910
- console.error('Failed to fetch AIT:', error);
911
- setAit(null);
912
- setPermissions([]);
978
+ if (!(error instanceof StaleRuntimeAITResponseError)) {
979
+ console.error('Failed to recompute AIT:', error);
980
+ }
913
981
  }
914
982
  finally {
915
983
  setIsAITLoading(false);
@@ -1097,9 +1165,13 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
1097
1165
  }
1098
1166
  const { accessToken } = response;
1099
1167
  setNxtlinqAITServiceAccessToken(accessToken);
1100
- // Wait for state to update before refreshing AIT
1101
- await new Promise(resolve => setTimeout(resolve, 100));
1102
- await refreshAIT();
1168
+ localStorage.setItem('nxtlinqAITServiceAccessToken', JSON.stringify(accessToken));
1169
+ await queueRuntimeAITRefresh({
1170
+ controller: addressToUse,
1171
+ serviceId,
1172
+ ...(roles !== undefined ? { roles: [...roles] } : {}),
1173
+ ...(permissionGroup !== undefined ? { permissionGroup } : {}),
1174
+ });
1103
1175
  if (autoShowSuccessMessage) {
1104
1176
  showSuccess(walletTextUtils.getWalletText('Successfully signed in with your HIT wallet. You can now use the AI agent.', serviceId));
1105
1177
  }
@@ -2442,86 +2514,6 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2442
2514
  setInputValue(message.text);
2443
2515
  }
2444
2516
  };
2445
- // Generate and register AIT
2446
- const generateAndRegisterAIT = async (newPermissions, isFromAIAgent = false) => {
2447
- let currentSigner = signer;
2448
- let currentAddress = hitAddress;
2449
- // If we have an address but no signer, try to auto-connect wallet
2450
- if (currentAddress && !currentSigner) {
2451
- const storedWalletAddress = localStorage.getItem('walletAddress');
2452
- if (storedWalletAddress === currentAddress) {
2453
- try {
2454
- const autoConnectResult = await connectWallet(false); // Don't show sign-in message yet
2455
- if (autoConnectResult) {
2456
- // Wait for state to update
2457
- await new Promise(resolve => setTimeout(resolve, 1000));
2458
- // Get the updated signer and address
2459
- currentSigner = signerRef.current || signer;
2460
- currentAddress = hitAddressRef.current || hitAddress;
2461
- }
2462
- }
2463
- catch (error) {
2464
- console.error('Auto-connect failed during AIT generation:', error);
2465
- }
2466
- }
2467
- }
2468
- if (!currentSigner || !currentAddress) {
2469
- throw new Error('Missing signer or wallet address');
2470
- }
2471
- return generateAndRegisterAITWithSigner(newPermissions, isFromAIAgent, currentSigner, currentAddress);
2472
- };
2473
- // Generate and register AIT with explicit signer and address
2474
- const generateAndRegisterAITWithSigner = async (newPermissions, isFromAIAgent = false, explicitSigner, explicitAddress) => {
2475
- const currentSigner = explicitSigner || signer;
2476
- const currentAddress = explicitAddress || hitAddress;
2477
- if (!currentSigner || !currentAddress) {
2478
- throw new Error('Missing signer or wallet address');
2479
- }
2480
- // If AI Agent is creating, must check if user has existing AIT
2481
- if (isFromAIAgent && !aitRef.current) {
2482
- throw new Error('You must have an existing AIT before AI Agent can create new AITs');
2483
- }
2484
- // aitId is assigned by AIT-Service (UUIDv7) and returned in the response. It must not be
2485
- // minted here: the client cannot guarantee uniqueness, and this value feeds parentAITId, which
2486
- // is part of the on-chain commitment -- a locally invented id would anchor a parent that does
2487
- // not exist.
2488
- const metadata = {
2489
- permissions: newPermissions || permissions,
2490
- issuedBy: currentAddress,
2491
- };
2492
- const metadataStr = stringify(metadata);
2493
- // ethers v6: utils.keccak256 -> keccak256, utils.toUtf8Bytes -> toUtf8Bytes
2494
- const metadataHash = ethers.keccak256(ethers.toUtf8Bytes(metadataStr));
2495
- // AIT-Service no longer publishes metadata to IPFS: the registry is hash-only, integrity comes
2496
- // from the on-chain commitment, and /api/metadata has been removed. `permissions` now travels
2497
- // in the request body instead of being recovered from a CID, so nothing is uploaded here.
2498
- const createAITParams = {
2499
- controller: currentAddress,
2500
- serviceId,
2501
- permissions: metadata.permissions,
2502
- metadataHash,
2503
- isFromAIAgent: isFromAIAgent,
2504
- parentAITId: isFromAIAgent ? aitRef.current?.aitId : undefined,
2505
- };
2506
- const createAITResponse = await nxtlinqApi.ait.createAIT(createAITParams, nxtlinqAITServiceAccessToken || '');
2507
- if ('error' in createAITResponse) {
2508
- throw new Error(`Failed to create AIT: ${createAITResponse.error}`);
2509
- }
2510
- const aitId = createAITResponse.aitId;
2511
- if (!aitId) {
2512
- // Surfaced rather than substituted: this id becomes parentAITId on agent-created AITs, and
2513
- // parentAITId is committed on chain. Guessing one would anchor a dangling parent link.
2514
- throw new Error('AIT-Service did not return an aitId; refusing to invent one.');
2515
- }
2516
- const aitInfo = {
2517
- aitId,
2518
- controller: currentAddress,
2519
- metadata,
2520
- metadataHash,
2521
- };
2522
- setAit(aitInfo);
2523
- setPermissions(newPermissions || permissions);
2524
- };
2525
2517
  // Auto enable AIT permission
2526
2518
  const enableAIT = async (toolName) => {
2527
2519
  if (isAITEnabling)
@@ -2583,35 +2575,41 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2583
2575
  }
2584
2576
  }
2585
2577
  try {
2586
- // Get available permissions to find the tool
2587
- const availablePermissionLabels = availablePermissions.map(p => p.label);
2588
- if (!availablePermissionLabels.includes(toolName)) {
2578
+ const context = {
2579
+ controller: currentHitAddress,
2580
+ serviceId,
2581
+ ...(roles !== undefined ? { roles: [...roles] } : {}),
2582
+ ...(permissionGroup !== undefined ? { permissionGroup } : {}),
2583
+ };
2584
+ const enabled = await runtimeMutationQueueRef.current.run(runtimeAITSubjectKey(context), async () => {
2585
+ runtimeRecomputeCoordinatorRef.current.assertContextActive(context);
2586
+ const current = await recomputeRuntimeAIT(context);
2587
+ if (!current.maximumPermissions.includes(toolName)) {
2588
+ return false;
2589
+ }
2590
+ const nextDeniedPermissions = removeOneDeniedPermission(current.deniedPermissions, toolName);
2591
+ runtimeRecomputeCoordinatorRef.current.assertContextActive(context);
2592
+ await dispatchRuntimeDenyListReplacement(context, nextDeniedPermissions);
2593
+ return true;
2594
+ });
2595
+ if (!enabled) {
2589
2596
  showError(`Tool ${toolName} is not available for your current identity provider`);
2590
2597
  setIsAITEnabling(false);
2591
2598
  return false;
2592
2599
  }
2593
- // Get current permissions from AIT metadata instead of React state
2594
- // This ensures we don't lose existing permissions when enabling new ones
2595
- const currentAITPermissions = aitRef.current?.metadata?.permissions || permissions;
2596
- const newPermissions = [...currentAITPermissions];
2597
- if (!newPermissions.includes(toolName)) {
2598
- newPermissions.push(toolName);
2599
- }
2600
- // Filter out deleted permissions before saving
2601
- const validPermissions = newPermissions.filter(permission => availablePermissionLabels.includes(permission));
2602
- // Generate and register AIT with new permissions
2603
- // For auto-enable, we should create a regular AIT (not AI Agent AIT) if user doesn't have existing AIT
2604
- const shouldCreateAsAIAgent = !!aitRef.current; // Only create as AI Agent if user already has an AIT
2605
- await generateAndRegisterAITWithSigner(validPermissions, shouldCreateAsAIAgent, currentSigner, currentHitAddress);
2606
2600
  showSuccess('AIT permission enabled successfully! You can now use the AI agent.');
2607
- await refreshAIT(true);
2608
2601
  setIsAITEnabling(false);
2609
2602
  return true;
2610
2603
  }
2611
2604
  catch (error) {
2612
- console.error('Failed to auto-enable AIT:', error);
2605
+ if (!(error instanceof StaleRuntimeAITResponseError)) {
2606
+ console.error('Failed to auto-enable AIT:', error);
2607
+ }
2613
2608
  setIsAITEnabling(false);
2614
- if (error instanceof Error) {
2609
+ if (error instanceof StaleRuntimeAITResponseError) {
2610
+ return false;
2611
+ }
2612
+ else if (error instanceof Error) {
2615
2613
  showError(error.message);
2616
2614
  }
2617
2615
  else {
@@ -2624,20 +2622,36 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2624
2622
  const savePermissions = async (newPermissions) => {
2625
2623
  setIsDisabled(true);
2626
2624
  try {
2627
- // Filter out deleted permissions before saving
2628
- const permissionsToSave = newPermissions || permissions;
2629
- const availablePermissionLabels = availablePermissions.map(p => p.label);
2630
- const validPermissions = permissionsToSave.filter(permission => availablePermissionLabels.includes(permission));
2631
- await generateAndRegisterAIT(validPermissions, false);
2625
+ if (!hitAddress) {
2626
+ throw new Error('Please connect your wallet first');
2627
+ }
2628
+ const context = {
2629
+ controller: hitAddress,
2630
+ serviceId,
2631
+ ...(roles !== undefined ? { roles: [...roles] } : {}),
2632
+ ...(permissionGroup !== undefined ? { permissionGroup } : {}),
2633
+ };
2634
+ const checkedPermissions = [...(newPermissions ?? permissions)];
2635
+ await runtimeMutationQueueRef.current.run(runtimeAITSubjectKey(context), async () => {
2636
+ runtimeRecomputeCoordinatorRef.current.assertContextActive(context);
2637
+ const fresh = await recomputeRuntimeAIT(context);
2638
+ const nextDeniedPermissions = replaceCurrentMaximumDenyList(fresh.deniedPermissions, fresh.maximumPermissions, checkedPermissions);
2639
+ runtimeRecomputeCoordinatorRef.current.assertContextActive(context);
2640
+ await dispatchRuntimeDenyListReplacement(context, nextDeniedPermissions);
2641
+ });
2632
2642
  showSuccess('AIT permissions saved successfully! You can now use the AI agent with your configured permissions.');
2633
2643
  setShowPermissionForm(false);
2634
2644
  setIsPermissionFormOpen(false);
2635
- await refreshAIT(true);
2636
2645
  }
2637
2646
  catch (error) {
2638
- console.error('Failed to generate AIT:', error);
2647
+ if (!(error instanceof StaleRuntimeAITResponseError)) {
2648
+ console.error('Failed to update AIT deny-list:', error);
2649
+ }
2639
2650
  setIsDisabled(false);
2640
- if (error instanceof Error) {
2651
+ if (error instanceof StaleRuntimeAITResponseError) {
2652
+ return;
2653
+ }
2654
+ else if (error instanceof Error) {
2641
2655
  showError(error.message);
2642
2656
  }
2643
2657
  else {
@@ -2683,14 +2697,12 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2683
2697
  const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
2684
2698
  if (!('error' in walletResponse)) {
2685
2699
  setWalletInfo(walletResponse);
2686
- const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
2687
- serviceId,
2700
+ await queueRuntimeAITRefresh({
2688
2701
  controller: address,
2689
- customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
2690
- }, token);
2691
- if (!('error' in aitResponse)) {
2692
- setAit(aitResponse);
2693
- }
2702
+ serviceId,
2703
+ ...(roles !== undefined ? { roles: [...roles] } : {}),
2704
+ ...(permissionGroup !== undefined ? { permissionGroup } : {}),
2705
+ });
2694
2706
  }
2695
2707
  }
2696
2708
  finally {
@@ -2723,14 +2735,12 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2723
2735
  const walletResponse = await nxtlinqApi.wallet.getWallet({ address }, token);
2724
2736
  if (!('error' in walletResponse)) {
2725
2737
  setWalletInfo(walletResponse);
2726
- const aitResponse = await nxtlinqApi.ait.getAITByServiceIdAndController({
2727
- serviceId,
2738
+ await queueRuntimeAITRefresh({
2728
2739
  controller: address,
2729
- customUsername: (!requireWalletIDVVerification && customUsername) ? getFinalCustomUsername(customUsername) : undefined
2730
- }, token);
2731
- if (!('error' in aitResponse)) {
2732
- setAit(aitResponse);
2733
- }
2740
+ serviceId,
2741
+ ...(roles !== undefined ? { roles: [...roles] } : {}),
2742
+ ...(permissionGroup !== undefined ? { permissionGroup } : {}),
2743
+ });
2734
2744
  }
2735
2745
  }
2736
2746
  finally {
@@ -2839,7 +2849,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2839
2849
  if (hitAddress && nxtlinqAITServiceAccessToken) {
2840
2850
  refreshAIT();
2841
2851
  }
2842
- }, [hitAddress, nxtlinqAITServiceAccessToken]);
2852
+ }, [hitAddress, nxtlinqAITServiceAccessToken, permissionGroup, runtimeRolesKey, serviceId]);
2843
2853
  // Set loading state when permission form opens
2844
2854
  React.useEffect(() => {
2845
2855
  if (isPermissionFormOpen && hitAddress) {
@@ -2918,6 +2928,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2918
2928
  };
2919
2929
  updateExternalId();
2920
2930
  }, [hitAddress, nxtlinqApi, authFields, pseudoId]);
2931
+ const runtimeAuthorizationMatchesRenderedContext = runtimeAuthorizationMatchesContext(runtimeAuthorizationContextKey, runtimeContext);
2921
2932
  const contextValue = {
2922
2933
  // State
2923
2934
  messages,
@@ -2925,9 +2936,16 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2925
2936
  isLoading,
2926
2937
  isOpen,
2927
2938
  hitAddress,
2928
- ait,
2929
- permissions,
2930
- availablePermissions,
2939
+ ait: runtimeAuthorizationMatchesRenderedContext ? ait : null,
2940
+ permissions: runtimeAuthorizationMatchesRenderedContext ? permissions : [],
2941
+ maximumPermissions: runtimeAuthorizationMatchesRenderedContext ? maximumPermissions : [],
2942
+ deniedPermissions: runtimeAuthorizationMatchesRenderedContext ? deniedPermissions : [],
2943
+ runtimePermissionsUnavailable: runtimeAuthorizationMatchesRenderedContext
2944
+ ? runtimePermissionsUnavailable
2945
+ : runtimeContext !== null,
2946
+ availablePermissions: runtimeAuthorizationMatchesRenderedContext
2947
+ ? availablePermissions
2948
+ : [],
2931
2949
  showPermissionForm,
2932
2950
  isPermissionFormOpen,
2933
2951
  isAITLoading,
@@ -2963,7 +2981,6 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
2963
2981
  setIsOpen,
2964
2982
  setShowPermissionForm,
2965
2983
  setIsPermissionFormOpen,
2966
- setPermissions,
2967
2984
  setIsDisabled,
2968
2985
  setIsWalletLoading,
2969
2986
  setNotification,
@@ -3011,6 +3028,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
3011
3028
  onVerifyWallet: (method) => handleVerifyWalletClick(method),
3012
3029
  serviceId,
3013
3030
  permissionGroup,
3031
+ roles,
3014
3032
  // Props
3015
3033
  props: {
3016
3034
  onMessage,
@@ -3028,6 +3046,7 @@ piiDisplayMode = 'redacted', voiceThresholds, debugVoiceRms = false, sttGlossary
3028
3046
  getAuthToken,
3029
3047
  onVerifyWallet,
3030
3048
  permissionGroup,
3049
+ roles,
3031
3050
  onModelChange,
3032
3051
  storageMode,
3033
3052
  requireWalletIDVVerification,
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
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 type { AIModel, AITMetadata, ChatBotContextType, ChatBotProps, NovaError, NovaResponse, ToolCall, ToolUse, PresetMessage, } from './types/ChatBotTypes';
4
+ export type { AIModel, ChatBotContextType, ChatBotProps, NovaError, NovaResponse, ToolCall, ToolUse, PresetMessage, } from './types/ChatBotTypes';
5
5
  export type { AgentEnvironment, AgentConfig, Attachment, AgentResponse, Message, SendMessageOptions, NxtlinqAgentSnapshot, VoiceSession, VoiceStatus, } from '@bytexbyte/nxtlinq-ai-agent-core-development';
6
6
  export { NxtlinqAgent, setApiHosts, VoiceNotSupportedError, STORAGE_KEYS, } 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';
@@ -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,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"}
@@ -0,0 +1,53 @@
1
+ import type { AIT, RuntimeAITResult } from '@bytexbyte/nxtlinq-ai-agent-core-development';
2
+ import * as React from 'react';
3
+ export declare function commitProviderRuntime<T, E>(identityRef: React.MutableRefObject<T>, identity: T, environment: E, publishEnvironment: (environment: E) => void): void;
4
+ export declare function useProviderRuntimeCommit<T, E>(identityRef: React.MutableRefObject<T>, identity: T, environment: E, publishEnvironment: (environment: E) => void): void;
5
+ export declare function replaceCurrentMaximumDenyList(persistedDeniedPermissions: readonly string[], maximumPermissions: readonly string[], checkedPermissions: readonly string[]): string[];
6
+ export declare function removeOneDeniedPermission(persistedDeniedPermissions: readonly string[], permission: string): string[];
7
+ export type RuntimeAITContext = {
8
+ controller: string;
9
+ serviceId: string;
10
+ roles?: string[];
11
+ permissionGroup?: string;
12
+ };
13
+ export declare function runtimeAITContextKey(context: RuntimeAITContext): string;
14
+ export declare function runtimeAITSubjectKey(context: RuntimeAITContext): string;
15
+ export declare function runtimeAuthorizationMatchesContext(authorizationContextKey: string | null, renderedContext: RuntimeAITContext | null): boolean;
16
+ export declare class StaleRuntimeAITResponseError extends Error {
17
+ constructor();
18
+ }
19
+ /**
20
+ * Owns the authoritative recompute lifecycle. Only the newest request for the
21
+ * active captured context may write state; its failures clear state first.
22
+ */
23
+ export declare class RuntimeAITRecomputeCoordinator {
24
+ private activeContextKey;
25
+ private activeContext;
26
+ private generation;
27
+ commitContext(context: RuntimeAITContext | null, invalidate: () => void): boolean;
28
+ getActiveContext(): RuntimeAITContext | null;
29
+ isContextActive(context: RuntimeAITContext): boolean;
30
+ assertContextActive(context: RuntimeAITContext): void;
31
+ run<T>(context: RuntimeAITContext, request: () => Promise<T>, apply: (result: T, context: RuntimeAITContext) => void, clear: () => void): Promise<T>;
32
+ }
33
+ export declare function useRuntimeAITContextCommit(coordinator: RuntimeAITRecomputeCoordinator, context: RuntimeAITContext | null, invalidate: () => void): void;
34
+ export declare function dispatchRuntimeAITCompleteReplacement(coordinator: RuntimeAITRecomputeCoordinator, context: RuntimeAITContext, update: () => Promise<unknown>, converge: (subjectKey: string) => Promise<void>, clear: () => void): Promise<void>;
35
+ /** Serializes reads, complete replacements, and convergence for one persistence subject. */
36
+ export declare class RuntimeAITMutationQueue {
37
+ private readonly tails;
38
+ run<T>(subjectKey: string, mutation: () => Promise<T>): Promise<T>;
39
+ }
40
+ export type RuntimeAuthorizationState = {
41
+ ait: AIT | null;
42
+ maximumPermissions: string[];
43
+ effectivePermissions: string[];
44
+ deniedPermissions: string[];
45
+ selectedRuleId: string | null;
46
+ selectedRuleType: RuntimeAITResult['selectedRuleType'];
47
+ expiresAt: string | null;
48
+ grantActive: boolean;
49
+ unavailable: boolean;
50
+ };
51
+ export declare function runtimeAuthorizationState(result: RuntimeAITResult, controller: string, serviceId: string): RuntimeAuthorizationState;
52
+ export declare function unavailableRuntimeAuthorization(persistedDeniedPermissions: readonly string[]): RuntimeAuthorizationState;
53
+ //# sourceMappingURL=permissionState.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissionState.d.ts","sourceRoot":"","sources":["../src/permissionState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAC1F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,CAAC,EACxC,WAAW,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EACtC,QAAQ,EAAE,CAAC,EACX,WAAW,EAAE,CAAC,EACd,kBAAkB,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,IAAI,GAC3C,IAAI,CAGN;AAED,wBAAgB,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAC3C,WAAW,EAAE,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,EACtC,QAAQ,EAAE,CAAC,EACX,WAAW,EAAE,CAAC,EACd,kBAAkB,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,IAAI,GAC3C,IAAI,CASN;AAcD,wBAAgB,6BAA6B,CAC3C,0BAA0B,EAAE,SAAS,MAAM,EAAE,EAC7C,kBAAkB,EAAE,SAAS,MAAM,EAAE,EACrC,kBAAkB,EAAE,SAAS,MAAM,EAAE,GACpC,MAAM,EAAE,CAgBV;AAED,wBAAgB,yBAAyB,CACvC,0BAA0B,EAAE,SAAS,MAAM,EAAE,EAC7C,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAEV;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAOvE;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,CAEvE;AAED,wBAAgB,kCAAkC,CAChD,uBAAuB,EAAE,MAAM,GAAG,IAAI,EACtC,eAAe,EAAE,iBAAiB,GAAG,IAAI,GACxC,OAAO,CAIT;AAED,qBAAa,4BAA6B,SAAQ,KAAK;;CAKtD;AAED;;;GAGG;AACH,qBAAa,8BAA8B;IACzC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,UAAU,CAAK;IAEvB,aAAa,CACX,OAAO,EAAE,iBAAiB,GAAG,IAAI,EACjC,UAAU,EAAE,MAAM,IAAI,GACrB,OAAO;IAmBV,gBAAgB,IAAI,iBAAiB,GAAG,IAAI;IAa5C,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO;IAIpD,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI;IAM/C,GAAG,CAAC,CAAC,EACT,OAAO,EAAE,iBAAiB,EAC1B,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,KAAK,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,iBAAiB,KAAK,IAAI,EACtD,KAAK,EAAE,MAAM,IAAI,GAChB,OAAO,CAAC,CAAC,CAAC;CAuBd;AAED,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,8BAA8B,EAC3C,OAAO,EAAE,iBAAiB,GAAG,IAAI,EACjC,UAAU,EAAE,MAAM,IAAI,GACrB,IAAI,CAKN;AAED,wBAAsB,qCAAqC,CACzD,WAAW,EAAE,8BAA8B,EAC3C,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EAC9B,QAAQ,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EAC/C,KAAK,EAAE,MAAM,IAAI,GAChB,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED,4FAA4F;AAC5F,qBAAa,uBAAuB;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAoC;IAEpD,GAAG,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAazE;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,GAAG,GAAG,IAAI,CAAC;IAChB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IACvD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,gBAAgB,EACxB,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,GAChB,yBAAyB,CAmB3B;AAED,wBAAgB,+BAA+B,CAC7C,0BAA0B,EAAE,SAAS,MAAM,EAAE,GAC5C,yBAAyB,CAY3B"}