From c4b85c0dcbaa030655a55e84dd2fd73190cebab0 Mon Sep 17 00:00:00 2001
From: Paul Ccari <46382556+paulclindo@users.noreply.github.com>
Date: Tue, 28 Jan 2025 23:55:30 -0500
Subject: [PATCH] feat: implement pagination inboxes (#617)
* esllint
* refactor
* feat: pagination wip
* feat: change inbox name updated to v2 and fixes
* fixes
* updates
---
.../use-onboarding-stepper.ts | 9 +-
.../components/reset-connection-dialog.tsx | 138 +++++++++++++++++
.../components/tools/components/tool-card.tsx | 9 +-
.../src/hooks/use-current-inbox.ts | 10 +-
.../src/lib/shinkai-node-overlay.tsx | 2 +-
.../shinkai-desktop/src/pages/chat/layout.tsx | 141 +++++++++++-------
.../src/pages/galxe-subscriptions.tsx | 8 +-
.../src/pages/layout/main-layout.tsx | 141 +-----------------
.../edit-inbox-name-dialog.tsx | 11 +-
libs/shinkai-message-ts/src/api/jobs/index.ts | 36 +++++
libs/shinkai-message-ts/src/api/jobs/types.ts | 19 +++
.../lib/mutations/updateInboxName/index.ts | 34 -----
.../lib/mutations/updateInboxName/types.ts | 12 --
libs/shinkai-node-state/src/v2/constants.ts | 1 +
.../src/v2/mutations/updateInboxName/index.ts | 17 +++
.../src/v2/mutations/updateInboxName/types.ts | 10 ++
.../updateInboxName/useUpdateInboxName.ts | 6 +-
.../src/v2/queries/getInboxes/index.ts | 20 ++-
.../src/v2/queries/getInboxes/types.ts | 15 +-
.../v2/queries/getInboxes/useGetInboxes.ts | 10 +-
.../getInboxes/useGetInboxesWithPagination.ts | 44 ++++++
21 files changed, 410 insertions(+), 283 deletions(-)
create mode 100644 apps/shinkai-desktop/src/components/reset-connection-dialog.tsx
delete mode 100644 libs/shinkai-node-state/src/lib/mutations/updateInboxName/index.ts
delete mode 100644 libs/shinkai-node-state/src/lib/mutations/updateInboxName/types.ts
create mode 100644 libs/shinkai-node-state/src/v2/mutations/updateInboxName/index.ts
create mode 100644 libs/shinkai-node-state/src/v2/mutations/updateInboxName/types.ts
rename libs/shinkai-node-state/src/{lib => v2}/mutations/updateInboxName/useUpdateInboxName.ts (80%)
create mode 100644 libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxesWithPagination.ts
diff --git a/apps/shinkai-desktop/src/components/onboarding-checklist/use-onboarding-stepper.ts b/apps/shinkai-desktop/src/components/onboarding-checklist/use-onboarding-stepper.ts
index 7a5c12471..454ca556a 100644
--- a/apps/shinkai-desktop/src/components/onboarding-checklist/use-onboarding-stepper.ts
+++ b/apps/shinkai-desktop/src/components/onboarding-checklist/use-onboarding-stepper.ts
@@ -1,7 +1,7 @@
import { flattenDirectoryContents } from '@shinkai_network/shinkai-node-state/lib/utils/files';
import { useGetListDirectoryContents } from '@shinkai_network/shinkai-node-state/v2/queries/getDirectoryContents/useGetListDirectoryContents';
import { useGetHealth } from '@shinkai_network/shinkai-node-state/v2/queries/getHealth/useGetHealth';
-import { useGetInboxes } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxes';
+import { useGetInboxesWithPagination } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxesWithPagination';
import { useGetLLMProviders } from '@shinkai_network/shinkai-node-state/v2/queries/getLLMProviders/useGetLLMProviders';
import { useMap } from '@shinkai_network/shinkai-ui/hooks';
import { useEffect } from 'react';
@@ -27,7 +27,7 @@ export const useOnboardingSteps = () => {
token: auth?.api_v2_key ?? '',
});
- const { inboxes } = useGetInboxes({
+ const { data: inboxesPagination } = useGetInboxesWithPagination({
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
});
@@ -69,6 +69,9 @@ export const useOnboardingSteps = () => {
}, [VRFiles]);
useEffect(() => {
+ const inboxes =
+ inboxesPagination?.pages.flatMap((page) => page.inboxes) ?? [];
+
if (inboxes.length > 1) {
currentStepsMap.set(GetStartedSteps.CreateAIChat, GetStartedStatus.Done);
}
@@ -87,7 +90,7 @@ export const useOnboardingSteps = () => {
GetStartedStatus.Done,
);
}
- }, [inboxes]);
+ }, [inboxesPagination]);
// useEffect(() => {
// if ((subscriptionFolder ?? [])?.length > 0) {
diff --git a/apps/shinkai-desktop/src/components/reset-connection-dialog.tsx b/apps/shinkai-desktop/src/components/reset-connection-dialog.tsx
new file mode 100644
index 000000000..411e25aa7
--- /dev/null
+++ b/apps/shinkai-desktop/src/components/reset-connection-dialog.tsx
@@ -0,0 +1,138 @@
+import { useSubmitRegistrationNoCode } from '@shinkai_network/shinkai-node-state/v2/mutations/submitRegistation/useSubmitRegistrationNoCode';
+import { useGetEncryptionKeys } from '@shinkai_network/shinkai-node-state/v2/queries/getEncryptionKeys/useGetEncryptionKeys';
+import {
+ AlertDialog,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+ Button,
+} from '@shinkai_network/shinkai-ui';
+import { submitRegistrationNoCodeError } from '@shinkai_network/shinkai-ui/helpers';
+import { XIcon } from 'lucide-react';
+import { useNavigate } from 'react-router-dom';
+
+import {
+ useShinkaiNodeKillMutation,
+ useShinkaiNodeRemoveStorageMutation,
+ useShinkaiNodeSpawnMutation,
+} from '../lib/shinkai-node-manager/shinkai-node-manager-client';
+import { useAuth } from '../store/auth';
+import { useShinkaiNodeManager } from '../store/shinkai-node-manager';
+
+export const ResetConnectionDialog = ({
+ isOpen,
+ onOpenChange,
+ allowClose = false,
+}: {
+ isOpen: boolean;
+ onOpenChange: (open: boolean) => void;
+ allowClose?: boolean;
+}) => {
+ const { mutateAsync: shinkaiNodeKill, isPending: isShinkaiNodeKillPending } =
+ useShinkaiNodeKillMutation();
+ const {
+ mutateAsync: shinkaiNodeSpawn,
+ isPending: isShinkaiNodeSpawnPending,
+ } = useShinkaiNodeSpawnMutation({
+ onSuccess: async () => {
+ if (!encryptionKeys) return;
+ await submitRegistrationNoCode({
+ profile: 'main',
+ registration_name: 'main_device',
+ node_address: 'http://127.0.0.1:9550',
+ ...encryptionKeys,
+ });
+ },
+ });
+ const {
+ mutateAsync: shinkaiNodeRemoveStorage,
+ isPending: isShinkaiNodeRemoveStoragePending,
+ } = useShinkaiNodeRemoveStorageMutation();
+ const { setShinkaiNodeOptions } = useShinkaiNodeManager();
+ const { encryptionKeys } = useGetEncryptionKeys();
+ const setAuth = useAuth((state) => state.setAuth);
+ const navigate = useNavigate();
+
+ const isResetLoading =
+ isShinkaiNodeKillPending ||
+ isShinkaiNodeRemoveStoragePending ||
+ isShinkaiNodeSpawnPending;
+
+ const { mutateAsync: submitRegistrationNoCode } = useSubmitRegistrationNoCode(
+ {
+ onSuccess: (response, setupPayload) => {
+ if (response.status !== 'success') {
+ shinkaiNodeKill();
+ }
+ if (response.status === 'success' && encryptionKeys) {
+ const updatedSetupData = {
+ ...encryptionKeys,
+ ...setupPayload,
+ permission_type: '',
+ shinkai_identity: response.data?.node_name ?? '',
+ node_signature_pk: response.data?.identity_public_key ?? '',
+ node_encryption_pk: response.data?.encryption_public_key ?? '',
+ api_v2_key: response.data?.api_v2_key ?? '',
+ };
+ setAuth(updatedSetupData);
+ navigate('/ai-model-installation');
+ onOpenChange(false);
+ } else {
+ submitRegistrationNoCodeError();
+ }
+ },
+ },
+ );
+
+ const handleReset = async () => {
+ await shinkaiNodeKill();
+ useAuth.getState().setLogout(); // clean up local storage
+ await shinkaiNodeRemoveStorage({ preserveKeys: true });
+ setShinkaiNodeOptions(null);
+ await shinkaiNodeSpawn();
+ };
+
+ return (
+
+
+ {allowClose && (
+
+
+
+ )}
+
+ App Reset Required
+
+
+
+ We're currently in beta and we made some significant
+ updates to improve your experience. To apply these updates, we
+ need to reset your data.
+
+ If you need assistance, please contact our support team.
+
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/apps/shinkai-desktop/src/components/tools/components/tool-card.tsx b/apps/shinkai-desktop/src/components/tools/components/tool-card.tsx
index 5f40981b4..e3aada827 100644
--- a/apps/shinkai-desktop/src/components/tools/components/tool-card.tsx
+++ b/apps/shinkai-desktop/src/components/tools/components/tool-card.tsx
@@ -35,14 +35,7 @@ import { save } from '@tauri-apps/plugin-dialog';
import * as fs from '@tauri-apps/plugin-fs';
import { BaseDirectory } from '@tauri-apps/plugin-fs';
import { open } from '@tauri-apps/plugin-shell';
-import {
- CheckCircle,
- DownloadIcon,
- MoreVertical,
- PlayCircle,
- Rocket,
-} from 'lucide-react';
-import { InfoCircleIcon } from 'primereact/icons/infocircle';
+import { DownloadIcon, MoreVertical, PlayCircle, Rocket } from 'lucide-react';
import { useEffect, useState } from 'react';
import { Link, useParams } from 'react-router-dom';
import { toast } from 'sonner';
diff --git a/apps/shinkai-desktop/src/hooks/use-current-inbox.ts b/apps/shinkai-desktop/src/hooks/use-current-inbox.ts
index f6ebaea39..4cbb0bc6b 100644
--- a/apps/shinkai-desktop/src/hooks/use-current-inbox.ts
+++ b/apps/shinkai-desktop/src/hooks/use-current-inbox.ts
@@ -1,4 +1,4 @@
-import { useGetInboxes } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxes';
+import { useGetInboxesWithPagination } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxesWithPagination';
import { useMemo } from 'react';
import { useLocation } from 'react-router-dom';
@@ -8,7 +8,7 @@ export const useGetCurrentInbox = (inboxId?: string) => {
const auth = useAuth((state) => state.auth);
const location = useLocation();
- const { inboxes } = useGetInboxes({
+ const { data: inboxesPagination } = useGetInboxesWithPagination({
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
});
@@ -16,8 +16,10 @@ export const useGetCurrentInbox = (inboxId?: string) => {
const currentInboxId = inboxId ?? location.pathname.split('/')?.[2];
const decodedInboxId = decodeURIComponent(currentInboxId);
- return inboxes.find((inbox) => decodedInboxId === inbox.inbox_id);
- }, [inboxId, inboxes, location.pathname]);
+ return inboxesPagination?.pages
+ .flatMap((page) => page.inboxes)
+ .find((inbox) => decodedInboxId === inbox.inbox_id);
+ }, [inboxId, inboxesPagination, location.pathname]);
return currentInbox;
};
diff --git a/apps/shinkai-desktop/src/lib/shinkai-node-overlay.tsx b/apps/shinkai-desktop/src/lib/shinkai-node-overlay.tsx
index 408aa15a8..8275ccdca 100644
--- a/apps/shinkai-desktop/src/lib/shinkai-node-overlay.tsx
+++ b/apps/shinkai-desktop/src/lib/shinkai-node-overlay.tsx
@@ -8,7 +8,7 @@ import { DownloadIcon, Loader2 } from 'lucide-react';
import React, { useState } from 'react';
import { toast } from 'sonner';
-import { ResetConnectionDialog } from '../pages/layout/main-layout';
+import { ResetConnectionDialog } from '../components/reset-connection-dialog';
import { useAuth } from '../store/auth';
import { useShinkaiNodeManager } from '../store/shinkai-node-manager';
import { useRetrieveLogsQuery } from './shinkai-logs/logs-client';
diff --git a/apps/shinkai-desktop/src/pages/chat/layout.tsx b/apps/shinkai-desktop/src/pages/chat/layout.tsx
index b9b516dde..73e4896c2 100644
--- a/apps/shinkai-desktop/src/pages/chat/layout.tsx
+++ b/apps/shinkai-desktop/src/pages/chat/layout.tsx
@@ -9,9 +9,9 @@ import {
UpdateInboxNameFormSchema,
updateInboxNameFormSchema,
} from '@shinkai_network/shinkai-node-state/forms/chat/inbox';
-import { useUpdateInboxName } from '@shinkai_network/shinkai-node-state/lib/mutations/updateInboxName/useUpdateInboxName';
import { useRemoveJob } from '@shinkai_network/shinkai-node-state/v2/mutations/removeJob/useRemoveJob';
-import { useGetInboxes } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxes';
+import { useUpdateInboxName } from '@shinkai_network/shinkai-node-state/v2/mutations/updateInboxName/useUpdateInboxName';
+import { useGetInboxesWithPagination } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxesWithPagination';
import {
Button,
Dialog,
@@ -45,6 +45,7 @@ import { AnimatePresence, motion } from 'framer-motion';
import { Edit3, Trash2Icon } from 'lucide-react';
import { memo, useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
+import { useInView } from 'react-intersection-observer';
import { Link, Outlet, useMatch, useNavigate } from 'react-router-dom';
import { toast } from 'sonner';
@@ -85,14 +86,7 @@ const InboxNameInput = ({
await updateInboxName({
nodeAddress: auth.node_address,
- sender: auth.shinkai_identity,
- senderSubidentity: auth.profile,
- receiver: `${auth.shinkai_identity}`,
- my_device_encryption_sk: auth.my_device_encryption_sk,
- my_device_identity_sk: auth.my_device_identity_sk,
- node_encryption_pk: auth.node_encryption_pk,
- profile_encryption_sk: auth.profile_encryption_sk,
- profile_identity_sk: auth.profile_identity_sk,
+ token: auth.api_v2_key,
inboxId,
inboxName: data.name,
});
@@ -434,32 +428,52 @@ const ChatSidebar = () => {
(state) => state.setPromptSelected,
);
- const { inboxes, isPending, isSuccess } = useGetInboxes(
+ const { ref, inView } = useInView();
+
+ const {
+ data: inboxesPagination,
+ isPending,
+ isSuccess,
+ hasNextPage,
+ isFetchingNextPage,
+ fetchNextPage,
+ } = useGetInboxesWithPagination(
{ nodeAddress: auth?.node_address ?? '', token: auth?.api_v2_key ?? '' },
- {
- refetchIntervalInBackground: true,
- refetchInterval: (query) => {
- const queryState = query?.state?.data?.filter(
- (item) => !!item.last_message,
- );
- if (!queryState || !auth) return 0;
-
- const allInboxesAreCompleted = queryState.every((inbox) => {
- return (
- inbox.last_message &&
- inbox.last_message.sender &&
- !(
- inbox.last_message.sender === auth?.shinkai_identity &&
- inbox.last_message.sender_subidentity === auth?.profile
- )
- );
- });
-
- return allInboxesAreCompleted ? 0 : 5000;
- },
- },
+ // {
+ // refetchIntervalInBackground: true,
+ // refetchInterval: (query) => {
+ // const queryState = query?.state?.data?.filter(
+ // (item) => !!item.last_message,
+ // );
+ // if (!queryState || !auth) return 0;
+
+ // const allInboxesAreCompleted = queryState.every((inbox) => {
+ // return (
+ // inbox.last_message &&
+ // inbox.last_message.sender &&
+ // !(
+ // inbox.last_message.sender === auth?.shinkai_identity &&
+ // inbox.last_message.sender_subidentity === auth?.profile
+ // )
+ // );
+ // });
+
+ // return allInboxesAreCompleted ? 0 : 5000;
+ // },
+ // },
);
+ console.log(inboxesPagination, 'inboxes');
+
+ useEffect(() => {
+ if (inView && hasNextPage && !isFetchingNextPage) {
+ fetchNextPage();
+ }
+ }, [inView, fetchNextPage, hasNextPage, isFetchingNextPage]);
+
+ const hasInboxes =
+ (inboxesPagination?.pages?.at(-1)?.inboxes ?? []).length > 0;
+
return (
@@ -515,35 +529,46 @@ const ChatSidebar = () => {
))}
{isSuccess &&
- inboxes?.length > 0 &&
- inboxes.map((inbox) => (
-
- ))}
- {isSuccess && inboxes?.length === 0 && (
+ inboxesPagination?.pages.map((page) =>
+ page.inboxes.map((inbox) => (
+
+ )),
+ )}
+ {isSuccess && !hasInboxes && (
{t('chat.actives.notFound')}{' '}
)}
+ {hasNextPage && (
+
+ )}
diff --git a/apps/shinkai-desktop/src/pages/galxe-subscriptions.tsx b/apps/shinkai-desktop/src/pages/galxe-subscriptions.tsx
index ee3a5cf72..dfee7c2fb 100644
--- a/apps/shinkai-desktop/src/pages/galxe-subscriptions.tsx
+++ b/apps/shinkai-desktop/src/pages/galxe-subscriptions.tsx
@@ -3,7 +3,7 @@ import { CheckCircledIcon, CircleIcon } from '@radix-ui/react-icons';
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import { Inbox } from '@shinkai_network/shinkai-message-ts/api/jobs/types';
import { useGetListDirectoryContents } from '@shinkai_network/shinkai-node-state/v2/queries/getDirectoryContents/useGetListDirectoryContents';
-import { useGetInboxes } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxes';
+import { useGetInboxesWithPagination } from '@shinkai_network/shinkai-node-state/v2/queries/getInboxes/useGetInboxesWithPagination';
import { useGetMySubscriptions } from '@shinkai_network/shinkai-node-state/v2/queries/getMySubscriptions/useGetMySubscriptions';
import {
Button,
@@ -45,7 +45,7 @@ export const GalxeSusbcriptions = () => {
const evmAddress = useSettings((store) => store.evmAddress);
const setEvmAddress = useSettings((store) => store.setEvmAddress);
- const { inboxes } = useGetInboxes({
+ const { data: inboxesWithPagination } = useGetInboxesWithPagination({
nodeAddress: auth?.node_address ?? '',
token: auth?.api_v2_key ?? '',
});
@@ -80,7 +80,9 @@ export const GalxeSusbcriptions = () => {
const isUserSubscribedToKnowledge = (subscriptionFolder ?? [])?.length > 0;
- const inboxesWithSubscriptions: Inbox[] = inboxes.filter(
+ const inboxesWithSubscriptions: Inbox[] = (
+ inboxesWithPagination?.pages.flatMap((page) => page.inboxes) ?? []
+ ).filter(
(inbox) =>
(inbox?.job_scope?.vector_fs_folders ?? []).some((folder) =>
folder?.includes(SUBSCRIPTION_PATH),
diff --git a/apps/shinkai-desktop/src/pages/layout/main-layout.tsx b/apps/shinkai-desktop/src/pages/layout/main-layout.tsx
index b29910ac7..871d324e1 100644
--- a/apps/shinkai-desktop/src/pages/layout/main-layout.tsx
+++ b/apps/shinkai-desktop/src/pages/layout/main-layout.tsx
@@ -1,8 +1,6 @@
import { ExitIcon, GearIcon } from '@radix-ui/react-icons';
import { useTranslation } from '@shinkai_network/shinkai-i18n';
import { useImportTool } from '@shinkai_network/shinkai-node-state/v2/mutations/importTool/useImportTool';
-import { useSubmitRegistrationNoCode } from '@shinkai_network/shinkai-node-state/v2/mutations/submitRegistation/useSubmitRegistrationNoCode';
-import { useGetEncryptionKeys } from '@shinkai_network/shinkai-node-state/v2/queries/getEncryptionKeys/useGetEncryptionKeys';
import { useGetHealth } from '@shinkai_network/shinkai-node-state/v2/queries/getHealth/useGetHealth';
import {
AlertDialog,
@@ -35,17 +33,11 @@ import {
ShinkaiCombinationMarkIcon,
ToolsIcon,
} from '@shinkai_network/shinkai-ui/assets';
-import { submitRegistrationNoCodeError } from '@shinkai_network/shinkai-ui/helpers';
import { cn } from '@shinkai_network/shinkai-ui/utils';
import { listen } from '@tauri-apps/api/event';
import { getCurrentWindow } from '@tauri-apps/api/window';
-import { AnimatePresence, motion, TargetAndTransition } from 'framer-motion';
-import {
- ArrowLeftToLine,
- ArrowRightToLine,
- BotIcon,
- XIcon,
-} from 'lucide-react';
+import { AnimatePresence, motion } from 'framer-motion';
+import { ArrowLeftToLine, ArrowRightToLine, BotIcon } from 'lucide-react';
import React, { Fragment, useEffect, useState } from 'react';
import {
Link,
@@ -59,15 +51,10 @@ import { toast } from 'sonner';
import { ResourcesBanner } from '../../components/hardware-capabilities/resources-banner';
import { UpdateBanner } from '../../components/hardware-capabilities/update-banner';
import OnboardingStepper from '../../components/onboarding-checklist/onboarding';
+import { ResetConnectionDialog } from '../../components/reset-connection-dialog';
import config from '../../config';
-import {
- useShinkaiNodeKillMutation,
- useShinkaiNodeRemoveStorageMutation,
- useShinkaiNodeSpawnMutation,
-} from '../../lib/shinkai-node-manager/shinkai-node-manager-client';
import { useAuth } from '../../store/auth';
import { useSettings } from '../../store/settings';
-import { useShinkaiNodeManager } from '../../store/shinkai-node-manager';
type NavigationLink = {
title: string;
@@ -78,12 +65,6 @@ type NavigationLink = {
disabled?: boolean;
};
-export const sidebarTransition: TargetAndTransition['transition'] = {
- type: 'spring',
- stiffness: 260,
- damping: 24,
-};
-
export const showAnimation = {
hidden: {
width: 0,
@@ -100,6 +81,7 @@ export const showAnimation = {
},
},
};
+
const NavLink = ({
href,
external,
@@ -185,121 +167,6 @@ const NavLink = ({
);
};
-export const ResetConnectionDialog = ({
- isOpen,
- onOpenChange,
- allowClose = false,
-}: {
- isOpen: boolean;
- onOpenChange: (open: boolean) => void;
- allowClose?: boolean;
-}) => {
- const { mutateAsync: shinkaiNodeKill, isPending: isShinkaiNodeKillPending } =
- useShinkaiNodeKillMutation();
- const {
- mutateAsync: shinkaiNodeSpawn,
- isPending: isShinkaiNodeSpawnPending,
- } = useShinkaiNodeSpawnMutation({
- onSuccess: async () => {
- if (!encryptionKeys) return;
- await submitRegistrationNoCode({
- profile: 'main',
- registration_name: 'main_device',
- node_address: 'http://127.0.0.1:9550',
- ...encryptionKeys,
- });
- },
- });
- const {
- mutateAsync: shinkaiNodeRemoveStorage,
- isPending: isShinkaiNodeRemoveStoragePending,
- } = useShinkaiNodeRemoveStorageMutation();
- const { setShinkaiNodeOptions } = useShinkaiNodeManager();
- const { encryptionKeys } = useGetEncryptionKeys();
- const setAuth = useAuth((state) => state.setAuth);
- const navigate = useNavigate();
-
- const isResetLoading =
- isShinkaiNodeKillPending ||
- isShinkaiNodeRemoveStoragePending ||
- isShinkaiNodeSpawnPending;
-
- const { mutateAsync: submitRegistrationNoCode } = useSubmitRegistrationNoCode(
- {
- onSuccess: (response, setupPayload) => {
- if (response.status !== 'success') {
- shinkaiNodeKill();
- }
- if (response.status === 'success' && encryptionKeys) {
- const updatedSetupData = {
- ...encryptionKeys,
- ...setupPayload,
- permission_type: '',
- shinkai_identity: response.data?.node_name ?? '',
- node_signature_pk: response.data?.identity_public_key ?? '',
- node_encryption_pk: response.data?.encryption_public_key ?? '',
- api_v2_key: response.data?.api_v2_key ?? '',
- };
- setAuth(updatedSetupData);
- navigate('/ai-model-installation');
- onOpenChange(false);
- } else {
- submitRegistrationNoCodeError();
- }
- },
- },
- );
-
- const handleReset = async () => {
- await shinkaiNodeKill();
- useAuth.getState().setLogout(); // clean up local storage
- await shinkaiNodeRemoveStorage({ preserveKeys: true });
- setShinkaiNodeOptions(null);
- await shinkaiNodeSpawn();
- };
-
- return (
-
-
- {allowClose && (
-
-
-
- )}
-
- App Reset Required
-
-
-
- We're currently in beta and we made some significant
- updates to improve your experience. To apply these updates, we
- need to reset your data.
-
- If you need assistance, please contact our support team.
-
-
-
-
-
-
-
-
-
- );
-};
-
export function MainNav() {
const { t, Trans } = useTranslation();
const optInExperimental = useSettings((state) => state.optInExperimental);
diff --git a/apps/shinkai-visor/src/components/edit-inbox-name-dialog/edit-inbox-name-dialog.tsx b/apps/shinkai-visor/src/components/edit-inbox-name-dialog/edit-inbox-name-dialog.tsx
index b68c1a0a8..62045905f 100644
--- a/apps/shinkai-visor/src/components/edit-inbox-name-dialog/edit-inbox-name-dialog.tsx
+++ b/apps/shinkai-visor/src/components/edit-inbox-name-dialog/edit-inbox-name-dialog.tsx
@@ -4,7 +4,7 @@ import {
UpdateInboxNameFormSchema,
updateInboxNameFormSchema,
} from '@shinkai_network/shinkai-node-state/forms/chat/inbox';
-import { useUpdateInboxName } from '@shinkai_network/shinkai-node-state/lib/mutations/updateInboxName/useUpdateInboxName';
+import { useUpdateInboxName } from '@shinkai_network/shinkai-node-state/v2/mutations/updateInboxName/useUpdateInboxName';
import {
Button,
DialogFooter,
@@ -57,14 +57,7 @@ export const EditInboxNameDialog = ({
const submit = (values: UpdateInboxNameFormSchema) => {
updateInboxName({
nodeAddress: auth?.node_address ?? '',
- sender: auth?.shinkai_identity ?? '',
- senderSubidentity: auth?.profile ?? '',
- receiver: auth?.shinkai_identity ?? '',
- my_device_encryption_sk: auth?.my_device_encryption_sk ?? '',
- my_device_identity_sk: auth?.my_device_identity_sk ?? '',
- node_encryption_pk: auth?.node_encryption_pk ?? '',
- profile_encryption_sk: auth?.profile_encryption_sk ?? '',
- profile_identity_sk: auth?.profile_identity_sk ?? '',
+ token: auth?.api_v2_key ?? '',
inboxId: inboxId,
inboxName: values.name,
});
diff --git a/libs/shinkai-message-ts/src/api/jobs/index.ts b/libs/shinkai-message-ts/src/api/jobs/index.ts
index b2f5833c6..9c5646e8f 100644
--- a/libs/shinkai-message-ts/src/api/jobs/index.ts
+++ b/libs/shinkai-message-ts/src/api/jobs/index.ts
@@ -10,6 +10,8 @@ import {
CreateJobRequest,
CreateJobResponse,
GetAllInboxesResponse,
+ GetAllInboxesWithPaginationRequest,
+ GetAllInboxesWithPaginationResponse,
GetChatConfigRequest,
GetChatConfigResponse,
GetDownloadFileRequest,
@@ -34,6 +36,8 @@ import {
StopGeneratingLLMRequest,
UpdateChatConfigRequest,
UpdateChatConfigResponse,
+ UpdateInboxNameRequest,
+ UpdateInboxNameResponse,
UpdateJobScopeRequest,
UpdateLLMProviderRequest,
UpdateLLMProviderResponse,
@@ -347,6 +351,38 @@ export const getAllInboxes = async (
return response.data as GetAllInboxesResponse;
};
+export const getAllInboxesWithPagination = async (
+ nodeAddress: string,
+ bearerToken: string,
+ payload: GetAllInboxesWithPaginationRequest,
+) => {
+ const response = await httpClient.get(
+ urlJoin(nodeAddress, '/v2/all_inboxes_paginated'),
+ {
+ headers: { Authorization: `Bearer ${bearerToken}` },
+ responseType: 'json',
+ params: payload,
+ },
+ );
+ return response.data as GetAllInboxesWithPaginationResponse;
+};
+
+export const updateInboxName = async (
+ nodeAddress: string,
+ bearerToken: string,
+ payload: UpdateInboxNameRequest,
+) => {
+ const response = await httpClient.post(
+ urlJoin(nodeAddress, '/v2/update_smart_inbox_name'),
+ payload,
+ {
+ headers: { Authorization: `Bearer ${bearerToken}` },
+ responseType: 'json',
+ },
+ );
+ return response.data as UpdateInboxNameResponse;
+};
+
export const getJobConfig = async (
nodeAddress: string,
bearerToken: string,
diff --git a/libs/shinkai-message-ts/src/api/jobs/types.ts b/libs/shinkai-message-ts/src/api/jobs/types.ts
index fa0ef685c..14bfecdda 100644
--- a/libs/shinkai-message-ts/src/api/jobs/types.ts
+++ b/libs/shinkai-message-ts/src/api/jobs/types.ts
@@ -200,6 +200,25 @@ export type Inbox = {
};
export type GetAllInboxesResponse = Inbox[];
+export type GetAllInboxesWithPaginationRequest = {
+ limit?: number;
+ offset?: string;
+ show_hidden?: boolean;
+};
+export type GetAllInboxesWithPaginationResponse = {
+ inboxes: Inbox[];
+ hasNextPage: boolean;
+};
+
+export type UpdateInboxNameRequest = {
+ inbox_name: string;
+ custom_name: string;
+};
+export type UpdateInboxNameResponse = {
+ data: null;
+ status: string;
+};
+
export type GetFileNamesRequest = {
inboxName: string;
};
diff --git a/libs/shinkai-node-state/src/lib/mutations/updateInboxName/index.ts b/libs/shinkai-node-state/src/lib/mutations/updateInboxName/index.ts
deleted file mode 100644
index 83b76ea85..000000000
--- a/libs/shinkai-node-state/src/lib/mutations/updateInboxName/index.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { updateInboxName as updateInboxNameApi } from '@shinkai_network/shinkai-message-ts/api';
-
-import { UpdateInboxNameInput } from './types';
-export const updateInboxName = async ({
- nodeAddress,
- senderSubidentity,
- sender,
- receiver,
- my_device_encryption_sk,
- my_device_identity_sk,
- node_encryption_pk,
- profile_encryption_sk,
- profile_identity_sk,
- inboxName,
- inboxId,
-}: UpdateInboxNameInput) => {
- const response = await updateInboxNameApi(
- nodeAddress,
- sender,
- senderSubidentity,
- receiver,
- {
- my_device_encryption_sk,
- my_device_identity_sk,
- node_encryption_pk,
- profile_encryption_sk,
- profile_identity_sk,
- },
- inboxName,
- inboxId,
- );
-
- return response;
-};
diff --git a/libs/shinkai-node-state/src/lib/mutations/updateInboxName/types.ts b/libs/shinkai-node-state/src/lib/mutations/updateInboxName/types.ts
deleted file mode 100644
index bcf965732..000000000
--- a/libs/shinkai-node-state/src/lib/mutations/updateInboxName/types.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { CredentialsPayload } from '@shinkai_network/shinkai-message-ts/models';
-
-export type UpdateInboxNameInput = CredentialsPayload & {
- nodeAddress: string;
- senderSubidentity: string;
- sender: string;
- receiver: string;
- inboxName: string;
- inboxId: string;
-};
-
-export type UpdateInboxNameOutput = { success: string; data: null };
diff --git a/libs/shinkai-node-state/src/v2/constants.ts b/libs/shinkai-node-state/src/v2/constants.ts
index 59df7e01f..f4cc9caef 100644
--- a/libs/shinkai-node-state/src/v2/constants.ts
+++ b/libs/shinkai-node-state/src/v2/constants.ts
@@ -11,6 +11,7 @@ export enum FunctionKeyV2 {
GET_AGENTS = 'GET_AGENTS',
GET_LLM_PROVIDERS = 'GET_LLM_PROVIDERS',
GET_INBOXES = 'GET_INBOXES',
+ GET_INBOXES_WITH_PAGINATION = 'GET_INBOXES_WITH_PAGINATION',
GET_CHAT_CONVERSATION = 'GET_CHAT_CONVERSATION',
GET_CHAT_CONVERSATION_PAGINATION = 'GET_CHAT_CONVERSATION_PAGINATION',
GET_CHAT_CONVERSATION_BRANCHES = 'GET_CHAT_CONVERSATION_BRANCHES',
diff --git a/libs/shinkai-node-state/src/v2/mutations/updateInboxName/index.ts b/libs/shinkai-node-state/src/v2/mutations/updateInboxName/index.ts
new file mode 100644
index 000000000..414a8677e
--- /dev/null
+++ b/libs/shinkai-node-state/src/v2/mutations/updateInboxName/index.ts
@@ -0,0 +1,17 @@
+import { updateInboxName as updateInboxNameApi } from '@shinkai_network/shinkai-message-ts/api/jobs/index';
+
+import { UpdateInboxNameInput } from './types';
+
+export const updateInboxName = async ({
+ nodeAddress,
+ token,
+ inboxName,
+ inboxId,
+}: UpdateInboxNameInput) => {
+ const response = await updateInboxNameApi(nodeAddress, token, {
+ custom_name: inboxName,
+ inbox_name: inboxId,
+ });
+
+ return response;
+};
diff --git a/libs/shinkai-node-state/src/v2/mutations/updateInboxName/types.ts b/libs/shinkai-node-state/src/v2/mutations/updateInboxName/types.ts
new file mode 100644
index 000000000..c5b44380e
--- /dev/null
+++ b/libs/shinkai-node-state/src/v2/mutations/updateInboxName/types.ts
@@ -0,0 +1,10 @@
+import { Token } from '@shinkai_network/shinkai-message-ts/api/general/types';
+import { UpdateInboxNameResponse } from '@shinkai_network/shinkai-message-ts/api/jobs/types';
+
+export type UpdateInboxNameInput = Token & {
+ nodeAddress: string;
+ inboxName: string;
+ inboxId: string;
+};
+
+export type UpdateInboxNameOutput = UpdateInboxNameResponse;
diff --git a/libs/shinkai-node-state/src/lib/mutations/updateInboxName/useUpdateInboxName.ts b/libs/shinkai-node-state/src/v2/mutations/updateInboxName/useUpdateInboxName.ts
similarity index 80%
rename from libs/shinkai-node-state/src/lib/mutations/updateInboxName/useUpdateInboxName.ts
rename to libs/shinkai-node-state/src/v2/mutations/updateInboxName/useUpdateInboxName.ts
index d3caa01ae..de5e15d68 100644
--- a/libs/shinkai-node-state/src/lib/mutations/updateInboxName/useUpdateInboxName.ts
+++ b/libs/shinkai-node-state/src/v2/mutations/updateInboxName/useUpdateInboxName.ts
@@ -1,7 +1,7 @@
import { UseMutationOptions, useQueryClient } from '@tanstack/react-query';
import { useMutation } from '@tanstack/react-query';
-import { FunctionKey } from '../../constants';
+import { FunctionKeyV2 } from '../../constants';
import { updateInboxName } from '.';
import type { UpdateInboxNameInput, UpdateInboxNameOutput } from './types';
@@ -16,7 +16,9 @@ export const useUpdateInboxName = (options?: Options) => {
return useMutation({
mutationFn: updateInboxName,
onSuccess: (...onSuccessParameters) => {
- queryClient.invalidateQueries({ queryKey: [FunctionKey.GET_INBOXES] });
+ queryClient.invalidateQueries({
+ queryKey: [FunctionKeyV2.GET_INBOXES_WITH_PAGINATION],
+ });
if (options?.onSuccess) {
options.onSuccess(...onSuccessParameters);
}
diff --git a/libs/shinkai-node-state/src/v2/queries/getInboxes/index.ts b/libs/shinkai-node-state/src/v2/queries/getInboxes/index.ts
index 9f4b6389a..4cf226b84 100644
--- a/libs/shinkai-node-state/src/v2/queries/getInboxes/index.ts
+++ b/libs/shinkai-node-state/src/v2/queries/getInboxes/index.ts
@@ -1,4 +1,7 @@
-import { getAllInboxes as getAllInboxesApi } from '@shinkai_network/shinkai-message-ts/api/jobs/index';
+import {
+ getAllInboxes as getAllInboxesApi,
+ getAllInboxesWithPagination as getAllInboxesWithPaginationApi,
+} from '@shinkai_network/shinkai-message-ts/api/jobs/index';
import type { GetInboxesInput } from './types';
@@ -6,3 +9,18 @@ export const getInboxes = async ({ nodeAddress, token }: GetInboxesInput) => {
const inboxes = await getAllInboxesApi(nodeAddress, token);
return inboxes;
};
+
+export const getInboxesWithPagination = async ({
+ nodeAddress,
+ token,
+ limit,
+ offset,
+ show_hidden,
+}: GetInboxesInput) => {
+ const inboxes = await getAllInboxesWithPaginationApi(nodeAddress, token, {
+ limit,
+ offset,
+ show_hidden,
+ });
+ return inboxes;
+};
diff --git a/libs/shinkai-node-state/src/v2/queries/getInboxes/types.ts b/libs/shinkai-node-state/src/v2/queries/getInboxes/types.ts
index 85ea6f4cf..9111375ae 100644
--- a/libs/shinkai-node-state/src/v2/queries/getInboxes/types.ts
+++ b/libs/shinkai-node-state/src/v2/queries/getInboxes/types.ts
@@ -1,14 +1,21 @@
import { Token } from '@shinkai_network/shinkai-message-ts/api/general/types';
-import { GetAllInboxesResponse } from '@shinkai_network/shinkai-message-ts/api/jobs/types';
+import {
+ GetAllInboxesWithPaginationRequest,
+ GetAllInboxesWithPaginationResponse,
+} from '@shinkai_network/shinkai-message-ts/api/jobs/types';
import { QueryObserverOptions } from '@tanstack/react-query';
import { FunctionKeyV2 } from '../../constants';
export type GetInboxesInput = Token & {
nodeAddress: string;
-};
-export type GetInboxesOutput = GetAllInboxesResponse;
-export type UseGetInboxes = [FunctionKeyV2.GET_INBOXES, GetInboxesInput];
+} & GetAllInboxesWithPaginationRequest;
+export type GetInboxesOutput = GetAllInboxesWithPaginationResponse;
+
+export type UseGetInboxes = [
+ FunctionKeyV2.GET_INBOXES_WITH_PAGINATION,
+ GetInboxesInput,
+];
export type Options = QueryObserverOptions<
GetInboxesOutput,
diff --git a/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxes.ts b/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxes.ts
index 19df253b9..2b5964b7a 100644
--- a/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxes.ts
+++ b/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxes.ts
@@ -2,14 +2,11 @@ import { useQuery } from '@tanstack/react-query';
import { FunctionKeyV2 } from '../../constants';
import { getInboxes } from '.';
-import { GetInboxesInput, Options } from './types';
+import { GetInboxesInput } from './types';
-export const useGetInboxes = (
- input: GetInboxesInput,
- options?: Omit,
-) => {
+export const useGetInboxes = (input: GetInboxesInput) => {
const response = useQuery({
- queryKey: [FunctionKeyV2.GET_INBOXES, input],
+ queryKey: [FunctionKeyV2.GET_INBOXES_WITH_PAGINATION, input],
queryFn: async () => getInboxes(input),
select: (data) =>
// display only job inboxes
@@ -18,7 +15,6 @@ export const useGetInboxes = (
inbox?.inbox_id?.split('::')?.[0] === 'job_inbox' &&
inbox.is_finished === false,
),
- ...options,
});
return {
...response,
diff --git a/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxesWithPagination.ts b/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxesWithPagination.ts
new file mode 100644
index 000000000..2cd5104dd
--- /dev/null
+++ b/libs/shinkai-node-state/src/v2/queries/getInboxes/useGetInboxesWithPagination.ts
@@ -0,0 +1,44 @@
+import { GetAllInboxesWithPaginationRequest } from '@shinkai_network/shinkai-message-ts/api/jobs/types';
+import { InfiniteData, useInfiniteQuery } from '@tanstack/react-query';
+
+import { FunctionKeyV2 } from '../../constants';
+import { APIError } from '../../types';
+import { getInboxesWithPagination } from '.';
+import {
+ GetInboxesInput,
+ GetInboxesOutput,
+ Options,
+ UseGetInboxes,
+} from './types';
+
+const DEFAULT_LIMIT = 20;
+
+export const useGetInboxesWithPagination = (
+ input: GetInboxesInput,
+ options?: Omit,
+) => {
+ const response = useInfiniteQuery<
+ GetInboxesOutput,
+ APIError,
+ InfiniteData,
+ UseGetInboxes,
+ GetAllInboxesWithPaginationRequest
+ >({
+ queryKey: [FunctionKeyV2.GET_INBOXES_WITH_PAGINATION, input],
+ queryFn: ({ pageParam }) =>
+ getInboxesWithPagination({
+ ...input,
+ offset: pageParam?.offset ?? undefined, // offset is last inbox id
+ limit: pageParam?.limit ?? DEFAULT_LIMIT,
+ show_hidden: false,
+ }),
+ getNextPageParam: (lastPage, pages) => {
+ if (lastPage?.inboxes?.length < DEFAULT_LIMIT) return;
+ const lastInbox = pages.at(-1)?.inboxes?.at(-1);
+ if (!lastInbox) return null;
+ return { offset: lastInbox.inbox_id };
+ },
+ initialPageParam: { offset: undefined },
+ });
+ return response;
+};