File size: 3,547 Bytes
0b9dc2e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import { CircleAlert, Loader2, PlusCircle } from 'lucide-react';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';

import type { ContextConfig, ReActConfig } from '@/api';
import {
	AgentFormFields,
	defaultAgentFormValues,
	type AgentFormValues,
	type AgentSection,
} from '@/components/form/AgentFormFields';
import type { SchemaFormValue } from '@/components/form/SchemaForm';
import { Button } from '@/components/ui/button';
import {
	Dialog,
	DialogContent,
	DialogFooter,
	DialogHeader,
	DialogTitle,
	DialogDescription,
	DialogTrigger,
} from '@/components/ui/dialog';
import { useAgents } from '@/hooks/useAgents';
import { useAgentSchema } from '@/hooks/useAgentSchema';

interface Props {
	onCreated?: () => void;
	triggerId?: string;
}

export function AgentDialog({ onCreated, triggerId }: Props) {
	const { create } = useAgents();
	const { t } = useTranslation();
	const { schema } = useAgentSchema();
	const [open, setOpen] = useState(false);
	const [submitting, setSubmitting] = useState(false);
	const [values, setValues] = useState<AgentFormValues | null>(null);

	useEffect(() => {
		if (open && schema && !values) {
			setValues(defaultAgentFormValues(schema));
		}
		if (!open) setValues(null);
	}, [open, schema, values]);

	const handleChange = (section: AgentSection, key: string, value: SchemaFormValue) => {
		setValues((prev) =>
			prev ? { ...prev, [section]: { ...prev[section], [key]: value } } : prev,
		);
	};

	const handleSubmit = async () => {
		if (!values) return;
		const name = (values.identity.name as string | undefined)?.trim();
		if (!name) return;
		setSubmitting(true);
		try {
			await create({
				name,
				system_prompt: values.identity.system_prompt as string | undefined,
				context_config: values.context_config as unknown as ContextConfig,
				react_config: values.react_config as unknown as ReActConfig,
			});
			setOpen(false);
			onCreated?.();
		} finally {
			setSubmitting(false);
		}
	};

	const nameValid = !!(values?.identity.name as string | undefined)?.trim();

	return (
		<Dialog open={open} onOpenChange={setOpen}>

			<DialogTrigger asChild>

				<Button id={triggerId}>

					<PlusCircle />

					<span>{t('dialog-agent-create.trigger')}</span>

				</Button>

			</DialogTrigger>

			<DialogContent className="!w-[500px] !max-w-[500px]">

				<DialogHeader>

					<DialogTitle>{t('dialog-agent-create.title')}</DialogTitle>

					<DialogDescription className="sr-only">

						{t('dialog-agent-create.description')}

					</DialogDescription>

				</DialogHeader>

				<div className="no-scrollbar -mx-4 max-h-[75vh] overflow-y-auto px-4">

					{schema && values ? (

						<AgentFormFields schema={schema} values={values} onChange={handleChange} />

					) : (

						<p className="text-muted-foreground text-sm">{t('common.loading')}</p>

					)}

				</div>

				<DialogFooter>

					<Button variant="ghost" onClick={() => setOpen(false)} disabled={submitting}>

						<CircleAlert className="size-3.5" />

						{t('common.cancel')}

					</Button>

					<Button

						onClick={handleSubmit}

						disabled={!nameValid || submitting || !schema || !values}

					>

						{submitting ? (

							<Loader2 className="size-3.5 animate-spin" />

						) : (

							<PlusCircle className="size-3.5" />

						)}

						{submitting ? t('common.creating') : t('common.create')}

					</Button>

				</DialogFooter>

			</DialogContent>

		</Dialog>
	);
}