1
1
import { ExitIcon , GearIcon } from '@radix-ui/react-icons' ;
2
2
import { useTranslation } from '@shinkai_network/shinkai-i18n' ;
3
+ import { useGetEncryptionKeys } from '@shinkai_network/shinkai-node-state/lib/queries/getEncryptionKeys/useGetEncryptionKeys' ;
4
+ import { useSubmitRegistrationNoCode } from '@shinkai_network/shinkai-node-state/v2/mutations/submitRegistation/useSubmitRegistrationNoCode' ;
3
5
import { useGetHealth } from '@shinkai_network/shinkai-node-state/v2/queries/getHealth/useGetHealth' ;
4
6
import {
5
7
AlertDialog ,
@@ -31,6 +33,7 @@ import {
31
33
ToolsIcon ,
32
34
WorkflowPlaygroundIcon ,
33
35
} from '@shinkai_network/shinkai-ui/assets' ;
36
+ import { submitRegistrationNoCodeError } from '@shinkai_network/shinkai-ui/helpers' ;
34
37
import { cn } from '@shinkai_network/shinkai-ui/utils' ;
35
38
import { AnimatePresence , motion , TargetAndTransition } from 'framer-motion' ;
36
39
import { ArrowLeftToLine , ArrowRightToLine , BotIcon } from 'lucide-react' ;
@@ -48,8 +51,14 @@ import { ResourcesBanner } from '../../components/hardware-capabilities/resource
48
51
import { UpdateBanner } from '../../components/hardware-capabilities/update-banner' ;
49
52
import OnboardingStepper from '../../components/onboarding-checklist/onboarding' ;
50
53
import config from '../../config' ;
54
+ import {
55
+ useShinkaiNodeKillMutation ,
56
+ useShinkaiNodeRemoveStorageMutation ,
57
+ useShinkaiNodeSpawnMutation ,
58
+ } from '../../lib/shinkai-node-manager/shinkai-node-manager-client' ;
51
59
import { useAuth } from '../../store/auth' ;
52
60
import { useSettings } from '../../store/settings' ;
61
+ import { useShinkaiNodeManager } from '../../store/shinkai-node-manager' ;
53
62
54
63
type NavigationLink = {
55
64
title : string ;
@@ -211,10 +220,100 @@ const ShinkaiLogo = ({ className }: { className?: string }) => (
211
220
</ svg >
212
221
) ;
213
222
223
+ const ResetConnectionDialog = ( {
224
+ isOpen,
225
+ onOpenChange,
226
+ } : {
227
+ isOpen : boolean ;
228
+ onOpenChange : ( open : boolean ) => void ;
229
+ } ) => {
230
+ const { mutateAsync : shinkaiNodeKill } = useShinkaiNodeKillMutation ( ) ;
231
+ const { mutateAsync : shinkaiNodeSpawn } = useShinkaiNodeSpawnMutation ( {
232
+ onSuccess : async ( ) => {
233
+ if ( ! encryptionKeys ) return ;
234
+ await submitRegistrationNoCode ( {
235
+ profile : 'main' ,
236
+ registration_name : 'main_device' ,
237
+ node_address : 'http://127.0.0.1:9550' ,
238
+ ...encryptionKeys ,
239
+ } ) ;
240
+ } ,
241
+ } ) ;
242
+ const { mutateAsync : shinkaiNodeRemoveStorage } =
243
+ useShinkaiNodeRemoveStorageMutation ( ) ;
244
+ const { setShinkaiNodeOptions } = useShinkaiNodeManager ( ) ;
245
+ const { encryptionKeys } = useGetEncryptionKeys ( ) ;
246
+ const setAuth = useAuth ( ( state ) => state . setAuth ) ;
247
+ const navigate = useNavigate ( ) ;
248
+
249
+ const { mutateAsync : submitRegistrationNoCode } = useSubmitRegistrationNoCode (
250
+ {
251
+ onSuccess : ( response , setupPayload ) => {
252
+ if ( response . status !== 'success' ) {
253
+ shinkaiNodeKill ( ) ;
254
+ }
255
+ if ( response . status === 'success' && encryptionKeys ) {
256
+ const updatedSetupData = {
257
+ ...encryptionKeys ,
258
+ ...setupPayload ,
259
+ permission_type : '' ,
260
+ shinkai_identity : response . data ?. node_name ?? '' ,
261
+ node_signature_pk : response . data ?. identity_public_key ?? '' ,
262
+ node_encryption_pk : response . data ?. encryption_public_key ?? '' ,
263
+ api_v2_key : response . data ?. api_v2_key ?? '' ,
264
+ } ;
265
+ setAuth ( updatedSetupData ) ;
266
+ navigate ( '/ai-model-installation' ) ;
267
+ } else {
268
+ submitRegistrationNoCodeError ( ) ;
269
+ }
270
+ } ,
271
+ } ,
272
+ ) ;
273
+
274
+ const handleReset = async ( ) => {
275
+ await shinkaiNodeKill ( ) ;
276
+ await shinkaiNodeRemoveStorage ( { preserveKeys : true } ) ;
277
+ setShinkaiNodeOptions ( null ) ;
278
+ await shinkaiNodeSpawn ( ) ;
279
+ } ;
280
+
281
+ return (
282
+ < AlertDialog onOpenChange = { onOpenChange } open = { isOpen } >
283
+ < AlertDialogContent className = "w-[75%]" >
284
+ < AlertDialogHeader >
285
+ < AlertDialogTitle > App Reset Required</ AlertDialogTitle >
286
+ < AlertDialogDescription >
287
+ < div className = "flex flex-col space-y-3 text-left text-white/70" >
288
+ < div className = "text-sm" >
289
+ We’re currently in beta and we made some significant updates to
290
+ improve your experience. To apply these updates, we need to
291
+ reset your data.
292
+ < br /> < br />
293
+ If you need assistance, please contact our support team.
294
+ </ div >
295
+ </ div >
296
+ </ AlertDialogDescription >
297
+ </ AlertDialogHeader >
298
+ < AlertDialogFooter className = "mt-4 flex items-center justify-end gap-2.5" >
299
+ < Button
300
+ className = "min-w-32 text-sm"
301
+ onClick = { handleReset }
302
+ size = "sm"
303
+ variant = { 'destructive' }
304
+ >
305
+ Reset App
306
+ </ Button >
307
+ </ AlertDialogFooter >
308
+ </ AlertDialogContent >
309
+ </ AlertDialog >
310
+ ) ;
311
+ } ;
312
+
214
313
export function MainNav ( ) {
215
314
const { t, Trans } = useTranslation ( ) ;
216
315
const optInExperimental = useSettings ( ( state ) => state . optInExperimental ) ;
217
-
316
+ const auth = useAuth ( ( state ) => state . auth ) ;
218
317
const navigate = useNavigate ( ) ;
219
318
const logout = useAuth ( ( state ) => state . setLogout ) ;
220
319
const isGetStartedChecklistHidden = useSettings (
@@ -223,6 +322,8 @@ export function MainNav() {
223
322
224
323
const [ isConfirmLogoutDialogOpened , setIsConfirmLogoutDialogOpened ] =
225
324
useState ( false ) ;
325
+ const [ isApiV2KeyMissingDialogOpen , setIsApiV2KeyMissingDialogOpen ] =
326
+ useState ( false ) ;
226
327
227
328
const sidebarExpanded = useSettings ( ( state ) => state . sidebarExpanded ) ;
228
329
const toggleSidebar = useSettings ( ( state ) => state . toggleSidebar ) ;
@@ -231,6 +332,12 @@ export function MainNav() {
231
332
setIsConfirmLogoutDialogOpened ( true ) ;
232
333
} ;
233
334
335
+ useEffect ( ( ) => {
336
+ if ( ! auth ?. api_v2_key ) {
337
+ setIsApiV2KeyMissingDialogOpen ( true ) ;
338
+ }
339
+ } , [ auth ?. api_v2_key ] ) ;
340
+
234
341
const handleDisconnect = ( ) => {
235
342
logout ( ) ;
236
343
navigate ( '/get-started' ) ;
@@ -481,6 +588,10 @@ export function MainNav() {
481
588
</ div >
482
589
</ div >
483
590
591
+ < ResetConnectionDialog
592
+ isOpen = { isApiV2KeyMissingDialogOpen }
593
+ onOpenChange = { setIsApiV2KeyMissingDialogOpen }
594
+ />
484
595
< AlertDialog
485
596
onOpenChange = { setIsConfirmLogoutDialogOpened }
486
597
open = { isConfirmLogoutDialogOpened }
0 commit comments