-
-
- See runs
-
+
+
+ {name}
+
- {isCreatedByUser && (
+
+ {descriptions}
+
+
+
+
- Open in builder
+ See runs
- )}
-
- {/* {output && (
-
- New output
+
+ {!isCreatedByUser && (
+
+ Open in builder
+
+ )}
- )} */}
+
);
diff --git a/autogpt_platform/frontend/src/components/agptui/LibraryUploadAgent.tsx b/autogpt_platform/frontend/src/components/agptui/LibraryUploadAgent.tsx
index cc913ce2ae..d3bf14abcd 100644
--- a/autogpt_platform/frontend/src/components/agptui/LibraryUploadAgent.tsx
+++ b/autogpt_platform/frontend/src/components/agptui/LibraryUploadAgent.tsx
@@ -3,7 +3,7 @@ import { Upload, X } from "lucide-react";
import { Button } from "./Button";
import { useEffect, useState } from "react";
import { motion, useAnimation } from "framer-motion";
-import { cn } from "@/lib/utils";
+import { cn, removeCredentials } from "@/lib/utils";
import {
Dialog,
DialogContent,
@@ -11,23 +11,86 @@ import {
DialogTitle,
DialogTrigger,
} from "../ui/dialog";
+import { z } from "zod";
+import { useForm } from "react-hook-form";
+import { zodResolver } from "@hookform/resolvers/zod";
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from "@/components/ui/form";
import { Input } from "../ui/input";
import { FileUploader } from "react-drag-drop-files";
+import { Graph, GraphCreatable } from "@/lib/autogpt-server-api";
+import { useBackendAPI } from "@/lib/autogpt-server-api/context";
+import { Textarea } from "@/components/ui/textarea";
const fileTypes = ["JSON"];
+const fileSchema = z.custom
((val) => val instanceof File, {
+ message: "Must be a File object",
+});
+
+const formSchema = z.object({
+ agentFile: fileSchema,
+ agentName: z.string().min(1, "Agent name is required"),
+ agentDescription: z.string(),
+});
+
+function updateBlockIDs(graph: Graph) {
+ const updatedBlockIDMap: Record = {
+ "a1b2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6":
+ "436c3984-57fd-4b85-8e9a-459b356883bd",
+ "b2g2c3d4-5e6f-7g8h-9i0j-k1l2m3n4o5p6":
+ "0e50422c-6dee-4145-83d6-3a5a392f65de",
+ "c3d4e5f6-7g8h-9i0j-1k2l-m3n4o5p6q7r8":
+ "a0a69be1-4528-491c-a85a-a4ab6873e3f0",
+ "c3d4e5f6-g7h8-i9j0-k1l2-m3n4o5p6q7r8":
+ "32a87eab-381e-4dd4-bdb8-4c47151be35a",
+ "b2c3d4e5-6f7g-8h9i-0j1k-l2m3n4o5p6q7":
+ "87840993-2053-44b7-8da4-187ad4ee518c",
+ "h1i2j3k4-5l6m-7n8o-9p0q-r1s2t3u4v5w6":
+ "d0822ab5-9f8a-44a3-8971-531dd0178b6b",
+ "d3f4g5h6-1i2j-3k4l-5m6n-7o8p9q0r1s2t":
+ "df06086a-d5ac-4abb-9996-2ad0acb2eff7",
+ "h5e7f8g9-1b2c-3d4e-5f6g-7h8i9j0k1l2m":
+ "f5b0f5d0-1862-4d61-94be-3ad0fa772760",
+ "a1234567-89ab-cdef-0123-456789abcdef":
+ "4335878a-394e-4e67-adf2-919877ff49ae",
+ "f8e7d6c5-b4a3-2c1d-0e9f-8g7h6i5j4k3l":
+ "f66a3543-28d3-4ab5-8945-9b336371e2ce",
+ "b29c1b50-5d0e-4d9f-8f9d-1b0e6fcbf0h2":
+ "716a67b3-6760-42e7-86dc-18645c6e00fc",
+ "31d1064e-7446-4693-o7d4-65e5ca9110d1":
+ "cc10ff7b-7753-4ff2-9af6-9399b1a7eddc",
+ "c6731acb-4105-4zp1-bc9b-03d0036h370g":
+ "5ebe6768-8e5d-41e3-9134-1c7bd89a8d52",
+ };
+ graph.nodes
+ .filter((node) => node.block_id in updatedBlockIDMap)
+ .forEach((node) => {
+ node.block_id = updatedBlockIDMap[node.block_id];
+ });
+ return graph;
+}
+
export const LibraryUploadAgent = () => {
const [scrolled, setScrolled] = useState(false);
- const [file, setFile] = useState(null);
const [isDroped, setisDroped] = useState(false);
const controls = useAnimation();
- const handleChange = (file: File) => {
- setTimeout(() => {
- setisDroped(false);
- }, 2000);
- setFile(file);
- setisDroped(false);
- };
+ const api = useBackendAPI();
+ const [agentObject, setAgentObject] = useState(null);
+
+ const form = useForm>({
+ resolver: zodResolver(formSchema),
+ defaultValues: {
+ agentName: "",
+ agentDescription: "",
+ },
+ });
useEffect(() => {
const handleScroll = () => {
@@ -42,11 +105,66 @@ export const LibraryUploadAgent = () => {
return () => window.removeEventListener("scroll", handleScroll);
}, []);
- const handleUpload = () => {
- // Add upload logic here
- if (file) {
- console.log("Uploading file:", file);
+ const onSubmit = (values: z.infer) => {
+ if (!agentObject) {
+ form.setError("root", { message: "No Agent object to save" });
+ return;
}
+ const payload: GraphCreatable = {
+ ...agentObject,
+ name: values.agentName,
+ description: values.agentDescription,
+ is_active: true,
+ };
+
+ api
+ .createGraph(payload)
+ .then((response) => {
+ const qID = "flowID";
+ window.location.href = `/build?${qID}=${response.id}`;
+ })
+ .catch((error) => {
+ form.setError("root", {
+ message: `Could not create agent: ${error}`,
+ });
+ });
+ };
+
+ const handleChange = (file: File) => {
+ setTimeout(() => {
+ setisDroped(false);
+ }, 2000);
+
+ form.setValue("agentFile", file);
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ try {
+ const obj = JSON.parse(event.target?.result as string);
+ if (
+ !["name", "description", "nodes", "links"].every(
+ (key) => key in obj && obj[key] != null,
+ )
+ ) {
+ throw new Error(
+ "Invalid agent object in file: " + JSON.stringify(obj, null, 2),
+ );
+ }
+ const agent = obj as Graph;
+ removeCredentials(agent);
+ updateBlockIDs(agent);
+ setAgentObject(agent);
+ if (!form.getValues("agentName")) {
+ form.setValue("agentName", agent.name);
+ }
+ if (!form.getValues("agentDescription")) {
+ form.setValue("agentDescription", agent.description);
+ }
+ } catch (error) {
+ console.error("Error loading agent file:", error);
+ }
+ };
+ reader.readAsText(file);
+ setisDroped(false);
};
return (
@@ -82,85 +200,123 @@ export const LibraryUploadAgent = () => {
- Upload Agent
+ Upload Agent
-
-
-
-
- {file ? (
-
- {file.name}
-
-
- ) : (
-
{
- setisDroped(true);
- }}
- onSelect={() => {
- setisDroped(true);
- }}
- children={
-
- {isDroped ? (
-
- ) : (
- <>
-
Drop your agent here
-
or
-
Click to upload
- >
- )}
-
- }
+
+ (
+
+ Description
+
+
+
+
+
+ )}
+ />
+
+ (
+
+
+ {field.value ? (
+
+ {field.value.name}
+
+
+ ) : (
+ {
+ setisDroped(true);
+ }}
+ onSelect={() => setisDroped(true)}
+ >
+
+ {isDroped ? (
+
+ ) : (
+ <>
+
Drop your agent here
+
or
+
Click to upload
+ >
+ )}
+
+
+ )}
+
+
+
+ )}
+ />
+
+
+
+
);
diff --git a/autogpt_platform/frontend/src/components/agptui/composite/LibraryAgentListContainer.tsx b/autogpt_platform/frontend/src/components/agptui/composite/LibraryAgentListContainer.tsx
index 890f21ef2a..21ed9c3281 100644
--- a/autogpt_platform/frontend/src/components/agptui/composite/LibraryAgentListContainer.tsx
+++ b/autogpt_platform/frontend/src/components/agptui/composite/LibraryAgentListContainer.tsx
@@ -80,7 +80,7 @@ const LibraryAgentListContainer: React.FC<
+
{agents?.map((agent) => (
([]);
const [agentLoading, setAgentLoading] = useState(true);
- const [searchTerm, setSearchTerm] = useState(undefined);
+ const [searchTerm, setSearchTerm] = useState("");
const [uploadedFile, setUploadedFile] = useState(null);
const [libraryFilter, setLibraryFilter] = useState(
LibraryAgentFilterEnum.UPDATED_AT,