From 250ffdfaed8b6c3fa67057baeb924f007f587c5b Mon Sep 17 00:00:00 2001 From: Krzysztof Czerwinski Date: Wed, 8 Jan 2025 16:25:25 +0100 Subject: [PATCH] Redirect to Builder after adding to library --- .../backend/backend/server/v2/library/db.py | 115 ++++++++++++---- .../backend/server/v2/library/routes.py | 45 +++++- .../src/components/agptui/AgentInfo.tsx | 128 +++++++++++------- .../src/lib/autogpt-server-api/client.ts | 15 +- 4 files changed, 224 insertions(+), 79 deletions(-) diff --git a/autogpt_platform/backend/backend/server/v2/library/db.py b/autogpt_platform/backend/backend/server/v2/library/db.py index 8d142ef40c..2b6ad1fdfb 100644 --- a/autogpt_platform/backend/backend/server/v2/library/db.py +++ b/autogpt_platform/backend/backend/server/v2/library/db.py @@ -95,13 +95,14 @@ async def get_library_agents( ) from e -async def add_agent_to_library(store_listing_version_id: str, user_id: str) -> None: +async def get_library_agent( + store_listing_version_id: str, user_id: str +) -> backend.data.graph.Graph | None: """ - Finds the agent from the store listing version and adds it to the user's library (UserAgent table) - if they don't already have it + Get user agent from the store listing version """ logger.debug( - f"Adding agent from store listing version {store_listing_version_id} to library for user {user_id}" + f"Getting agent by store listing version {store_listing_version_id} for user {user_id}" ) try: @@ -122,14 +123,6 @@ async def add_agent_to_library(store_listing_version_id: str, user_id: str) -> N agent = store_listing_version.Agent - if agent.userId == user_id: - logger.warning( - f"User {user_id} cannot add their own agent to their library" - ) - raise backend.server.v2.store.exceptions.DatabaseError( - "Cannot add own agent to library" - ) - # Check if user already has this agent existing_user_agent = await prisma.models.UserAgent.prisma().find_first( where={ @@ -140,26 +133,94 @@ async def add_agent_to_library(store_listing_version_id: str, user_id: str) -> N ) if existing_user_agent: - logger.debug( - f"User {user_id} already has agent {agent.id} in their library" + logger.debug(f"User {user_id} has agent {agent.id} in their library") + return backend.data.graph.Graph( + id=agent.id, + version=agent.version, + is_active=agent.isActive, + name=agent.name or "", + description=agent.description or "", ) - return - # Create UserAgent entry - await prisma.models.UserAgent.prisma().create( - data=prisma.types.UserAgentCreateInput( - userId=user_id, - agentId=agent.id, - agentVersion=agent.version, - isCreatedByUser=False, - ) - ) - logger.debug(f"Added agent {agent.id} to library for user {user_id}") + logger.debug(f"User {user_id} does not have agent {agent.id} in their library") + return None except backend.server.v2.store.exceptions.AgentNotFoundError: raise except prisma.errors.PrismaError as e: - logger.error(f"Database error adding agent to library: {str(e)}") + logger.error(f"Database error checking library agent: {str(e)}") raise backend.server.v2.store.exceptions.DatabaseError( - "Failed to add agent to library" + "Failed to check library agent" ) from e + + +# async def add_agent_to_library( +# store_listing_version_id: str, user_id: str +# ) -> backend.data.graph.Graph | None: +# """ +# Finds the agent from the store listing version and adds it to the user's library (UserAgent table) +# if they don't already have it +# """ +# logger.debug( +# f"Adding agent from store listing version {store_listing_version_id} to library for user {user_id}" +# ) + +# try: +# # Get store listing version to find agent +# store_listing_version = ( +# await prisma.models.StoreListingVersion.prisma().find_unique( +# where={"id": store_listing_version_id}, include={"Agent": True} +# ) +# ) + +# if not store_listing_version or not store_listing_version.Agent: +# logger.warning( +# f"Store listing version not found: {store_listing_version_id}" +# ) +# raise backend.server.v2.store.exceptions.AgentNotFoundError( +# f"Store listing version {store_listing_version_id} not found" +# ) + +# agent = store_listing_version.Agent + +# if agent.userId == user_id: +# logger.warning( +# f"User {user_id} cannot add their own agent to their library" +# ) +# raise backend.server.v2.store.exceptions.DatabaseError( +# "Cannot add own agent to library" +# ) + +# # Check if user already has this agent +# existing_user_agent = await prisma.models.UserAgent.prisma().find_first( +# where={ +# "userId": user_id, +# "agentId": agent.id, +# "agentVersion": agent.version, +# } +# ) + +# if existing_user_agent: +# logger.debug( +# f"User {user_id} already has agent {agent.id} in their library" +# ) +# return + +# # Create UserAgent entry +# await prisma.models.UserAgent.prisma().create( +# data=prisma.types.UserAgentCreateInput( +# userId=user_id, +# agentId=agent.id, +# agentVersion=agent.version, +# isCreatedByUser=False, +# ) +# ) +# logger.debug(f"Added agent {agent.id} to library for user {user_id}") + +# except backend.server.v2.store.exceptions.AgentNotFoundError: +# raise +# except prisma.errors.PrismaError as e: +# logger.error(f"Database error adding agent to library: {str(e)}") +# raise backend.server.v2.store.exceptions.DatabaseError( +# "Failed to add agent to library" +# ) from e diff --git a/autogpt_platform/backend/backend/server/v2/library/routes.py b/autogpt_platform/backend/backend/server/v2/library/routes.py index 0c3b1a77ec..ae456d7f3f 100644 --- a/autogpt_platform/backend/backend/server/v2/library/routes.py +++ b/autogpt_platform/backend/backend/server/v2/library/routes.py @@ -43,18 +43,54 @@ async def get_library_agents( ) +@router.get( + "/agents/{store_listing_version_id}", + tags=["library", "private"], + dependencies=[fastapi.Depends(autogpt_libs.auth.middleware.auth_middleware)], +) +async def get_library_agent( + store_listing_version_id: str, + user_id: typing.Annotated[ + str, fastapi.Depends(autogpt_libs.auth.depends.get_user_id) + ], +) -> backend.data.graph.Graph | None: + """ + Get an agent from the user's library by store listing version ID. + + Args: + store_listing_version_id (str): ID of the store listing version to get + user_id (str): ID of the authenticated user + + Returns: + backend.data.graph.Graph: Agent from the user's library + None: If the agent is not found in the user's library + + Raises: + HTTPException: If there is an error getting the agent from the library + """ + try: + agent = await backend.server.v2.library.db.get_library_agent( + store_listing_version_id, user_id + ) + return agent + except Exception: + logger.exception("Exception occurred whilst getting library agent") + raise fastapi.HTTPException( + status_code=500, detail="Failed to get library agent" + ) + + @router.post( "/agents/{store_listing_version_id}", tags=["library", "private"], dependencies=[fastapi.Depends(autogpt_libs.auth.middleware.auth_middleware)], - status_code=201, ) async def add_agent_to_library( store_listing_version_id: str, user_id: typing.Annotated[ str, fastapi.Depends(autogpt_libs.auth.depends.get_user_id) ], -) -> fastapi.Response: +) -> backend.data.graph.Graph | None: """ Add an agent from the store to the user's library. @@ -63,7 +99,8 @@ async def add_agent_to_library( user_id (str): ID of the authenticated user Returns: - fastapi.Response: 201 status code on success + backend.data.graph.Graph: Agent added to the user's library + None: On failure Raises: HTTPException: If there is an error adding the agent to the library @@ -114,7 +151,7 @@ async def add_agent_to_library( ) ) - return fastapi.Response(status_code=201) + return graph except Exception: logger.exception("Exception occurred whilst adding agent to library") diff --git a/autogpt_platform/frontend/src/components/agptui/AgentInfo.tsx b/autogpt_platform/frontend/src/components/agptui/AgentInfo.tsx index 03f7d141d7..d003cbf710 100644 --- a/autogpt_platform/frontend/src/components/agptui/AgentInfo.tsx +++ b/autogpt_platform/frontend/src/components/agptui/AgentInfo.tsx @@ -3,13 +3,14 @@ import * as React from "react"; import { IconPlay, StarRatingIcons } from "@/components/ui/icons"; import { Separator } from "@/components/ui/separator"; -import BackendAPI from "@/lib/autogpt-server-api"; +import BackendAPI, { GraphMeta } from "@/lib/autogpt-server-api"; import { useRouter } from "next/navigation"; import Link from "next/link"; import { useToast } from "@/components/ui/use-toast"; import useSupabase from "@/hooks/useSupabase"; import { DownloadIcon, LoaderIcon } from "lucide-react"; +import { useBackendAPI } from "@/lib/autogpt-server-api/context"; interface AgentInfoProps { name: string; creator: string; @@ -36,61 +37,87 @@ export const AgentInfo: React.FC = ({ storeListingVersionId, }) => { const router = useRouter(); - const api = React.useMemo(() => new BackendAPI(), []); + const api = useBackendAPI(); const { user } = useSupabase(); const { toast } = useToast(); + const [userAgent, setAgent] = React.useState(null); + // Either downloading or adding to library + const [processing, setProcessing] = React.useState(false); - const [downloading, setDownloading] = React.useState(false); + React.useEffect(() => { + (async () => { + try { + const agent = await api.getUserLibraryAgent(storeListingVersionId); + setAgent(agent); + } catch (error) { + console.error("Failed to fetch library agent:", error); + } + })(); + }, [api, storeListingVersionId]); + + const handleAddToLibrary = React.useCallback(async () => { + if (!user || userAgent) { + return; + } + + toast({ + title: "Adding to Library", + description: "Adding agent to library and opening builder...", + duration: 2000, + }); + setProcessing(true); - const handleAddToLibrary = async () => { try { - await api.addAgentToLibrary(storeListingVersionId); + const agent = await api.addAgentToLibrary(storeListingVersionId); + if (!agent) { + throw new Error(); + } console.log("Agent added to library successfully"); - router.push("/monitoring"); + router.push(`/builder?flowID=${agent.id}`); } catch (error) { console.error("Failed to add agent to library:", error); } - }; + setProcessing(false); + }, [api, router, storeListingVersionId, toast, user, userAgent]); - const handleDownloadToLibrary = async () => { - const downloadAgent = async (): Promise => { - setDownloading(true); - try { - const file = await api.downloadStoreAgent(storeListingVersionId); + const handleDownloadToLibrary = React.useCallback(async () => { + setProcessing(true); + try { + const file = await api.downloadStoreAgent(storeListingVersionId); - // Similar to Marketplace v1 - const jsonData = JSON.stringify(file, null, 2); - // Create a Blob from the file content - const blob = new Blob([jsonData], { type: "application/json" }); + // Similar to Marketplace v1 + const jsonData = JSON.stringify(file, null, 2); + // Create a Blob from the file content + const blob = new Blob([jsonData], { type: "application/json" }); - // Create a temporary URL for the Blob - const url = window.URL.createObjectURL(blob); + // Create a temporary URL for the Blob + const url = window.URL.createObjectURL(blob); - // Create a temporary anchor element - const a = document.createElement("a"); - a.href = url; - a.download = `agent_${storeListingVersionId}.json`; // Set the filename + // Create a temporary anchor element + const a = document.createElement("a"); + a.href = url; + a.download = `agent_${storeListingVersionId}.json`; // Set the filename - // Append the anchor to the body, click it, and remove it - document.body.appendChild(a); - a.click(); - document.body.removeChild(a); + // Append the anchor to the body, click it, and remove it + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); - // Revoke the temporary URL - window.URL.revokeObjectURL(url); + // Revoke the temporary URL + window.URL.revokeObjectURL(url); - toast({ - title: "Download Complete", - description: "Your agent has been successfully downloaded.", - }); - } catch (error) { - console.error(`Error downloading agent:`, error); - throw error; - } - }; - await downloadAgent(); - setDownloading(false); - }; + toast({ + title: "Download Complete", + description: "Your agent has been successfully downloaded.", + duration: 2000, + }); + } catch (error) { + console.error(`Error downloading agent:`, error); + throw error; + } + + setProcessing(false); + }, [api, storeListingVersionId, toast]); return (
@@ -123,29 +150,38 @@ export const AgentInfo: React.FC = ({ ) : ( )} diff --git a/autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts b/autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts index 1f74e67f63..010b65aaba 100644 --- a/autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts +++ b/autogpt_platform/frontend/src/lib/autogpt-server-api/client.ts @@ -367,8 +367,19 @@ export default class BackendAPI { return this._get("/library/agents"); } - async addAgentToLibrary(storeListingVersionId: string): Promise { - await this._request("POST", `/library/agents/${storeListingVersionId}`); + getUserLibraryAgent( + storeListingVersionId: string, + ): Promise { + return this._get(`/library/agents/${storeListingVersionId}`); + } + + async addAgentToLibrary( + storeListingVersionId: string, + ): Promise { + return await this._request( + "POST", + `/library/agents/${storeListingVersionId}`, + ); } ///////////////////////////////////////////