Skip to content

Commit

Permalink
fix: Enhance CreateAgentDialog with Improved Error Handling and User …
Browse files Browse the repository at this point in the history
…Feedback (#932)
  • Loading branch information
arduenify authored Feb 9, 2024
1 parent 6e7fc50 commit 0a6ef1f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 25 deletions.
15 changes: 12 additions & 3 deletions chatui/src/app/libs/agents/use-agents.mutation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ import { Agent } from './agent';
export const useAgentsCreateMutation = (userId: string | null | undefined) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (params: { name: string; human: string; persona: string; model: string }) =>
(await fetch(API_BASE_URL + '/agents', {
mutationFn: async (params: { name: string; human: string; persona: string; model: string }) => {
const response = await fetch(API_BASE_URL + '/agents', {
method: 'POST',
headers: { 'Content-Type': ' application/json' },
body: JSON.stringify({ config: params, user_id: userId }),
}).then((res) => res.json())) as Promise<Agent>,
});

if (!response.ok) {
// Throw an error if the response is not OK
const errorBody = await response.text();
throw new Error(errorBody || 'Error creating agent');
}

return response.json() as Promise<Agent>;
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: [userId, 'agents', 'list'] }),
});
};
86 changes: 64 additions & 22 deletions chatui/src/app/modules/home/create-agent-dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import {
import { Input } from '@memgpt/components/input';
import { Label } from '@memgpt/components/label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@memgpt/components/select';
import { useToast } from '@memgpt/components/toast';
import { Loader2 } from 'lucide-react';
import { useEffect } from 'react';
import { Controller, useForm } from 'react-hook-form';
import { useAgentsCreateMutation } from '../../libs/agents/use-agents.mutation';
import { useAuthStoreState } from '../../libs/auth/auth.store';
Expand All @@ -25,54 +27,95 @@ interface FormData {
model: string;
}

const CreateAgentDialog = (props: { open: boolean; onOpenChange: (open: boolean) => void }) => {
const CreateAgentDialog = ({ open, onOpenChange }: { open: boolean; onOpenChange: (open: boolean) => void }) => {
const auth = useAuthStoreState();
const createAgent = useAgentsCreateMutation(auth.uuid);
const { toast } = useToast();

const { register, handleSubmit, control } = useForm<FormData>({
defaultValues: {
name: 'James Bond',
human: 'cs_phd',
persona: 'sam_pov',
model: 'gpt-4',
},
const {
register,
handleSubmit,
control,
formState: { errors, isSubmitting, isValid },
reset,
} = useForm<FormData>({
mode: 'onBlur',
});

useEffect(() => {
if (!open) {
reset(); // Resets form on dialog close
}
}, [open, reset]);

// Fetch models, humans, and personas using the custom hooks
const { data: modelsData } = useModelsQuery(auth.uuid);
const { data: humansData } = useHumansQuery(auth.uuid);
const { data: personasData } = usePersonasQuery(auth.uuid);

const onSubmit = (data: FormData) => {
if (!auth.uuid) return;
// The data parameter already contains the values from the form
createAgent.mutate(
{

createAgent
.mutateAsync({
name: data.name,
human: data.human,
persona: data.persona,
model: data.model,
},
{
onSuccess: () => props.onOpenChange(false),
}
);
})
.then(() => {
onOpenChange(false);
toast({ title: 'Agent created successfully!', duration: 5000 });
})
.catch((error) => {
let errorMessage = 'Error creating agent';
const unknownErrorMessage = `${errorMessage}: Unspecified error.`;

try {
const errorData = JSON.parse(error.message);
if (errorData.detail) {
// TODO: Modify this once the backend is changed: Backend should not return 'None' as the detail.
// This will eventually just be:
// errorMessage = `${errorMessage}: ${errorData.detail}`;
if (errorData.detail == 'None') {
errorMessage = unknownErrorMessage;
} else {
errorMessage = `${errorMessage}: ${errorData.detail}`;
}
}
} catch (parseError) {
errorMessage = unknownErrorMessage;
}

toast({
title: errorMessage,
duration: 5000,
});
});
};

return (
<Dialog open={props.open} onOpenChange={props.onOpenChange}>
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[425px]">
<form onSubmit={handleSubmit(onSubmit)}>
<DialogHeader>
<DialogTitle>Create Agent</DialogTitle>
<DialogDescription>Add a new agent here. Click create when you're done.</DialogDescription>
<DialogDescription>
Add a new agent here. Click create when you're done. Human, Persona, and Model can be left blank to use
default values.
</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="name" className="text-right">
Name
</Label>
<Input id="name" {...register('name')} className="col-span-3" />
<Input
id="name"
placeholder="Enter a name"
{...register('name', { required: true })}
className={`col-span-3 ${errors.name ? 'border-red-500' : ''} border`}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="human" className="text-right">
Expand Down Expand Up @@ -145,9 +188,8 @@ const CreateAgentDialog = (props: { open: boolean; onOpenChange: (open: boolean)
</div>
</div>
<DialogFooter>
<Button type="submit" disabled={createAgent.isPending}>
{createAgent.isPending ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : undefined}
{createAgent.isPending ? 'Creating Agent' : 'Create Agent'}
<Button type="submit" disabled={isSubmitting || !isValid}>
{isSubmitting ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : 'Create Agent'}
</Button>
</DialogFooter>
</form>
Expand Down

0 comments on commit 0a6ef1f

Please sign in to comment.