mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-01-14 09:38:00 -05:00
implement agent run "Delete" option
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
from collections import defaultdict
|
||||
from datetime import datetime, timezone
|
||||
from multiprocessing import Manager
|
||||
from typing import Any, AsyncGenerator, Generator, Generic, Optional, Type, TypeVar
|
||||
from typing import Any, AsyncGenerator, Generator, Generic, Type, TypeVar
|
||||
|
||||
from prisma import Json
|
||||
from prisma.enums import AgentExecutionStatus
|
||||
from prisma.errors import PrismaError
|
||||
from prisma.models import (
|
||||
AgentGraphExecution,
|
||||
AgentNodeExecution,
|
||||
@@ -331,28 +330,14 @@ async def update_execution_status(
|
||||
return ExecutionResult.from_db(res)
|
||||
|
||||
|
||||
async def get_execution(
|
||||
execution_id: str, user_id: str
|
||||
) -> Optional[AgentNodeExecution]:
|
||||
"""
|
||||
Get an execution by ID. Returns None if not found.
|
||||
|
||||
Args:
|
||||
execution_id: The ID of the execution to retrieve
|
||||
|
||||
Returns:
|
||||
The execution if found, None otherwise
|
||||
"""
|
||||
try:
|
||||
execution = await AgentNodeExecution.prisma().find_unique(
|
||||
where={
|
||||
"id": execution_id,
|
||||
"userId": user_id,
|
||||
}
|
||||
async def delete_execution(graph_exec_id: str, user_id: str) -> None:
|
||||
delete_count = await AgentGraphExecution.prisma().delete_many(
|
||||
where={"id": graph_exec_id, "userId": user_id}
|
||||
)
|
||||
if delete_count < 1:
|
||||
raise DatabaseError(
|
||||
f"Could not delete graph execution #{graph_exec_id}: not found"
|
||||
)
|
||||
return execution
|
||||
except PrismaError:
|
||||
return None
|
||||
|
||||
|
||||
async def get_execution_results(graph_exec_id: str) -> list[ExecutionResult]:
|
||||
|
||||
@@ -591,6 +591,7 @@ async def get_graphs(
|
||||
return graph_models
|
||||
|
||||
|
||||
# TODO: move execution stuff to .execution
|
||||
async def get_graphs_executions(user_id: str) -> list[GraphExecutionMeta]:
|
||||
executions = await AgentGraphExecution.prisma().find_many(
|
||||
where={"userId": user_id},
|
||||
|
||||
@@ -10,12 +10,14 @@ from autogpt_libs.auth.middleware import auth_middleware
|
||||
from autogpt_libs.feature_flag.client import feature_flag
|
||||
from autogpt_libs.utils.cache import thread_cached
|
||||
from fastapi import APIRouter, Body, Depends, HTTPException, Request, Response
|
||||
from starlette.status import HTTP_204_NO_CONTENT
|
||||
from typing_extensions import Optional, TypedDict
|
||||
|
||||
import backend.data.block
|
||||
import backend.server.integrations.router
|
||||
import backend.server.routers.analytics
|
||||
import backend.server.v2.library.db as library_db
|
||||
from backend.data import execution as execution_db
|
||||
from backend.data import graph as graph_db
|
||||
from backend.data.api_key import (
|
||||
APIKeyError,
|
||||
@@ -630,6 +632,19 @@ async def get_graph_execution(
|
||||
return result
|
||||
|
||||
|
||||
@v1_router.delete(
|
||||
path="/executions/{graph_exec_id}",
|
||||
tags=["graphs"],
|
||||
dependencies=[Depends(auth_middleware)],
|
||||
status_code=HTTP_204_NO_CONTENT,
|
||||
)
|
||||
async def delete_graph_execution(
|
||||
graph_exec_id: str,
|
||||
user_id: Annotated[str, Depends(get_user_id)],
|
||||
) -> None:
|
||||
await execution_db.delete_execution(graph_exec_id=graph_exec_id, user_id=user_id)
|
||||
|
||||
|
||||
########################################################
|
||||
##################### Schedules ########################
|
||||
########################################################
|
||||
|
||||
@@ -98,20 +98,30 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
fetchSchedules();
|
||||
}, [fetchSchedules]);
|
||||
|
||||
const removeSchedule = useCallback(
|
||||
async (scheduleId: string) => {
|
||||
const removedSchedule = await api.deleteSchedule(scheduleId);
|
||||
setSchedules(schedules.filter((s) => s.id !== removedSchedule.id));
|
||||
},
|
||||
[schedules, api],
|
||||
);
|
||||
|
||||
/* TODO: use websockets instead of polling - https://github.com/Significant-Gravitas/AutoGPT/issues/8782 */
|
||||
useEffect(() => {
|
||||
const intervalId = setInterval(() => fetchAgents(), 5000);
|
||||
return () => clearInterval(intervalId);
|
||||
}, [fetchAgents, agent]);
|
||||
|
||||
// =========================== ACTIONS ============================
|
||||
|
||||
const deleteRun = useCallback(
|
||||
async (graphExecID: string) => {
|
||||
await api.deleteGraphExecution(graphExecID);
|
||||
setAgentRuns(agentRuns.filter((r) => r.execution_id !== graphExecID));
|
||||
},
|
||||
[agentRuns, api],
|
||||
);
|
||||
|
||||
const deleteSchedule = useCallback(
|
||||
async (scheduleID: string) => {
|
||||
const removedSchedule = await api.deleteSchedule(scheduleID);
|
||||
setSchedules(schedules.filter((s) => s.id !== removedSchedule.id));
|
||||
},
|
||||
[schedules, api],
|
||||
);
|
||||
|
||||
const agentActions: { label: string; callback: () => void }[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
@@ -139,7 +149,9 @@ export default function AgentRunsPage(): React.ReactElement {
|
||||
selectedView={selectedView}
|
||||
onSelectRun={selectRun}
|
||||
onSelectSchedule={selectSchedule}
|
||||
onDraftNewRun={openRunDraftView}
|
||||
onSelectDraftNewRun={openRunDraftView}
|
||||
onDeleteRun={(id) => deleteRun(id)}
|
||||
onDeleteSchedule={(id) => deleteSchedule(id)}
|
||||
/>
|
||||
|
||||
<div className="flex-1">
|
||||
|
||||
@@ -18,24 +18,24 @@ import AgentRunStatusChip, {
|
||||
} from "@/components/agents/agent-run-status-chip";
|
||||
|
||||
export type AgentRunSummaryProps = {
|
||||
agentID: string;
|
||||
agentRunID: string;
|
||||
status: AgentRunStatus;
|
||||
title: string;
|
||||
timestamp: number | Date;
|
||||
selected?: boolean;
|
||||
onClick?: () => void;
|
||||
// onRename: () => void;
|
||||
onDelete: () => void;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
export default function AgentRunSummaryCard({
|
||||
agentID,
|
||||
agentRunID,
|
||||
status,
|
||||
title,
|
||||
timestamp,
|
||||
selected = false,
|
||||
onClick,
|
||||
// onRename,
|
||||
onDelete,
|
||||
className,
|
||||
}: AgentRunSummaryProps): React.ReactElement {
|
||||
return (
|
||||
@@ -55,32 +55,24 @@ export default function AgentRunSummaryCard({
|
||||
{title}
|
||||
</h3>
|
||||
|
||||
{/* <DropdownMenu>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant="ghost" className="h-5 w-5 p-0">
|
||||
<MoreVertical className="h-5 w-5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
// TODO: implement
|
||||
>
|
||||
Pin into a template
|
||||
{/* {onPinAsPreset && (
|
||||
<DropdownMenuItem onClick={onPinAsPreset}>
|
||||
Pin as a preset
|
||||
</DropdownMenuItem>
|
||||
)} */}
|
||||
|
||||
<DropdownMenuItem
|
||||
// TODO: implement
|
||||
>
|
||||
Rename
|
||||
</DropdownMenuItem>
|
||||
{/* <DropdownMenuItem onClick={onRename}>Rename</DropdownMenuItem> */}
|
||||
|
||||
<DropdownMenuItem
|
||||
// TODO: implement
|
||||
>
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={onDelete}>Delete</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu> */}
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
<p
|
||||
|
||||
@@ -23,7 +23,8 @@ interface AgentRunsSelectorListProps {
|
||||
selectedView: { type: "run" | "schedule"; id?: string };
|
||||
onSelectRun: (id: string) => void;
|
||||
onSelectSchedule: (schedule: Schedule) => void;
|
||||
onDraftNewRun: () => void;
|
||||
onSelectDraftNewRun: () => void;
|
||||
onDeleteSchedule: (id: string) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
@@ -34,7 +35,9 @@ export default function AgentRunsSelectorList({
|
||||
selectedView,
|
||||
onSelectRun,
|
||||
onSelectSchedule,
|
||||
onDraftNewRun,
|
||||
onSelectDraftNewRun,
|
||||
onDeleteRun,
|
||||
onDeleteSchedule,
|
||||
className,
|
||||
}: AgentRunsSelectorListProps): React.ReactElement {
|
||||
const [activeListTab, setActiveListTab] = useState<"runs" | "scheduled">(
|
||||
@@ -51,7 +54,7 @@ export default function AgentRunsSelectorList({
|
||||
? "agpt-card-selected text-accent"
|
||||
: "")
|
||||
}
|
||||
onClick={onDraftNewRun}
|
||||
onClick={onSelectDraftNewRun}
|
||||
>
|
||||
<Plus className="h-6 w-6" />
|
||||
<span>New run</span>
|
||||
@@ -91,7 +94,7 @@ export default function AgentRunsSelectorList({
|
||||
? "agpt-card-selected text-accent"
|
||||
: "")
|
||||
}
|
||||
onClick={onDraftNewRun}
|
||||
onClick={onSelectDraftNewRun}
|
||||
>
|
||||
<Plus className="h-6 w-6" />
|
||||
<span>New run</span>
|
||||
@@ -102,13 +105,12 @@ export default function AgentRunsSelectorList({
|
||||
<AgentRunSummaryCard
|
||||
className="h-28 w-72 lg:h-32 xl:w-80"
|
||||
key={i}
|
||||
agentID={run.graph_id}
|
||||
agentRunID={run.execution_id}
|
||||
status={agentRunStatusMap[run.status]}
|
||||
title={agent.name}
|
||||
timestamp={run.started_at}
|
||||
selected={selectedView.id === run.execution_id}
|
||||
onClick={() => onSelectRun(run.execution_id)}
|
||||
onDelete={() => onDeleteRun(run.execution_id)}
|
||||
/>
|
||||
))
|
||||
: schedules
|
||||
@@ -117,13 +119,12 @@ export default function AgentRunsSelectorList({
|
||||
<AgentRunSummaryCard
|
||||
className="h-28 w-72 lg:h-32 xl:w-80"
|
||||
key={i}
|
||||
agentID={schedule.graph_id}
|
||||
agentRunID={schedule.id}
|
||||
status="scheduled"
|
||||
title={schedule.name}
|
||||
timestamp={schedule.next_run_time}
|
||||
selected={selectedView.id === schedule.id}
|
||||
onClick={() => onSelectSchedule(schedule)}
|
||||
onDelete={() => onDeleteSchedule(schedule.id)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@@ -246,6 +246,10 @@ export default class BackendAPI {
|
||||
return result;
|
||||
}
|
||||
|
||||
async deleteGraphExecution(runID: string): Promise<void> {
|
||||
await this._request("DELETE", `/executions/${runID}`);
|
||||
}
|
||||
|
||||
oAuthLogin(
|
||||
provider: string,
|
||||
scopes?: string[],
|
||||
|
||||
Reference in New Issue
Block a user