From f285f8601ed9a7f754f2d596d7fac23254cdea7a Mon Sep 17 00:00:00 2001 From: Robin Goetz <35136007+goetzrobin@users.noreply.github.com> Date: Sun, 21 Jan 2024 01:28:31 +0100 Subject: [PATCH] feat: Next iteration of ChatUI (#847) Co-authored-by: Charles Packer --- chatui/package-lock.json | 12 ++ chatui/package.json | 1 + chatui/src/app/auth.tsx | 15 ++ .../libs/agents/use-agent-memory.mutation.ts | 7 +- .../app/libs/agents/use-agent-memory.query.ts | 8 +- .../app/libs/agents/use-agents.mutation.ts | 11 +- .../src/app/libs/agents/use-agents.query.ts | 7 +- chatui/src/app/libs/auth/auth.store.ts | 32 +++++ chatui/src/app/libs/auth/use-auth.query.ts | 9 ++ .../app/libs/messages/message-stream.store.ts | 14 +- .../app/libs/messages/use-messages.query.ts | 19 +++ chatui/src/app/modules/chat/chat.tsx | 12 +- .../modules/chat/memory-view/memory-form.tsx | 30 +++- .../modules/chat/memory-view/memory-view.tsx | 4 +- .../chat/messages/message-container.tsx | 21 ++- .../chat/messages/select-agent-form.tsx | 4 +- .../app/modules/home/create-agent-dialog.tsx | 16 +-- chatui/src/app/modules/home/home.tsx | 54 ++++++-- .../app/modules/settings/agents/agents.tsx | 4 +- chatui/src/app/router.tsx | 24 ++-- memgpt/cli/cli.py | 41 ++++-- memgpt/server/rest_api/agents/message.py | 9 +- memgpt/server/rest_api/auth/__init__.py | 0 memgpt/server/rest_api/auth/index.py | 33 +++++ memgpt/server/rest_api/server.py | 3 + memgpt/server/server.py | 4 + .../static_files/assets/index-273ebfe0.js | 129 ++++++++++++++++++ .../static_files/assets/index-27e4af26.css | 1 - .../static_files/assets/index-9ace7bf7.css | 1 + .../static_files/assets/index-c3a527b1.js | 129 ------------------ memgpt/server/static_files/index.html | 6 +- 31 files changed, 437 insertions(+), 223 deletions(-) create mode 100644 chatui/src/app/auth.tsx create mode 100644 chatui/src/app/libs/auth/auth.store.ts create mode 100644 chatui/src/app/libs/auth/use-auth.query.ts create mode 100644 chatui/src/app/libs/messages/use-messages.query.ts create mode 100644 memgpt/server/rest_api/auth/__init__.py create mode 100644 memgpt/server/rest_api/auth/index.py create mode 100644 memgpt/server/static_files/assets/index-273ebfe0.js delete mode 100644 memgpt/server/static_files/assets/index-27e4af26.css create mode 100644 memgpt/server/static_files/assets/index-9ace7bf7.css delete mode 100644 memgpt/server/static_files/assets/index-c3a527b1.js diff --git a/chatui/package-lock.json b/chatui/package-lock.json index b7b4ff68..7054bd03 100644 --- a/chatui/package-lock.json +++ b/chatui/package-lock.json @@ -54,6 +54,7 @@ "tailwind-merge": "^2.0.0", "tailwindcss-animate": "^1.0.7", "tslib": "^2.3.0", + "use-debounce": "^10.0.0", "zod": "^3.22.4", "zustand": "^4.4.6" }, @@ -16296,6 +16297,17 @@ } } }, + "node_modules/use-debounce": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/use-debounce/-/use-debounce-10.0.0.tgz", + "integrity": "sha512-XRjvlvCB46bah9IBXVnq/ACP2lxqXyZj0D9hj4K5OzNroMDpTEBg8Anuh1/UfRTRs7pLhQ+RiNxxwZu9+MVl1A==", + "engines": { + "node": ">= 16.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, "node_modules/use-sidecar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", diff --git a/chatui/package.json b/chatui/package.json index 0fd3d0ed..000a0a57 100644 --- a/chatui/package.json +++ b/chatui/package.json @@ -55,6 +55,7 @@ "tailwind-merge": "^2.0.0", "tailwindcss-animate": "^1.0.7", "tslib": "^2.3.0", + "use-debounce": "^10.0.0", "zod": "^3.22.4", "zustand": "^4.4.6" }, diff --git a/chatui/src/app/auth.tsx b/chatui/src/app/auth.tsx new file mode 100644 index 00000000..993d75ec --- /dev/null +++ b/chatui/src/app/auth.tsx @@ -0,0 +1,15 @@ +import { PropsWithChildren } from 'react'; +import { useAuthStoreActions, useAuthStoreState } from './libs/auth/auth.store'; +import { useAuthQuery } from './libs/auth/use-auth.query'; + +const Auth = (props: PropsWithChildren) => { + const result = useAuthQuery(); + const { uuid } = useAuthStoreState(); + const { setAsAuthenticated } = useAuthStoreActions(); + if (result.isSuccess && uuid !== result.data.uuid) { + setAsAuthenticated(result.data.uuid); + } + return props.children; +}; + +export default Auth; diff --git a/chatui/src/app/libs/agents/use-agent-memory.mutation.ts b/chatui/src/app/libs/agents/use-agent-memory.mutation.ts index 6bca05c6..40b11ef5 100644 --- a/chatui/src/app/libs/agents/use-agent-memory.mutation.ts +++ b/chatui/src/app/libs/agents/use-agent-memory.mutation.ts @@ -2,15 +2,16 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { API_BASE_URL } from '../constants'; import { AgentMemoryUpdate } from './agent-memory-update'; -export const useAgentMemoryUpdateMutation = () => { +export const useAgentMemoryUpdateMutation = (userId: string | null | undefined) => { const queryClient = useQueryClient(); return useMutation({ mutationFn: async (params: AgentMemoryUpdate) => - await fetch(API_BASE_URL + `/agents/memory`, { + await fetch(API_BASE_URL + `/agents/memory?${userId}`, { method: 'POST', headers: { 'Content-Type': ' application/json' }, body: JSON.stringify(params), }).then((res) => res.json()), - onSuccess: (res, { agent_id }) => queryClient.invalidateQueries({ queryKey: ['agents', agent_id, 'memory'] }), + onSuccess: (res, { agent_id }) => + queryClient.invalidateQueries({ queryKey: [userId, 'agents', 'entry', agent_id, 'memory'] }), }); }; diff --git a/chatui/src/app/libs/agents/use-agent-memory.query.ts b/chatui/src/app/libs/agents/use-agent-memory.query.ts index ed4dba84..a6258f12 100644 --- a/chatui/src/app/libs/agents/use-agent-memory.query.ts +++ b/chatui/src/app/libs/agents/use-agent-memory.query.ts @@ -2,12 +2,12 @@ import { useQuery } from '@tanstack/react-query'; import { API_BASE_URL } from '../constants'; import { AgentMemory } from './agent-memory'; -export const useAgentMemoryQuery = (agent_id: string | null | undefined) => +export const useAgentMemoryQuery = (userId: string | null | undefined, agentId: string | null | undefined) => useQuery({ - queryKey: ['agents', agent_id, 'memory'], + queryKey: [userId, 'agents', 'entry', agentId, 'memory'], queryFn: async () => - (await fetch(API_BASE_URL + `/agents/memory?agent_id=${agent_id}&user_id=null`).then((res) => + (await fetch(API_BASE_URL + `/agents/memory?agent_id=${agentId}&user_id=${userId}`).then((res) => res.json() )) as Promise, - enabled: !!agent_id, + enabled: !!userId && !!agentId, }); diff --git a/chatui/src/app/libs/agents/use-agents.mutation.ts b/chatui/src/app/libs/agents/use-agents.mutation.ts index 018cdc3a..48d00d43 100644 --- a/chatui/src/app/libs/agents/use-agents.mutation.ts +++ b/chatui/src/app/libs/agents/use-agents.mutation.ts @@ -2,18 +2,15 @@ import { useMutation, useQueryClient } from '@tanstack/react-query'; import { API_BASE_URL } from '../constants'; import { Agent } from './agent'; -export const useAgentsCreateMutation = () => { +export const useAgentsCreateMutation = (userId: string | null | undefined) => { const queryClient = useQueryClient(); return useMutation({ - mutationFn: async (params: { - user_id: string; - config: { name: string; human: string; persona: string; model: string }; - }) => + mutationFn: async (params: { name: string; human: string; persona: string; model: string }) => (await fetch(API_BASE_URL + '/agents', { method: 'POST', headers: { 'Content-Type': ' application/json' }, - body: JSON.stringify(params), + body: JSON.stringify({ config: params, user_id: userId }), }).then((res) => res.json())) as Promise, - onSuccess: () => queryClient.invalidateQueries({ queryKey: ['agents'] }), + onSuccess: () => queryClient.invalidateQueries({ queryKey: [userId, 'agents', 'list'] }), }); }; diff --git a/chatui/src/app/libs/agents/use-agents.query.ts b/chatui/src/app/libs/agents/use-agents.query.ts index 88b78fba..26a90680 100644 --- a/chatui/src/app/libs/agents/use-agents.query.ts +++ b/chatui/src/app/libs/agents/use-agents.query.ts @@ -2,11 +2,12 @@ import { useQuery } from '@tanstack/react-query'; import { API_BASE_URL } from '../constants'; import { Agent } from './agent'; -export const useAgentsQuery = () => +export const useAgentsQuery = (userId: string | null | undefined) => useQuery({ - queryKey: ['agents'], + queryKey: [userId, 'agents', 'list'], + enabled: !!userId, queryFn: async () => - (await fetch(API_BASE_URL + '/agents?user_id=null').then((res) => res.json())) as Promise<{ + (await fetch(API_BASE_URL + `/agents?user_id=${userId}`).then((res) => res.json())) as Promise<{ num_agents: number; agents: Agent[]; }>, diff --git a/chatui/src/app/libs/auth/auth.store.ts b/chatui/src/app/libs/auth/auth.store.ts new file mode 100644 index 00000000..676e4eb1 --- /dev/null +++ b/chatui/src/app/libs/auth/auth.store.ts @@ -0,0 +1,32 @@ +import { create } from 'zustand'; +import { createJSONStorage, persist } from 'zustand/middleware'; + +export type AuthState = { + uuid: string | null; +}; +export type AuthActions = { setAsAuthenticated: (uuid: string) => void }; + +const useAuthStore = create( + persist<{ auth: AuthState; actions: AuthActions }>( + (set, get) => ({ + auth: { uuid: null }, + actions: { + setAsAuthenticated: (uuid: string) => + set((prev) => ({ + ...prev, + auth: { + uuid, + }, + })), + }, + }), + { + name: 'auth-storage', + storage: createJSONStorage(() => localStorage), + partialize: ({ actions, ...rest }: any) => rest, + } + ) +); + +export const useAuthStoreState = () => useAuthStore().auth; +export const useAuthStoreActions = () => useAuthStore().actions; diff --git a/chatui/src/app/libs/auth/use-auth.query.ts b/chatui/src/app/libs/auth/use-auth.query.ts new file mode 100644 index 00000000..72ba03dc --- /dev/null +++ b/chatui/src/app/libs/auth/use-auth.query.ts @@ -0,0 +1,9 @@ +import { useQuery } from '@tanstack/react-query'; +import { API_BASE_URL } from '../constants'; + +export type AuthResponse = { uuid: string }; +export const useAuthQuery = () => + useQuery({ + queryKey: ['auth'], + queryFn: async () => (await fetch(API_BASE_URL + `/auth`).then((res) => res.json())) as Promise, + }); diff --git a/chatui/src/app/libs/messages/message-stream.store.ts b/chatui/src/app/libs/messages/message-stream.store.ts index 1e021f17..eb516699 100644 --- a/chatui/src/app/libs/messages/message-stream.store.ts +++ b/chatui/src/app/libs/messages/message-stream.store.ts @@ -25,7 +25,17 @@ const useMessageStreamStore = create( }, (set, get) => ({ actions: { - sendMessage: ({ agentId, message, role }: { agentId: string; message: string; role?: 'user' | 'system' }) => { + sendMessage: ({ + userId, + agentId, + message, + role, + }: { + userId: string; + agentId: string; + message: string; + role?: 'user' | 'system'; + }) => { const abortController = new AbortController(); set((state) => ({ ...state, abortController, readyState: ReadyState.LOADING })); const onMessageCallback = get().onMessageCallback; @@ -41,7 +51,7 @@ const useMessageStreamStore = create( method: 'POST', headers: { 'Content-Type': 'application/json', Accept: 'text/event-stream' }, body: JSON.stringify({ - user_id: 'null', + user_id: userId, agent_id: agentId, message, role: role ?? 'user', diff --git a/chatui/src/app/libs/messages/use-messages.query.ts b/chatui/src/app/libs/messages/use-messages.query.ts new file mode 100644 index 00000000..9fcb1c0e --- /dev/null +++ b/chatui/src/app/libs/messages/use-messages.query.ts @@ -0,0 +1,19 @@ +import { useQuery } from '@tanstack/react-query'; +import { API_BASE_URL } from '../constants'; + +export const useMessagesQuery = ( + userId: string | null | undefined, + agentId: string | null | undefined, + start = 0, + count = 10 +) => + useQuery({ + queryKey: [userId, 'agents', 'item', agentId, 'messages', 'list', start, count], + queryFn: async () => + (await fetch( + API_BASE_URL + `/agents/message?agent_id=${agentId}&user_id=${userId}&start=${start}&count=${count}` + ).then((res) => res.json())) as Promise<{ + messages: { role: string; name: string; content: string }[]; + }>, + enabled: !!userId && !!agentId, + }); diff --git a/chatui/src/app/modules/chat/chat.tsx b/chatui/src/app/modules/chat/chat.tsx index 8ce0da0b..c8b7d53f 100644 --- a/chatui/src/app/modules/chat/chat.tsx +++ b/chatui/src/app/modules/chat/chat.tsx @@ -1,5 +1,6 @@ import { useCallback, useEffect, useRef } from 'react'; import { useAgentActions, useCurrentAgent, useLastAgentInitMessage } from '../../libs/agents/agent.store'; +import { useAuthStoreState } from '../../libs/auth/auth.store'; import { useMessageHistoryActions, useMessagesForKey } from '../../libs/messages/message-history.store'; import { ReadyState, @@ -11,7 +12,7 @@ import UserInput from './user-input'; const Chat = () => { const initialized = useRef(false); - + const auth = useAuthStoreState(); const currentAgent = useCurrentAgent(); const lastAgentInitMessage = useLastAgentInitMessage(); const messages = useMessagesForKey(currentAgent?.id ?? ''); @@ -21,12 +22,11 @@ const Chat = () => { const { addMessage } = useMessageHistoryActions(); const { setLastAgentInitMessage } = useAgentActions(); - // eslint-disable-next-line react-hooks/exhaustive-deps const sendMessageAndAddToHistory = useCallback( (message: string, role: 'user' | 'system' = 'user') => { - if (!currentAgent) return; + if (!currentAgent || !auth.uuid) return; const date = new Date(); - sendMessage({ agentId: currentAgent.id, message, role }); + sendMessage({ userId: auth.uuid, agentId: currentAgent.id, message, role }); addMessage(currentAgent.id, { type: role === 'user' ? 'user_message' : 'system_message', message_type: 'user_message', @@ -34,7 +34,7 @@ const Chat = () => { date, }); }, - [currentAgent, sendMessage, addMessage] + [currentAgent, auth.uuid, sendMessage, addMessage] ); useEffect(() => { @@ -64,7 +64,7 @@ const Chat = () => { return (
- +
); diff --git a/chatui/src/app/modules/chat/memory-view/memory-form.tsx b/chatui/src/app/modules/chat/memory-view/memory-form.tsx index 1dc6ae26..2920ebd1 100644 --- a/chatui/src/app/modules/chat/memory-view/memory-form.tsx +++ b/chatui/src/app/modules/chat/memory-view/memory-form.tsx @@ -10,23 +10,26 @@ import { FormMessage, } from '@memgpt/components/form'; import { Textarea } from '@memgpt/components/textarea'; +import { cnMuted } from '@memgpt/components/typography'; import { cn } from '@memgpt/utils'; -import { Loader2 } from 'lucide-react'; +import { Loader2, LucideCheckCheck } from 'lucide-react'; import { useForm } from 'react-hook-form'; import * as z from 'zod'; import { AgentMemory } from '../../../libs/agents/agent-memory'; import { AgentMemoryUpdateSchema } from '../../../libs/agents/agent-memory-update'; import { useAgentMemoryUpdateMutation } from '../../../libs/agents/use-agent-memory.mutation'; +import { useAuthStoreState } from '../../../libs/auth/auth.store'; export function MemoryForm({ className, data, agentId }: { className?: string; data: AgentMemory; agentId: string }) { - const mutation = useAgentMemoryUpdateMutation(); + const auth = useAuthStoreState(); + const mutation = useAgentMemoryUpdateMutation(auth.uuid); const form = useForm>({ resolver: zodResolver(AgentMemoryUpdateSchema), defaultValues: { persona: data?.core_memory?.persona, human: data?.core_memory?.human, - user_id: 'null', + user_id: auth.uuid ?? undefined, agent_id: agentId, }, }); @@ -68,10 +71,23 @@ export function MemoryForm({ className, data, agentId }: { className?: string; d )} /> - +
+ {mutation.isPending && ( + + + Saving Memory... + + )} + {mutation.isSuccess && ( + + + New Memory Saved + + )} + +
); diff --git a/chatui/src/app/modules/chat/memory-view/memory-view.tsx b/chatui/src/app/modules/chat/memory-view/memory-view.tsx index 06c256d3..9010ab93 100644 --- a/chatui/src/app/modules/chat/memory-view/memory-view.tsx +++ b/chatui/src/app/modules/chat/memory-view/memory-view.tsx @@ -1,11 +1,13 @@ import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from '@memgpt/components/dialog'; import { useCurrentAgent } from '../../../libs/agents/agent.store'; import { useAgentMemoryQuery } from '../../../libs/agents/use-agent-memory.query'; +import { useAuthStoreState } from '../../../libs/auth/auth.store'; import { MemoryForm } from './memory-form'; const MemoryView = ({ open, onOpenChange }: { open: boolean; onOpenChange: (open: boolean) => void }) => { + const auth = useAuthStoreState(); const currentAgent = useCurrentAgent(); - const { data, isLoading } = useAgentMemoryQuery(currentAgent?.id); + const { data, isLoading } = useAgentMemoryQuery(auth.uuid, currentAgent?.id); return ( diff --git a/chatui/src/app/modules/chat/messages/message-container.tsx b/chatui/src/app/modules/chat/messages/message-container.tsx index e358d5e1..d90478c3 100644 --- a/chatui/src/app/modules/chat/messages/message-container.tsx +++ b/chatui/src/app/modules/chat/messages/message-container.tsx @@ -1,4 +1,6 @@ +import { Badge } from '@memgpt/components/badge'; import { useEffect, useRef } from 'react'; +import { Agent } from '../../../libs/agents/agent'; import { Message } from '../../../libs/messages/message'; import { ReadyState } from '../../../libs/messages/message-stream.store'; import MessageContainerLayout from './message-container-layout'; @@ -7,18 +9,20 @@ import SelectAgentForm from './select-agent-form'; import ThinkingIndicator from './thinking-indicator'; const MessageContainer = ({ - agentSet, + currentAgent, messages, readyState, + previousMessages, }: { - agentSet: boolean; + currentAgent: Agent | null; messages: Message[]; readyState: ReadyState; + previousMessages: { role: string; content: string; name: string; function_call: { arguments: string } }[]; }) => { const messageBox = useRef(null); useEffect(() => messageBox.current?.scrollIntoView(false), [messages]); - if (!agentSet) { + if (!currentAgent) { return ( @@ -28,7 +32,18 @@ const MessageContainer = ({ return ( + + {currentAgent.name} +
+ {previousMessages.map((m) => ( +

+ {m.name} | {m.role} | {m.content} | {m.function_call?.arguments} +

+ ))} {messages.map((message, i) => pickMessageElement(message, i))} {readyState === ReadyState.LOADING ? : undefined}
diff --git a/chatui/src/app/modules/chat/messages/select-agent-form.tsx b/chatui/src/app/modules/chat/messages/select-agent-form.tsx index f3bf02f3..34a3cb7c 100644 --- a/chatui/src/app/modules/chat/messages/select-agent-form.tsx +++ b/chatui/src/app/modules/chat/messages/select-agent-form.tsx @@ -6,9 +6,11 @@ import { useState } from 'react'; import { Agent } from '../../../libs/agents/agent'; import { useAgentActions } from '../../../libs/agents/agent.store'; import { useAgentsQuery } from '../../../libs/agents/use-agents.query'; +import { useAuthStoreState } from '../../../libs/auth/auth.store'; const SelectAgentForm = () => { - const { data } = useAgentsQuery(); + const { uuid } = useAuthStoreState(); + const { data } = useAgentsQuery(uuid); const [newAgent, setNewAgent] = useState(null); const { setAgent } = useAgentActions(); return ( diff --git a/chatui/src/app/modules/home/create-agent-dialog.tsx b/chatui/src/app/modules/home/create-agent-dialog.tsx index 7a1e4fa4..9a421f86 100644 --- a/chatui/src/app/modules/home/create-agent-dialog.tsx +++ b/chatui/src/app/modules/home/create-agent-dialog.tsx @@ -11,26 +11,26 @@ import { Input } from '@memgpt/components/input'; import { Label } from '@memgpt/components/label'; import { Loader2 } from 'lucide-react'; import { useAgentsCreateMutation } from '../../libs/agents/use-agents.mutation'; +import { useAuthStoreState } from '../../libs/auth/auth.store'; const CreateAgentDialog = (props: { open: boolean; onOpenChange: (open: boolean) => void }) => { - const createAgent = useAgentsCreateMutation(); + const auth = useAuthStoreState(); + const createAgent = useAgentsCreateMutation(auth.uuid); return (
{ event.preventDefault(); + if (!auth.uuid) return; const formData = new FormData(event.currentTarget); // ✅ mutation is invoked when the form is submitted createAgent.mutate( { - user_id: 'placeholder', - config: { - name: `${formData.get('name')}`, - human: `${formData.get('human')}`, - persona: `${formData.get('persona')}`, - model: `${formData.get('model')}`, - }, + name: `${formData.get('name')}`, + human: `${formData.get('human')}`, + persona: `${formData.get('persona')}`, + model: `${formData.get('model')}`, }, { onSuccess: () => props.onOpenChange(false), diff --git a/chatui/src/app/modules/home/home.tsx b/chatui/src/app/modules/home/home.tsx index 5c84d634..dff0c8f1 100644 --- a/chatui/src/app/modules/home/home.tsx +++ b/chatui/src/app/modules/home/home.tsx @@ -1,22 +1,28 @@ import { Button } from '@memgpt/components/button'; +import { Input } from '@memgpt/components/input'; import { Skeleton } from '@memgpt/components/skeleton'; -import { cnH1, cnLead } from '@memgpt/components/typography'; -import { LucidePlus } from 'lucide-react'; -import { useState } from 'react'; +import { cnH1, cnH3, cnLead, cnMuted } from '@memgpt/components/typography'; +import { LucidePlus, LucideSearch } from 'lucide-react'; +import { useRef, useState } from 'react'; +import { useDebounce } from 'use-debounce'; import { useAgentActions, useCurrentAgent } from '../../libs/agents/agent.store'; import { useAgentsQuery } from '../../libs/agents/use-agents.query'; +import { useAuthStoreState } from '../../libs/auth/auth.store'; import AgentCard from './agent-card'; import CreateAgentDialog from './create-agent-dialog'; const Home = () => { - const { data, isLoading } = useAgentsQuery(); + const { uuid } = useAuthStoreState(); + const { data, isSuccess, isLoading } = useAgentsQuery(uuid); const { setAgent } = useAgentActions(); const currentAgent = useCurrentAgent(); const [showingAgentCreation, setShowingAgentCreation] = useState(false); - + const [searchInput, setSearchInput] = useState(''); + const [debouncedInput] = useDebounce(searchInput, 300); + const filteredAgents = (data?.agents ?? []).filter((a) => a.name.includes(debouncedInput)); const agentsOrSkeletons = isLoading ? [1, 2, 3, 4, 5, 6, 7, 8].map((_, i) => ) - : (data?.agents ?? []).map((a) => ( + : filteredAgents.map((a) => ( { /> )); + const inputRef = useRef(null); return ( <>
@@ -36,16 +43,35 @@ const Home = () => {

Welcome to MemGPT

Select or create an agent to start your conversation...

-
- +
+
{agentsOrSkeletons} + {isSuccess && data?.num_agents === 0 ? ( +
+

No Agents exist

+

+ Create your first agent and start chatting by clicking the Add New button. +

+
+ ) : undefined}
setShowingAgentCreation(open)} /> diff --git a/chatui/src/app/modules/settings/agents/agents.tsx b/chatui/src/app/modules/settings/agents/agents.tsx index 56b2ec04..13975ea5 100644 --- a/chatui/src/app/modules/settings/agents/agents.tsx +++ b/chatui/src/app/modules/settings/agents/agents.tsx @@ -15,6 +15,7 @@ import { useForm } from 'react-hook-form'; import * as z from 'zod'; import { useAgentActions, useCurrentAgent } from '../../../libs/agents/agent.store'; import { useAgentsQuery } from '../../../libs/agents/use-agents.query'; +import { useAuthStoreState } from '../../../libs/auth/auth.store'; import { SettingsLayout } from '../layout'; const agentsFormSchema = z.object({ @@ -33,7 +34,8 @@ const getDefaultValues: (initialName: string | null | undefined) => Partial ( - <> -
-
- -
-