Redirect to Builder after adding to library
This commit is contained in:
parent
0b9c0c9f12
commit
250ffdfaed
|
@ -95,13 +95,14 @@ async def get_library_agents(
|
||||||
) from e
|
) 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)
|
Get user agent from the store listing version
|
||||||
if they don't already have it
|
|
||||||
"""
|
"""
|
||||||
logger.debug(
|
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:
|
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
|
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
|
# Check if user already has this agent
|
||||||
existing_user_agent = await prisma.models.UserAgent.prisma().find_first(
|
existing_user_agent = await prisma.models.UserAgent.prisma().find_first(
|
||||||
where={
|
where={
|
||||||
|
@ -140,26 +133,94 @@ async def add_agent_to_library(store_listing_version_id: str, user_id: str) -> N
|
||||||
)
|
)
|
||||||
|
|
||||||
if existing_user_agent:
|
if existing_user_agent:
|
||||||
logger.debug(
|
logger.debug(f"User {user_id} has agent {agent.id} in their library")
|
||||||
f"User {user_id} already 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
|
logger.debug(f"User {user_id} does not have agent {agent.id} in their library")
|
||||||
await prisma.models.UserAgent.prisma().create(
|
return None
|
||||||
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:
|
except backend.server.v2.store.exceptions.AgentNotFoundError:
|
||||||
raise
|
raise
|
||||||
except prisma.errors.PrismaError as e:
|
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(
|
raise backend.server.v2.store.exceptions.DatabaseError(
|
||||||
"Failed to add agent to library"
|
"Failed to check library agent"
|
||||||
) from e
|
) 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
|
||||||
|
|
|
@ -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(
|
@router.post(
|
||||||
"/agents/{store_listing_version_id}",
|
"/agents/{store_listing_version_id}",
|
||||||
tags=["library", "private"],
|
tags=["library", "private"],
|
||||||
dependencies=[fastapi.Depends(autogpt_libs.auth.middleware.auth_middleware)],
|
dependencies=[fastapi.Depends(autogpt_libs.auth.middleware.auth_middleware)],
|
||||||
status_code=201,
|
|
||||||
)
|
)
|
||||||
async def add_agent_to_library(
|
async def add_agent_to_library(
|
||||||
store_listing_version_id: str,
|
store_listing_version_id: str,
|
||||||
user_id: typing.Annotated[
|
user_id: typing.Annotated[
|
||||||
str, fastapi.Depends(autogpt_libs.auth.depends.get_user_id)
|
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.
|
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
|
user_id (str): ID of the authenticated user
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
fastapi.Response: 201 status code on success
|
backend.data.graph.Graph: Agent added to the user's library
|
||||||
|
None: On failure
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
HTTPException: If there is an error adding the agent to the library
|
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:
|
except Exception:
|
||||||
logger.exception("Exception occurred whilst adding agent to library")
|
logger.exception("Exception occurred whilst adding agent to library")
|
||||||
|
|
|
@ -3,13 +3,14 @@
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { IconPlay, StarRatingIcons } from "@/components/ui/icons";
|
import { IconPlay, StarRatingIcons } from "@/components/ui/icons";
|
||||||
import { Separator } from "@/components/ui/separator";
|
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 { useRouter } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
|
|
||||||
import useSupabase from "@/hooks/useSupabase";
|
import useSupabase from "@/hooks/useSupabase";
|
||||||
import { DownloadIcon, LoaderIcon } from "lucide-react";
|
import { DownloadIcon, LoaderIcon } from "lucide-react";
|
||||||
|
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
|
||||||
interface AgentInfoProps {
|
interface AgentInfoProps {
|
||||||
name: string;
|
name: string;
|
||||||
creator: string;
|
creator: string;
|
||||||
|
@ -36,25 +37,51 @@ export const AgentInfo: React.FC<AgentInfoProps> = ({
|
||||||
storeListingVersionId,
|
storeListingVersionId,
|
||||||
}) => {
|
}) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const api = React.useMemo(() => new BackendAPI(), []);
|
const api = useBackendAPI();
|
||||||
const { user } = useSupabase();
|
const { user } = useSupabase();
|
||||||
const { toast } = useToast();
|
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);
|
React.useEffect(() => {
|
||||||
|
(async () => {
|
||||||
const handleAddToLibrary = async () => {
|
|
||||||
try {
|
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");
|
console.log("Agent added to library successfully");
|
||||||
router.push("/monitoring");
|
router.push(`/builder?flowID=${agent.id}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to add agent to library:", error);
|
console.error("Failed to add agent to library:", error);
|
||||||
}
|
}
|
||||||
};
|
setProcessing(false);
|
||||||
|
}, [api, router, storeListingVersionId, toast, user, userAgent]);
|
||||||
|
|
||||||
const handleDownloadToLibrary = async () => {
|
const handleDownloadToLibrary = React.useCallback(async () => {
|
||||||
const downloadAgent = async (): Promise<void> => {
|
setProcessing(true);
|
||||||
setDownloading(true);
|
|
||||||
try {
|
try {
|
||||||
const file = await api.downloadStoreAgent(storeListingVersionId);
|
const file = await api.downloadStoreAgent(storeListingVersionId);
|
||||||
|
|
||||||
|
@ -82,15 +109,15 @@ export const AgentInfo: React.FC<AgentInfoProps> = ({
|
||||||
toast({
|
toast({
|
||||||
title: "Download Complete",
|
title: "Download Complete",
|
||||||
description: "Your agent has been successfully downloaded.",
|
description: "Your agent has been successfully downloaded.",
|
||||||
|
duration: 2000,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error downloading agent:`, error);
|
console.error(`Error downloading agent:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
await downloadAgent();
|
setProcessing(false);
|
||||||
setDownloading(false);
|
}, [api, storeListingVersionId, toast]);
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="w-full max-w-[396px] px-4 sm:px-6 lg:w-[396px] lg:px-0">
|
<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
|
<button
|
||||||
onClick={handleAddToLibrary}
|
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"
|
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" />
|
<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">
|
<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>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
onClick={handleDownloadToLibrary}
|
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 ${
|
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-neutral-400"
|
||||||
: "bg-violet-600 hover:bg-violet-700"
|
: "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" />
|
<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" />
|
<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">
|
<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>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -367,8 +367,19 @@ export default class BackendAPI {
|
||||||
return this._get("/library/agents");
|
return this._get("/library/agents");
|
||||||
}
|
}
|
||||||
|
|
||||||
async addAgentToLibrary(storeListingVersionId: string): Promise<void> {
|
getUserLibraryAgent(
|
||||||
await this._request("POST", `/library/agents/${storeListingVersionId}`);
|
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}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue