@bytexbyte/nxtlinq-ai-agent-ui-react-development 0.4.1 → 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.
@@ -0,0 +1,217 @@
1
+ import * as React from 'react';
2
+ const useCommitPhaseEffect = typeof window === 'undefined'
3
+ ? React.useEffect
4
+ : React.useLayoutEffect;
5
+ export function commitProviderRuntime(identityRef, identity, environment, publishEnvironment) {
6
+ identityRef.current = identity;
7
+ publishEnvironment(environment);
8
+ }
9
+ export function useProviderRuntimeCommit(identityRef, identity, environment, publishEnvironment) {
10
+ useCommitPhaseEffect(() => {
11
+ commitProviderRuntime(identityRef, identity, environment, publishEnvironment);
12
+ }, [environment, identity, identityRef, publishEnvironment]);
13
+ }
14
+ function stableUnique(values) {
15
+ const seen = new Set();
16
+ const result = [];
17
+ for (const value of values) {
18
+ if (!seen.has(value)) {
19
+ seen.add(value);
20
+ result.push(value);
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+ export function replaceCurrentMaximumDenyList(persistedDeniedPermissions, maximumPermissions, checkedPermissions) {
26
+ const maximum = new Set(maximumPermissions);
27
+ const checked = new Set(checkedPermissions);
28
+ for (const permission of checked) {
29
+ if (!maximum.has(permission)) {
30
+ throw new Error(`Permission is outside the authoritative maximum: ${permission}`);
31
+ }
32
+ }
33
+ const retainedOutsideMaximum = persistedDeniedPermissions.filter((permission) => !maximum.has(permission));
34
+ const deniedInsideMaximum = maximumPermissions.filter((permission) => !checked.has(permission));
35
+ return stableUnique([...retainedOutsideMaximum, ...deniedInsideMaximum]);
36
+ }
37
+ export function removeOneDeniedPermission(persistedDeniedPermissions, permission) {
38
+ return stableUnique(persistedDeniedPermissions).filter((value) => value !== permission);
39
+ }
40
+ export function runtimeAITContextKey(context) {
41
+ return JSON.stringify([
42
+ context.controller,
43
+ context.serviceId,
44
+ context.roles === undefined ? null : [...context.roles],
45
+ context.permissionGroup ?? null,
46
+ ]);
47
+ }
48
+ export function runtimeAITSubjectKey(context) {
49
+ return JSON.stringify([context.controller, context.serviceId]);
50
+ }
51
+ export function runtimeAuthorizationMatchesContext(authorizationContextKey, renderedContext) {
52
+ return authorizationContextKey === (renderedContext ? runtimeAITContextKey(renderedContext) : null);
53
+ }
54
+ export class StaleRuntimeAITResponseError extends Error {
55
+ constructor() {
56
+ super('Stale runtime AIT response was discarded');
57
+ this.name = 'StaleRuntimeAITResponseError';
58
+ }
59
+ }
60
+ /**
61
+ * Owns the authoritative recompute lifecycle. Only the newest request for the
62
+ * active captured context may write state; its failures clear state first.
63
+ */
64
+ export class RuntimeAITRecomputeCoordinator {
65
+ constructor() {
66
+ this.activeContextKey = null;
67
+ this.activeContext = null;
68
+ this.generation = 0;
69
+ }
70
+ commitContext(context, invalidate) {
71
+ const nextKey = context ? runtimeAITContextKey(context) : null;
72
+ if (nextKey === this.activeContextKey) {
73
+ return false;
74
+ }
75
+ this.activeContextKey = nextKey;
76
+ this.activeContext = context ? {
77
+ controller: context.controller,
78
+ serviceId: context.serviceId,
79
+ ...(context.roles !== undefined ? { roles: [...context.roles] } : {}),
80
+ ...(context.permissionGroup !== undefined
81
+ ? { permissionGroup: context.permissionGroup }
82
+ : {}),
83
+ } : null;
84
+ this.generation += 1;
85
+ invalidate();
86
+ return true;
87
+ }
88
+ getActiveContext() {
89
+ return this.activeContext ? {
90
+ controller: this.activeContext.controller,
91
+ serviceId: this.activeContext.serviceId,
92
+ ...(this.activeContext.roles !== undefined
93
+ ? { roles: [...this.activeContext.roles] }
94
+ : {}),
95
+ ...(this.activeContext.permissionGroup !== undefined
96
+ ? { permissionGroup: this.activeContext.permissionGroup }
97
+ : {}),
98
+ } : null;
99
+ }
100
+ isContextActive(context) {
101
+ return runtimeAITContextKey(context) === this.activeContextKey;
102
+ }
103
+ assertContextActive(context) {
104
+ if (!this.isContextActive(context)) {
105
+ throw new StaleRuntimeAITResponseError();
106
+ }
107
+ }
108
+ async run(context, request, apply, clear) {
109
+ this.assertContextActive(context);
110
+ const contextKey = runtimeAITContextKey(context);
111
+ const generation = ++this.generation;
112
+ try {
113
+ const result = await request();
114
+ if (generation !== this.generation || contextKey !== this.activeContextKey) {
115
+ throw new StaleRuntimeAITResponseError();
116
+ }
117
+ apply(result, context);
118
+ return result;
119
+ }
120
+ catch (error) {
121
+ if (!(error instanceof StaleRuntimeAITResponseError)
122
+ && generation === this.generation
123
+ && contextKey === this.activeContextKey) {
124
+ clear();
125
+ }
126
+ throw error;
127
+ }
128
+ }
129
+ }
130
+ export function useRuntimeAITContextCommit(coordinator, context, invalidate) {
131
+ const contextKey = context ? runtimeAITContextKey(context) : null;
132
+ useCommitPhaseEffect(() => {
133
+ coordinator.commitContext(context, invalidate);
134
+ }, [contextKey, coordinator, invalidate]);
135
+ }
136
+ export async function dispatchRuntimeAITCompleteReplacement(coordinator, context, update, converge, clear) {
137
+ const subjectKey = runtimeAITSubjectKey(context);
138
+ coordinator.assertContextActive(context);
139
+ let updateFailed = false;
140
+ let updateError;
141
+ try {
142
+ await update();
143
+ }
144
+ catch (error) {
145
+ updateFailed = true;
146
+ updateError = error;
147
+ }
148
+ try {
149
+ await converge(subjectKey);
150
+ }
151
+ catch (error) {
152
+ if (!updateFailed) {
153
+ throw error;
154
+ }
155
+ }
156
+ if (updateFailed) {
157
+ if (!coordinator.isContextActive(context)) {
158
+ throw new StaleRuntimeAITResponseError();
159
+ }
160
+ clear();
161
+ throw updateError;
162
+ }
163
+ coordinator.assertContextActive(context);
164
+ }
165
+ /** Serializes reads, complete replacements, and convergence for one persistence subject. */
166
+ export class RuntimeAITMutationQueue {
167
+ constructor() {
168
+ this.tails = new Map();
169
+ }
170
+ async run(subjectKey, mutation) {
171
+ const previous = this.tails.get(subjectKey) ?? Promise.resolve();
172
+ const result = previous.catch(() => undefined).then(mutation);
173
+ const tail = result.then(() => undefined, () => undefined);
174
+ this.tails.set(subjectKey, tail);
175
+ try {
176
+ return await result;
177
+ }
178
+ finally {
179
+ if (this.tails.get(subjectKey) === tail) {
180
+ this.tails.delete(subjectKey);
181
+ }
182
+ }
183
+ }
184
+ }
185
+ export function runtimeAuthorizationState(result, controller, serviceId) {
186
+ return {
187
+ ait: result.aitId
188
+ ? {
189
+ aitId: result.aitId,
190
+ controller,
191
+ serviceId,
192
+ metadata: { permissions: [...result.effectivePermissions] },
193
+ }
194
+ : null,
195
+ maximumPermissions: [...result.maximumPermissions],
196
+ effectivePermissions: [...result.effectivePermissions],
197
+ deniedPermissions: [...result.deniedPermissions],
198
+ selectedRuleId: result.selectedRuleId,
199
+ selectedRuleType: result.selectedRuleType,
200
+ expiresAt: result.expiresAt,
201
+ grantActive: result.grantActive,
202
+ unavailable: false,
203
+ };
204
+ }
205
+ export function unavailableRuntimeAuthorization(persistedDeniedPermissions) {
206
+ return {
207
+ ait: null,
208
+ maximumPermissions: [],
209
+ effectivePermissions: [],
210
+ deniedPermissions: [...persistedDeniedPermissions],
211
+ selectedRuleId: null,
212
+ selectedRuleType: 'none',
213
+ expiresAt: null,
214
+ grantActive: false,
215
+ unavailable: true,
216
+ };
217
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ChatBotUI.d.ts","sourceRoot":"","sources":["../../src/ui/ChatBotUI.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAqG/B,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAitB7B,CAAC"}
1
+ {"version":3,"file":"ChatBotUI.d.ts","sourceRoot":"","sources":["../../src/ui/ChatBotUI.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAsG/B,eAAO,MAAM,SAAS,EAAE,KAAK,CAAC,EAktB7B,CAAC"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "@emotion/reac
2
2
  /** @jsxImportSource @emotion/react */
3
3
  import { css } from '@emotion/react';
4
4
  import * as React from 'react';
5
+ import { hasRecordedWalletVerification } from '@bytexbyte/nxtlinq-ai-agent-core-development';
5
6
  import { useDraggable, useLocalStorage, useResizable, walletTextUtils } from '@bytexbyte/nxtlinq-ai-agent-web-development';
6
7
  import { useChatBot } from '../context/ChatBotContext';
7
8
  import { ChatBotHeader } from './ChatBotHeader';
@@ -93,7 +94,8 @@ export const ChatBotUI = () => {
93
94
  // Check if there's a berifyme token in URL (indicating recent berifyme verification)
94
95
  const urlParams = new URLSearchParams(window.location.search);
95
96
  const hasBerifymeToken = urlParams.get('token') && urlParams.get('method') === 'berifyme';
96
- const isWalletVerifiedWithBerifyme = walletInfo?.id && walletInfo?.method === 'berifyme';
97
+ const hasRecordedVerification = Boolean(walletInfo?.id)
98
+ && hasRecordedWalletVerification(walletInfo);
97
99
  // Helper function to update IDV suggestion state based on storage value
98
100
  const updateIDVSuggestionState = React.useCallback((dismissedValue) => {
99
101
  // Clear any existing countdown interval
@@ -150,14 +152,14 @@ export const ChatBotUI = () => {
150
152
  const shouldShowBanner = hitAddress &&
151
153
  !props.requireWalletIDVVerification &&
152
154
  !hasBerifymeToken &&
153
- !isWalletVerifiedWithBerifyme &&
155
+ !hasRecordedVerification &&
154
156
  !isNeedSignInWithWallet;
155
157
  if (shouldShowBanner) {
156
158
  const timer = setTimeout(() => {
157
159
  const shouldShowBannerAfterDelay = hitAddress &&
158
160
  !props.requireWalletIDVVerification &&
159
161
  !hasBerifymeToken &&
160
- !isWalletVerifiedWithBerifyme &&
162
+ !hasRecordedVerification &&
161
163
  !isNeedSignInWithWallet;
162
164
  if (shouldShowBannerAfterDelay) {
163
165
  const dismissed = localStorage.getItem('idv-suggestion-dismissed');
@@ -530,7 +532,7 @@ export const ChatBotUI = () => {
530
532
  left: ${MOBILE_EDGE_MARGIN}px !important;
531
533
  top: ${MOBILE_EDGE_MARGIN}px !important;
532
534
  ` : ''}
533
- `], children: [!mobileLayout && (_jsxs(_Fragment, { children: [_jsx("div", { css: resizeHandleNW, onPointerDown: handleResizeStart('nw'), title: "Resize", "aria-label": "Resize chat window from top-left" }), _jsx("div", { css: resizeHandleNE, onPointerDown: handleResizeStart('ne'), title: "Resize", "aria-label": "Resize chat window from top-right" }), _jsx("div", { css: resizeHandleSW, onPointerDown: handleResizeStart('sw'), title: "Resize", "aria-label": "Resize chat window from bottom-left" }), _jsx("div", { css: resizeHandleSE, onPointerDown: handleResizeStart('se'), title: "Resize", "aria-label": "Resize chat window from bottom-right" })] })), _jsx(ChatBotHeader, { mobileLayout: headerCompactLayout, isDragging: isDragging, onDragStart: handleDragStart, isVoiceMode: isVoiceMode, isVoiceConnecting: isVoiceConnecting, onVoiceToggle: () => void ((isVoiceMode || isVoiceConnecting) ? exitVoiceMode() : enterVoiceMode()), piiDisplayMode: piiDisplayMode, isAITLoading: isAITLoading, onSettingsClick: handleSettingsClick, onClose: handleClose }), showIDVSuggestion && hitAddress && !props.requireWalletIDVVerification && !hasBerifymeToken && !isWalletVerifiedWithBerifyme && (_jsxs("div", { "data-idv-banner": true, css: idvBanner, children: [_jsx("div", { css: css `
535
+ `], children: [!mobileLayout && (_jsxs(_Fragment, { children: [_jsx("div", { css: resizeHandleNW, onPointerDown: handleResizeStart('nw'), title: "Resize", "aria-label": "Resize chat window from top-left" }), _jsx("div", { css: resizeHandleNE, onPointerDown: handleResizeStart('ne'), title: "Resize", "aria-label": "Resize chat window from top-right" }), _jsx("div", { css: resizeHandleSW, onPointerDown: handleResizeStart('sw'), title: "Resize", "aria-label": "Resize chat window from bottom-left" }), _jsx("div", { css: resizeHandleSE, onPointerDown: handleResizeStart('se'), title: "Resize", "aria-label": "Resize chat window from bottom-right" })] })), _jsx(ChatBotHeader, { mobileLayout: headerCompactLayout, isDragging: isDragging, onDragStart: handleDragStart, isVoiceMode: isVoiceMode, isVoiceConnecting: isVoiceConnecting, onVoiceToggle: () => void ((isVoiceMode || isVoiceConnecting) ? exitVoiceMode() : enterVoiceMode()), piiDisplayMode: piiDisplayMode, isAITLoading: isAITLoading, onSettingsClick: handleSettingsClick, onClose: handleClose }), showIDVSuggestion && hitAddress && !props.requireWalletIDVVerification && !hasBerifymeToken && !hasRecordedVerification && (_jsxs("div", { "data-idv-banner": true, css: idvBanner, children: [_jsx("div", { css: css `
534
536
  font-size: 20px !important;
535
537
  color: #f39c12 !important;
536
538
  `, children: "\uD83D\uDCA1" }), _jsxs("div", { css: css `flex: 1 !important;`, children: [_jsx("h5", { css: idvBannerTitle, children: walletTextUtils.getWalletText('Recommended: Verify Your Wallet', serviceId) }), _jsx("p", { css: idvBannerText, children: walletTextUtils.getWalletText('While not required, verifying your wallet with Berify.me provides additional security and trust for your AI agent interactions.', serviceId) }), _jsx("button", { onClick: () => onVerifyWallet('berifyme'), css: idvVerifyButton, children: walletTextUtils.getWalletText('Verify Wallet', serviceId) })] }), _jsx("button", { onClick: handleDismissIDV, css: idvDismissButton, title: `Hide for ${Math.floor((props.idvBannerDismissSeconds || 86400) / 3600)} hours`, children: "\u00D7" })] })), !showIDVSuggestion && dismissUntil && timeRemaining && (_jsxs("div", { css: css `
@@ -1 +1 @@
1
- {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/ui/MessageList.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAuT/B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAmc/B,CAAC"}
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../src/ui/MessageList.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAuT/B,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAyc/B,CAAC"}
@@ -231,7 +231,7 @@ const PiiStatusHeader = React.memo(({ message }) => {
231
231
  return (_jsxs("div", { css: piiHeaderRow, children: [_jsx(ShieldIcon, {}), _jsx("span", { children: "\u2713 Protected" })] }));
232
232
  });
233
233
  export const MessageList = () => {
234
- const { messages, isLoading, isTtsProcessing, requiresGesture, retryTtsWithGesture, connectWallet, signInWallet, hitAddress, isAutoConnecting, isNeedSignInWithWallet, enableAIT, isAITLoading, isAITEnabling, sendMessage, permissions, availableModels, serviceId, piiDisplayMode, } = useChatBot();
234
+ const { messages, isLoading, isTtsProcessing, requiresGesture, retryTtsWithGesture, connectWallet, signInWallet, hitAddress, isAutoConnecting, isNeedSignInWithWallet, enableAIT, isAITLoading, isAITEnabling, sendMessage, permissions, availableModels, serviceId, piiDisplayMode, setShowPermissionForm, setIsPermissionFormOpen, } = useChatBot();
235
235
  const messagesEndRef = React.useRef(null);
236
236
  const scrollToBottom = () => {
237
237
  messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
@@ -266,6 +266,10 @@ export const MessageList = () => {
266
266
  }
267
267
  }
268
268
  }
269
+ else if (buttonType === 'verifyWallet') {
270
+ setIsPermissionFormOpen(true);
271
+ setShowPermissionForm(true);
272
+ }
269
273
  else if (buttonType === 'continue') {
270
274
  const lastUserMsg = [...messages].reverse().find(m => m.role === 'user');
271
275
  if (lastUserMsg && lastUserMsg.content) {
@@ -420,11 +424,12 @@ export const MessageList = () => {
420
424
  chatbotButton, children: isAutoConnecting ? 'Connecting...' :
421
425
  message.button === 'connectWallet' ? (Boolean(hitAddress) ? 'Connected' : walletTextUtils.getWalletText('Connect Wallet', serviceId)) :
422
426
  message.button === 'signIn' ? (!isNeedSignInWithWallet ? 'Signed In' : 'Sign In') :
423
- message.button === 'continue' ? 'Continue' :
424
- message.button === 'enableAIT' ?
425
- ((isAITLoading || isAITEnabling) ? 'Enabling...' :
426
- (message.metadata?.requiredPermission && permissions.includes(message.metadata.requiredPermission)) ? 'AIT Enabled' : 'Enable AIT Permissions') :
427
- message.button }) }))] }), showPiiHeader && message.piiStatus === 'complete' && entityCount > 0 && (_jsxs("div", { css: css `text-align: right !important;`, children: [_jsxs("button", { css: piiBelowBubbleBtn, onClick: () => setExpandedPiiMsgId(v => v === message.id ? null : message.id), type: "button", children: [_jsx(GreenCheckIcon, {}), entityCount, " item", entityCount !== 1 ? 's' : '', " protected ", isPiiExpanded ? '▴' : '▸'] }), isPiiExpanded && (_jsx("div", { css: piiEntityPanel, children: Object.entries(relevantMapping).map(([original, token]) => (_jsxs("div", { css: piiEntityRowStyle, children: [_jsx("span", { css: piiOriginalStyle, children: original }), _jsx("span", { css: piiArrowStyle, children: "\u2192" }), _jsx("span", { css: piiTokenMappingStyle, children: token })] }, original))) }))] })), message.role === 'assistant' && message.metadata?.model && (_jsxs("div", { css: css `
427
+ message.button === 'verifyWallet' ? 'Verify Wallet' :
428
+ message.button === 'continue' ? 'Continue' :
429
+ message.button === 'enableAIT' ?
430
+ ((isAITLoading || isAITEnabling) ? 'Enabling...' :
431
+ (message.metadata?.requiredPermission && permissions.includes(message.metadata.requiredPermission)) ? 'AIT Enabled' : 'Enable AIT Permissions') :
432
+ message.button }) }))] }), showPiiHeader && message.piiStatus === 'complete' && entityCount > 0 && (_jsxs("div", { css: css `text-align: right !important;`, children: [_jsxs("button", { css: piiBelowBubbleBtn, onClick: () => setExpandedPiiMsgId(v => v === message.id ? null : message.id), type: "button", children: [_jsx(GreenCheckIcon, {}), entityCount, " item", entityCount !== 1 ? 's' : '', " protected ", isPiiExpanded ? '▴' : '▸'] }), isPiiExpanded && (_jsx("div", { css: piiEntityPanel, children: Object.entries(relevantMapping).map(([original, token]) => (_jsxs("div", { css: piiEntityRowStyle, children: [_jsx("span", { css: piiOriginalStyle, children: original }), _jsx("span", { css: piiArrowStyle, children: "\u2192" }), _jsx("span", { css: piiTokenMappingStyle, children: token })] }, original))) }))] })), message.role === 'assistant' && message.metadata?.model && (_jsxs("div", { css: css `
428
433
  ${modelIndicator}
429
434
  gap: 8px !important;
430
435
  `, children: [_jsxs("div", { css: modelBadge, children: [_jsx("span", { css: modelDot }), getModelDisplayName(message.metadata.model)] }), (isTtsProcessing || requiresGesture) && !isLoading && message.id === messages[messages.length - 1]?.id && (_jsxs("div", { css: css `
@@ -1 +1 @@
1
- {"version":3,"file":"PermissionForm.d.ts","sourceRoot":"","sources":["../../src/ui/PermissionForm.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,UAAU,mBAAmB;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA4mBxD,CAAC"}
1
+ {"version":3,"file":"PermissionForm.d.ts","sourceRoot":"","sources":["../../src/ui/PermissionForm.tsx"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,UAAU,mBAAmB;IAC3B,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAsmBxD,CAAC"}
@@ -4,6 +4,7 @@ import * as React from 'react';
4
4
  import { css } from '@emotion/react';
5
5
  import { useChatBot } from '../context/ChatBotContext';
6
6
  import { walletTextUtils } from '@bytexbyte/nxtlinq-ai-agent-web-development';
7
+ import { hasRecordedWalletVerification } from '@bytexbyte/nxtlinq-ai-agent-core-development';
7
8
  import { actionButton } from './styles/isolatedStyles';
8
9
  export const PermissionForm = ({ onClose }) => {
9
10
  const { hitAddress, permissions, setPermissions, setIsDisabled, onSave, onConnectWallet, onSignIn, isNeedSignInWithWallet, walletInfo, onVerifyWallet, serviceId, nxtlinqApi, permissionGroup, isAITLoading, isWalletLoading = false, refreshAIT, props } = useChatBot();
@@ -73,12 +74,10 @@ export const PermissionForm = ({ onClose }) => {
73
74
  }, [hitAddress]);
74
75
  // Check if wallet IDV verification is required based on configuration
75
76
  const requireWalletIDVVerification = props.requireWalletIDVVerification ?? true; // Default to true
76
- const isWalletVerified = Boolean(walletInfo?.id);
77
- const isWalletVerifiedWithBerifyme = walletInfo?.method === 'berifyme';
78
- // Show verification prompt if:
79
- // 1. IDV verification is required AND wallet is not verified, OR
80
- // 2. IDV verification is required AND wallet is verified but not with Berifyme
81
- const shouldShowVerificationPrompt = requireWalletIDVVerification && (!isWalletVerified || !isWalletVerifiedWithBerifyme);
77
+ // Any recorded verification source is valid. Custom additionally requires
78
+ // its explicit username evidence so synthetic AIT-provisioned rows do not count.
79
+ const shouldShowVerificationPrompt = requireWalletIDVVerification
80
+ && (!walletInfo?.id || !hasRecordedWalletVerification(walletInfo));
82
81
  const handleSave = async () => {
83
82
  setIsSaving(true);
84
83
  try {
@@ -309,9 +308,7 @@ export const PermissionForm = ({ onClose }) => {
309
308
  margin-bottom: 24px !important;
310
309
  font-size: 16px !important;
311
310
  color: #666 !important;
312
- `, children: isWalletVerified && !isWalletVerifiedWithBerifyme
313
- ? walletTextUtils.getWalletText('Your wallet is verified with custom method, but Berify.me verification is required to continue.', serviceId)
314
- : walletTextUtils.getWalletText('Please verify your wallet with Berify.me to continue', serviceId) }), _jsx("button", { onClick: () => onVerifyWallet('berifyme'), css: css `
311
+ `, children: walletTextUtils.getWalletText('Please verify your wallet identity to continue', serviceId) }), _jsx("button", { onClick: () => onVerifyWallet('berifyme'), css: css `
315
312
  ${actionButton}
316
313
  padding: 12px 24px !important;
317
314
  background-color: #007bff !important;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytexbyte/nxtlinq-ai-agent-ui-react-development",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Official React Web UI for nxtlinq AI Agent — drop-in chat widget",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -38,8 +38,8 @@
38
38
  "react-dom": ">=18.0.0"
39
39
  },
40
40
  "dependencies": {
41
- "@bytexbyte/nxtlinq-ai-agent-core-development": "0.5.0",
42
- "@bytexbyte/nxtlinq-ai-agent-web-development": "0.4.0",
41
+ "@bytexbyte/nxtlinq-ai-agent-core-development": "2.0.1",
42
+ "@bytexbyte/nxtlinq-ai-agent-web-development": "1.0.1",
43
43
  "@emotion/react": "^11.14.0",
44
44
  "@emotion/styled": "^11.14.1",
45
45
  "@mui/icons-material": "^7.2.0",
@@ -55,4 +55,4 @@
55
55
  "react-dom": "^18.2.0",
56
56
  "typescript": "^5.4.2"
57
57
  }
58
- }
58
+ }