Redirect to Builder after adding to library

This commit is contained in:
Krzysztof Czerwinski 2025-01-08 16:25:25 +01:00
parent 0b9c0c9f12
commit 250ffdfaed
4 changed files with 224 additions and 79 deletions

View File

@ -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

View File

@ -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")

View File

@ -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,25 +37,51 @@ export const AgentInfo: React.FC<AgentInfoProps> = ({
storeListingVersionId,
}) => {
const router = useRouter();
const api = React.useMemo(() => new BackendAPI(), []);
const api = useBackendAPI();
const { user } = useSupabase();
const { toast } = useToast();
const [userAgent, setAgent] = React.useState<GraphMeta | null>(null);
// Either downloading or adding to library
const [processing, setProcessing] = React.useState(false);
const [downloading, setDownloading] = React.useState(false);
const handleAddToLibrary = async () => {
React.useEffect(() => {
(async () => {
try {
await api.addAgentToLibrary(storeListingVersionId);
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);
try {
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<void> => {
setDownloading(true);
const handleDownloadToLibrary = React.useCallback(async () => {
setProcessing(true);
try {
const file = await api.downloadStoreAgent(storeListingVersionId);
@ -82,15 +109,15 @@ export const AgentInfo: React.FC<AgentInfoProps> = ({
toast({
title: "Download Complete",
description: "Your agent has been successfully downloaded.",
duration: 2000,
});
} catch (error) {
console.error(`Error downloading agent:`, error);
throw error;
}
};
await downloadAgent();
setDownloading(false);
};
setProcessing(false);
}, [api, storeListingVersionId, toast]);
return (
<div className="w-full max-w-[396px] px-4 sm:px-6 lg:w-[396px] lg:px-0">
@ -123,29 +150,38 @@ export const AgentInfo: React.FC<AgentInfoProps> = ({
<button
onClick={handleAddToLibrary}
className="inline-flex w-full items-center justify-center gap-2 rounded-[38px] bg-violet-600 px-4 py-3 transition-colors hover:bg-violet-700 sm:w-auto sm:gap-2.5 sm:px-5 sm:py-3.5 lg:px-6 lg:py-4"
disabled={processing || userAgent !== null}
>
{processing ? (
<LoaderIcon className="h-5 w-5 animate-spin text-white sm:h-5 sm:w-5 lg:h-6 lg:w-6" />
) : (
<IconPlay className="h-5 w-5 text-white sm:h-5 sm:w-5 lg:h-6 lg:w-6" />
)}
<span className="font-poppins text-base font-medium text-neutral-50 sm:text-lg">
Add To Library
{processing
? "Adding to Library..."
: userAgent
? "Already in Library"
: "Add Agent to Library"}
</span>
</button>
) : (
<button
onClick={handleDownloadToLibrary}
className={`inline-flex w-full items-center justify-center gap-2 rounded-[38px] px-4 py-3 transition-colors sm:w-auto sm:gap-2.5 sm:px-5 sm:py-3.5 lg:px-6 lg:py-4 ${
downloading
processing
? "bg-neutral-400"
: "bg-violet-600 hover:bg-violet-700"
}`}
disabled={downloading}
disabled={processing}
>
{downloading ? (
{processing ? (
<LoaderIcon className="h-5 w-5 animate-spin text-white sm:h-5 sm:w-5 lg:h-6 lg:w-6" />
) : (
<DownloadIcon className="h-5 w-5 text-white sm:h-5 sm:w-5 lg:h-6 lg:w-6" />
)}
<span className="font-poppins text-base font-medium text-neutral-50 sm:text-lg">
{downloading ? "Downloading..." : "Download Agent as File"}
{processing ? "Downloading..." : "Download Agent as File"}
</span>
</button>
)}

View File

@ -367,8 +367,19 @@ export default class BackendAPI {
return this._get("/library/agents");
}
async addAgentToLibrary(storeListingVersionId: string): Promise<void> {
await this._request("POST", `/library/agents/${storeListingVersionId}`);
getUserLibraryAgent(
storeListingVersionId: string,
): Promise<GraphMeta | null> {
return this._get(`/library/agents/${storeListingVersionId}`);
}
async addAgentToLibrary(
storeListingVersionId: string,
): Promise<GraphMeta | null> {
return await this._request(
"POST",
`/library/agents/${storeListingVersionId}`,
);
}
///////////////////////////////////////////