Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add Agent creation frontend #1836

Merged
merged 8 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/lib/api/brain/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export type CreateBrainInput = {
brain_type?: BrainType;
brain_definition?: Omit<ApiBrainDefinition, "brain_id">;
brain_secrets_values?: Record<string, string>;
connected_brains_ids?: UUID[];
};

export type UpdateBrainInput = Partial<CreateBrainInput>;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { ApiRequestDefinition } from "@/lib/components/ApiRequestDefinition";
import Button from "@/lib/components/ui/Button";
import { BrainType } from "@/lib/types/brainConfig";

import { CompositeBrainConnections } from "./components/CompositeBrainConnections/CompositeBrainConnections";
import { KnowledgeToFeedInput } from "./components/KnowledgeToFeedInput";
import { useBrainCreationHandler } from "./hooks/useBrainCreationHandler";
import { useBrainKnowledgeStep } from "./hooks/useBrainKnowledgeStep";
Expand All @@ -30,7 +31,7 @@ export const BrainKnowledgeStep = ({
const brainTypeToKnowledgeComponent: Record<BrainType, JSX.Element> = {
doc: <KnowledgeToFeedInput />,
api: <ApiRequestDefinition />,
chatflow: <div>Coming soon</div>,
composite: <CompositeBrainConnections />,
};

if (currentStep !== "KNOWLEDGE" || brainType === undefined) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Checkbox } from "@/lib/components/ui/Checkbox";
import { MinimalBrainForUser } from "@/lib/context/BrainProvider/types";

import { useConnectableBrain } from "./hooks/useConnectableBrain";

type ConnectableBrainProps = {
brain: MinimalBrainForUser;
};

export const ConnectableBrain = ({
brain,
}: ConnectableBrainProps): JSX.Element => {
const { onCheckedChange } = useConnectableBrain();

return (
<div className="flex flex-row items-center gap-2">
<Checkbox
className="text-white"
onCheckedChange={(checked) =>
onCheckedChange({
brainId: brain.id,
checked,
})
}
id={`connected_brains_ids-${brain.id}`}
/>
<label
htmlFor={`connected_brains_ids-${brain.id}`}
className="text-md font-medium leading-none cursor-pointer"
>
{brain.name}
</label>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { CheckedState } from "@radix-ui/react-checkbox";
import { UUID } from "crypto";
import { useFormContext } from "react-hook-form";

import { CreateBrainProps } from "@/lib/components/AddBrainModal/types";

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const useConnectableBrain = () => {
const { setValue, getValues } = useFormContext<CreateBrainProps>();

const onCheckedChange = ({
checked,
brainId,
}: {
checked: CheckedState;
brainId: UUID;
}) => {
if (checked === "indeterminate") {
return;
}
const connected_brains_ids = getValues("connected_brains_ids") ?? [];
if (checked) {
setValue("connected_brains_ids", [...connected_brains_ids, brainId]);
} else {
setValue(
"connected_brains_ids",
connected_brains_ids.filter((id) => id !== brainId)
);
}
};

return {
onCheckedChange,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useTranslation } from "react-i18next";

import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";

import { ConnectableBrain } from "./Components/ConnectableBrain/ConnectableBrain";

export const CompositeBrainConnections = (): JSX.Element => {
const { allBrains } = useBrainContext();
const sortedBrains = allBrains.sort((a, b) => a.name.localeCompare(b.name));
const { t } = useTranslation("brain");

return (
<div className="px-10">
<p className="text-center mb-8 italic text-sm w-full">
{t("composite_brain_composition_invitation")}
</p>
<div className="w-full flex flex-col gap-2">
{sortedBrains.map((brain) => (
<ConnectableBrain key={brain.id} brain={brain} />
))}
</div>
</div>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const useBrainCreationApi = ({
brain_secrets_values,
status,
brain_type,
connected_brains_ids,
} = getValues();

const createdBrainId = await createBrainApi({
Expand All @@ -59,6 +60,8 @@ export const useBrainCreationApi = ({
brain_definition: brain_type === "api" ? brain_definition : undefined,
brain_secrets_values:
brain_type === "api" ? brain_secrets_values : undefined,
connected_brains_ids:
brain_type === "composite" ? connected_brains_ids : undefined,
});

if (createdBrainId === undefined) {
Expand Down Expand Up @@ -92,6 +95,12 @@ export const useBrainCreationApi = ({
text: t("brainCreated", { ns: "brain" }),
});
},
onError: () => {
publish({
variant: "danger",
text: t("errorCreatingBrain", { ns: "brain" }),
});
},
});

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ export const useBrainKnowledgeStep = () => {
const { watch } = useFormContext<CreateBrainProps>();
const brainType = watch("brain_type");
const url = watch("brain_definition.url");
const compositeBrainConnections = watch("connected_brains_ids") ?? [];
const isApiBrain = brainType === "api";
const isChatflowBrain = brainType === "chatflow";
const isCompositeBrain = brainType === "composite";

const isApiBrainDefinitionsFilled = url !== "";

const isSubmitButtonDisabled =
isChatflowBrain || (isApiBrain && !isApiBrainDefinitionsFilled);
(isCompositeBrain && compositeBrainConnections.length === 0) ||
(isApiBrain && !isApiBrainDefinitionsFilled);

return {
brainType,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { useFeatureIsOn } from "@growthbook/growthbook-react";
import { useTranslation } from "react-i18next";

import { BrainType } from "@/lib/types/brainConfig";

// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export const useKnowledgeSourceLabel = () => {
const { t } = useTranslation(["translation", "brain", "config"]);
const isCompositeBrainActivated = useFeatureIsOn("agent-brain");

const knowledgeSourceOptions: {
label: string;
Expand All @@ -18,12 +20,15 @@ export const useKnowledgeSourceLabel = () => {
label: t("knowledge_source_api", { ns: "brain" }),
value: "api",
},
{
label: t("knowledge_source_chatflow", { ns: "brain" }),
value: "chatflow",
},
];

if (isCompositeBrainActivated) {
knowledgeSourceOptions.push({
label: t("knowledge_source_composite_brain", { ns: "brain" }),
value: "composite",
});
}

return {
knowledgeSourceOptions,
};
Expand Down
26 changes: 26 additions & 0 deletions frontend/lib/components/ui/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import * as React from "react";
import { LuCheck } from "react-icons/lu";

import { cn } from "@/lib/utils";

export const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
className
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("flex items-center justify-center text-current")}
>
<LuCheck className="h-4 w-4" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
1 change: 1 addition & 0 deletions frontend/lib/config/defaultBrainConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const addBrainDefaultValues: CreateBrainInput = {
},
secrets: [],
},
connected_brains_ids: [],
};

export const defaultModel: Model = "gpt-3.5-turbo";
Expand Down
2 changes: 1 addition & 1 deletion frontend/lib/types/brainConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const brainStatuses = ["private", "public"] as const;

export type BrainStatus = (typeof brainStatuses)[number];

export const brainTypes = ["doc", "api", "chatflow"] as const;
export const brainTypes = ["doc", "api", "composite"] as const;

export type BrainType = (typeof brainTypes)[number];

Expand Down
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@growthbook/growthbook-react": "^0.17.0",
"@june-so/analytics-next": "^2.0.0",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.3",
"@radix-ui/react-popover": "^1.0.6",
"@radix-ui/react-radio-group": "^1.1.3",
Expand Down
3 changes: 2 additions & 1 deletion frontend/public/locales/en/brain.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"shareBrainUsers": "Users with access",
"shareBrainLink": "Click to copy link to share your brain",
"copiedToClipboard": "Copied to clipboard",
"composite_brain_composition_invitation": "Connect your new brain to other existing brains from your library by selecting them.",
"inviteUsers": "Add new users",
"usersInvited": "Users successfully invited",
"errorSendingInvitation": "An error occurred while sending invitations",
Expand Down Expand Up @@ -50,7 +51,7 @@
"knowledge_source_doc": "Documents",
"knowledge_source_api": "App (Through API)",
"knowledge_source_label": "Knowledge source",
"knowledge_source_chatflow":"Agent",
"knowledge_source_composite_brain":"Agent",
"api_brain": {
"name": "Name",
"description": "Description",
Expand Down
3 changes: 2 additions & 1 deletion frontend/public/locales/es/brain.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"brainNamePlaceholder": "Ejemplo: Anotaciones de historia",
"brainUndefined": "Cerebro no definido",
"copiedToClipboard": "Copiado al portapeles",
"composite_brain_composition_invitation": "Conecta tu nuevo cerebro a otros cerebros existentes de tu biblioteca seleccionándolos.",
"defaultBrain": "Cerebro por defecto",
"errorCreatingBrain": "Error al crear cerebro",
"errorFetchingBrainUsers": "Error al obtener usuarios del cerebro",
Expand Down Expand Up @@ -49,7 +50,7 @@
"myBrains": "Mis cerebros",
"knowledge_source_doc": "Documentos",
"knowledge_source_api": "API",
"knowledge_source_chatflow": "Agente",
"knowledge_source_composite_brain": "Agente",
"knowledge_source_label": "Fuente de conocimiento",
"api_brain":{
"name": "Nombre",
Expand Down
3 changes: 2 additions & 1 deletion frontend/public/locales/fr/brain.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"brainNamePlaceholder": "Ex. Notes d'histoire",
"brainUndefined": "Cerveau non défini",
"copiedToClipboard": "Copié dans le presse-papier",
"composite_brain_composition_invitation":"Connectez votre nouveau cerveau à d'autres cerveaux existants de votre librairie en les sélectionnant.",
"defaultBrain": "Cerveau par défaut",
"errorCreatingBrain": "Une erreur s'est produite lors de la création d'un cerveau",
"errorFetchingBrainUsers": "Une erreur s'est produite lors de la récupération des utilisateurs du cerveau",
Expand Down Expand Up @@ -49,7 +50,7 @@
"myBrains": "Mes cerveaux",
"knowledge_source_doc": "Documents",
"knowledge_source_api": "API",
"knowledge_source_chatflow": "Agent",
"knowledge_source_composite_brain": "Agent",
"knowledge_source_label": "Source de connaissance",
"api_brain": {
"name": "Nom",
Expand Down
3 changes: 2 additions & 1 deletion frontend/public/locales/pt-br/brain.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"shareBrainUsers": "Usuários com acesso",
"shareBrainLink": "Clique para copiar o link de compartilhamento",
"copiedToClipboard": "Copiado para a área de transferência",
"composite_brain_composition_invitation": "Conecte seu novo cérebro a outros cérebros existentes em sua biblioteca selecionando-os.",
"inviteUsers": "Adicionar novos usuários",
"usersInvited": "Usuários convidados com sucesso",
"errorSendingInvitation": "Um erro ocorreu ao enviar o(s) convite(s)",
Expand Down Expand Up @@ -49,7 +50,7 @@
"myBrains": "Meus cérebros",
"knowledge_source_doc": "Documentos",
"knowledge_source_api": "API",
"knowledge_source_chatflow": "Agente",
"knowledge_source_composite_brain": "Agente",
"knowledge_source_label": "Fonte de conhecimento",
"api_brain":{
"name": "Name",
Expand Down
3 changes: 2 additions & 1 deletion frontend/public/locales/ru/brain.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"shareBrainUsers": "Пользователи с доступом",
"shareBrainLink": "Нажмите, чтобы скопировать ссылку для совместного использования мозга",
"copiedToClipboard": "Скопировано в буфер обмена",
"composite_brain_composition_invitation": "Подключите свой новый мозг к другим существующим мозгам из вашей библиотеки, выбрав их.",
"inviteUsers": "Добавить новых пользователей",
"usersInvited": "Пользователи успешно приглашены",
"errorSendingInvitation": "Ошибка при отправке приглашений",
Expand Down Expand Up @@ -49,7 +50,7 @@
"myBrains": "Мои мозги",
"knowledge_source_doc": "Документы",
"knowledge_source_api": "API",
"knowledge_source_chatflow": "Агент",
"knowledge_source_composite_brain": "Агент",
"knowledge_source_label": "Источник знаний",
"api_brain":{
"name": "Название",
Expand Down
3 changes: 2 additions & 1 deletion frontend/public/locales/zh-cn/brain.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"shareBrainUsers": "具有访问权限的用户",
"shareBrainLink": "点击复制链接来分享大脑",
"copiedToClipboard": "已复制到剪贴板",
"composite_brain_composition_invitation": "通过选择将您的新大脑连接到现有的其他大脑来进行组合。",
"inviteUsers": "添加新用户",
"usersInvited": "已成功邀请用户",
"errorSendingInvitation": "发送邀请时发生错误",
Expand Down Expand Up @@ -49,7 +50,7 @@
"myBrains": "我的大脑",
"knowledge_source_doc": "文档",
"knowledge_source_api": "API",
"knowledge_source_chatflow": "代理",
"knowledge_source_composite_brain": "代理",
"knowledge_source_label": "知识来源",
"api_brain":{
"name": "名称",
Expand Down
15 changes: 15 additions & 0 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,21 @@
"@babel/runtime" "^7.13.10"
"@radix-ui/react-primitive" "1.0.3"

"@radix-ui/react-checkbox@^1.0.4":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz#98f22c38d5010dd6df4c5744cac74087e3275f4b"
integrity sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==
dependencies:
"@babel/runtime" "^7.13.10"
"@radix-ui/primitive" "1.0.1"
"@radix-ui/react-compose-refs" "1.0.1"
"@radix-ui/react-context" "1.0.1"
"@radix-ui/react-presence" "1.0.1"
"@radix-ui/react-primitive" "1.0.3"
"@radix-ui/react-use-controllable-state" "1.0.1"
"@radix-ui/react-use-previous" "1.0.1"
"@radix-ui/react-use-size" "1.0.1"

"@radix-ui/react-collapsible@1.0.3":
version "1.0.3"
resolved "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.3.tgz"
Expand Down
Loading