From 187ab0474512322b1d0ca9a0763a423053461294 Mon Sep 17 00:00:00 2001 From: Ubbe Date: Mon, 16 Feb 2026 18:29:59 +0800 Subject: [PATCH] refactor(frontend): remove OldAgentLibraryView and NEW_AGENT_RUNS flag (#12088) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Removes the deprecated `OldAgentLibraryView` directory (13 files, ~2200 lines deleted) - Removes the `NEW_AGENT_RUNS` feature flag from the `Flag` enum and defaults - Removes the legacy agent library page at `library/legacy/[id]` - Moves shared `CronScheduler` components to `src/components/contextual/CronScheduler/` - Moves `agent-run-draft-view` and `agent-status-chip` to `legacy-builder/` (co-located with their only consumer) - Updates all import paths in consuming files (`AgentInfoStep`, `SaveControl`, `RunnerInputUI`, `useRunGraph`) ## Test plan - [x] `pnpm format` passes - [x] `pnpm types` passes (no TypeScript errors) - [x] No remaining references to `OldAgentLibraryView`, `NEW_AGENT_RUNS`, or `new-agent-runs` in the codebase - [x] Verify `RunnerInputUI` dialog still works in the legacy builder - [x] Verify `AgentInfoStep` cron scheduling works in the publish modal - [x] Verify `SaveControl` cron scheduling works in the legacy builder πŸ€– Generated with [Claude Code](https://claude.com/claude-code)

Greptile Overview

Greptile Summary

This PR removes deprecated code from the legacy agent library view system and consolidates the codebase to use the new agent runs implementation exclusively. The refactor successfully removes ~2200 lines of code across 13 deleted files while properly relocating shared components. **Key changes:** - Removed the entire `OldAgentLibraryView` directory and its 13 component files - Removed the `NEW_AGENT_RUNS` feature flag from the `Flag` enum and defaults - Deleted the legacy agent library page route at `library/legacy/[id]` - Moved `CronScheduler` components to `src/components/contextual/CronScheduler/` for shared use across the application - Moved `agent-run-draft-view` and `agent-status-chip` to `legacy-builder/` directory, co-locating them with their only consumer - Updated `useRunGraph.ts` to import `GraphExecutionMeta` from the generated API models instead of the deleted custom type definition - Updated all import paths in consuming components (`AgentInfoStep`, `SaveControl`, `RunnerInputUI`) **Technical notes:** - The new import path for `GraphExecutionMeta` (`@/app/api/__generated__/models/graphExecutionMeta`) will be generated when running `pnpm generate:api` from the OpenAPI spec - All references to the old code have been cleanly removed from the codebase - The refactor maintains proper separation of concerns by moving shared components to contextual locations

Confidence Score: 4/5

- This PR is safe to merge with minimal risk, pending manual verification of the UI components mentioned in the test plan - The refactor is well-structured and all code changes are correct. The score of 4 (rather than 5) reflects that the PR author has marked three manual testing items as incomplete in the test plan: verifying `RunnerInputUI` dialog, `AgentInfoStep` cron scheduling, and `SaveControl` cron scheduling. While the code changes are sound, these UI components should be manually tested before merging to ensure the moved components work correctly in their new locations. - No files require special attention. The author should complete the manual testing checklist items for `RunnerInputUI`, `AgentInfoStep`, and `SaveControl` as noted in the test plan.

Sequence Diagram

```mermaid sequenceDiagram participant Dev as Developer participant FE as Frontend Build participant API as Backend API participant Gen as Generated Types Note over Dev,Gen: Refactor: Remove OldAgentLibraryView & NEW_AGENT_RUNS flag Dev->>FE: Delete OldAgentLibraryView (13 files, ~2200 lines) Dev->>FE: Remove NEW_AGENT_RUNS from Flag enum Dev->>FE: Delete library/legacy/[id]/page.tsx Dev->>FE: Move CronScheduler β†’ src/components/contextual/ Dev->>FE: Move agent-run-draft-view β†’ legacy-builder/ Dev->>FE: Move agent-status-chip β†’ legacy-builder/ Dev->>FE: Update RunnerInputUI import path Dev->>FE: Update SaveControl import path Dev->>FE: Update AgentInfoStep import path Dev->>FE: Update useRunGraph.ts FE->>Gen: Import GraphExecutionMeta from generated models Note over Gen: Type available after pnpm generate:api Gen-->>API: Uses OpenAPI spec schema API-->>FE: Type-safe GraphExecutionMeta model ```
Co-authored-by: Claude Opus 4.6 --- .../components/RunGraph/useRunGraph.ts | 2 +- .../legacy-builder/RunnerInputUI.tsx | 2 +- .../components/legacy-builder/SaveControl.tsx | 2 +- .../legacy-builder}/agent-run-draft-view.tsx | 7 +- .../legacy-builder}/agent-status-chip.tsx | 0 .../OldAgentLibraryView.tsx | 631 ------------------ .../components/agent-run-details-view.tsx | 445 ------------ .../components/agent-run-output-view.tsx | 178 ----- .../components/agent-run-status-chip.tsx | 68 -- .../components/agent-run-summary-card.tsx | 130 ---- .../components/agent-runs-selector-list.tsx | 237 ------- .../agent-schedule-details-view.tsx | 180 ----- .../components/create-preset-dialog.tsx | 100 --- .../OldAgentLibraryView/use-agent-runs.ts | 210 ------ .../(platform)/library/legacy/[id]/page.tsx | 7 - .../CronScheduler}/cron-scheduler-dialog.tsx | 2 +- .../CronScheduler}/cron-scheduler.tsx | 0 .../AgentInfoStep/AgentInfoStep.tsx | 2 +- .../services/feature-flags/use-get-flag.ts | 2 - 19 files changed, 10 insertions(+), 2195 deletions(-) rename autogpt_platform/frontend/src/app/(platform)/{library/agents/[id]/components/OldAgentLibraryView/components => build/components/legacy-builder}/agent-run-draft-view.tsx (99%) rename autogpt_platform/frontend/src/app/(platform)/{library/agents/[id]/components/OldAgentLibraryView/components => build/components/legacy-builder}/agent-status-chip.tsx (100%) delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/OldAgentLibraryView.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-details-view.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-output-view.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-status-chip.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-summary-card.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-runs-selector-list.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-schedule-details-view.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/create-preset-dialog.tsx delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/use-agent-runs.ts delete mode 100644 autogpt_platform/frontend/src/app/(platform)/library/legacy/[id]/page.tsx rename autogpt_platform/frontend/src/{app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components => components/contextual/CronScheduler}/cron-scheduler-dialog.tsx (97%) rename autogpt_platform/frontend/src/{app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components => components/contextual/CronScheduler}/cron-scheduler.tsx (100%) diff --git a/autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunGraph/useRunGraph.ts b/autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunGraph/useRunGraph.ts index 6980e95f11..51bb57057f 100644 --- a/autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunGraph/useRunGraph.ts +++ b/autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunGraph/useRunGraph.ts @@ -4,7 +4,7 @@ import { } from "@/app/api/__generated__/endpoints/graphs/graphs"; import { useToast } from "@/components/molecules/Toast/use-toast"; import { parseAsInteger, parseAsString, useQueryStates } from "nuqs"; -import { GraphExecutionMeta } from "@/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/use-agent-runs"; +import { GraphExecutionMeta } from "@/app/api/__generated__/models/graphExecutionMeta"; import { useGraphStore } from "@/app/(platform)/build/stores/graphStore"; import { useShallow } from "zustand/react/shallow"; import { useEffect, useState } from "react"; diff --git a/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/RunnerInputUI.tsx b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/RunnerInputUI.tsx index cb06a79683..f7d59a5693 100644 --- a/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/RunnerInputUI.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/RunnerInputUI.tsx @@ -1,6 +1,6 @@ import { useCallback } from "react"; -import { AgentRunDraftView } from "@/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-draft-view"; +import { AgentRunDraftView } from "@/app/(platform)/build/components/legacy-builder/agent-run-draft-view"; import { Dialog } from "@/components/molecules/Dialog/Dialog"; import type { CredentialsMetaInput, diff --git a/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/SaveControl.tsx b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/SaveControl.tsx index dcaa0f6264..3ee5217354 100644 --- a/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/SaveControl.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/SaveControl.tsx @@ -18,7 +18,7 @@ import { import { useToast } from "@/components/molecules/Toast/use-toast"; import { useQueryClient } from "@tanstack/react-query"; import { getGetV2ListMySubmissionsQueryKey } from "@/app/api/__generated__/endpoints/store/store"; -import { CronExpressionDialog } from "@/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/cron-scheduler-dialog"; +import { CronExpressionDialog } from "@/components/contextual/CronScheduler/cron-scheduler-dialog"; import { humanizeCronExpression } from "@/lib/cron-expression-utils"; import { CalendarClockIcon } from "lucide-react"; diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-draft-view.tsx b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/agent-run-draft-view.tsx similarity index 99% rename from autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-draft-view.tsx rename to autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/agent-run-draft-view.tsx index b0c3a6ff7b..372d479299 100644 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-draft-view.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/agent-run-draft-view.tsx @@ -20,7 +20,7 @@ import { import { useBackendAPI } from "@/lib/autogpt-server-api/context"; import { RunAgentInputs } from "@/app/(platform)/library/agents/[id]/components/NewAgentLibraryView/components/modals/RunAgentInputs/RunAgentInputs"; -import { ScheduleTaskDialog } from "@/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/cron-scheduler-dialog"; +import { ScheduleTaskDialog } from "@/components/contextual/CronScheduler/cron-scheduler-dialog"; import ActionButtonGroup from "@/components/__legacy__/action-button-group"; import type { ButtonAction } from "@/components/__legacy__/types"; import { @@ -53,7 +53,10 @@ import { ClockIcon, CopyIcon, InfoIcon } from "@phosphor-icons/react"; import { CalendarClockIcon, Trash2Icon } from "lucide-react"; import { analytics } from "@/services/analytics"; -import { AgentStatus, AgentStatusChip } from "./agent-status-chip"; +import { + AgentStatus, + AgentStatusChip, +} from "@/app/(platform)/build/components/legacy-builder/agent-status-chip"; export function AgentRunDraftView({ graph, diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-status-chip.tsx b/autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/agent-status-chip.tsx similarity index 100% rename from autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-status-chip.tsx rename to autogpt_platform/frontend/src/app/(platform)/build/components/legacy-builder/agent-status-chip.tsx diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/OldAgentLibraryView.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/OldAgentLibraryView.tsx deleted file mode 100644 index 54cc07878d..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/OldAgentLibraryView.tsx +++ /dev/null @@ -1,631 +0,0 @@ -"use client"; -import { useParams, useRouter } from "next/navigation"; -import { useQueryState } from "nuqs"; -import React, { - useCallback, - useEffect, - useMemo, - useRef, - useState, -} from "react"; - -import { - Graph, - GraphExecution, - GraphExecutionID, - GraphExecutionMeta, - GraphID, - LibraryAgent, - LibraryAgentID, - LibraryAgentPreset, - LibraryAgentPresetID, - Schedule, - ScheduleID, -} from "@/lib/autogpt-server-api"; -import { useBackendAPI } from "@/lib/autogpt-server-api/context"; -import { exportAsJSONFile } from "@/lib/utils"; - -import DeleteConfirmDialog from "@/components/__legacy__/delete-confirm-dialog"; -import type { ButtonAction } from "@/components/__legacy__/types"; -import { Button } from "@/components/__legacy__/ui/button"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/__legacy__/ui/dialog"; -import LoadingBox, { LoadingSpinner } from "@/components/__legacy__/ui/loading"; -import { - useToast, - useToastOnFail, -} from "@/components/molecules/Toast/use-toast"; -import { AgentRunDetailsView } from "./components/agent-run-details-view"; -import { AgentRunDraftView } from "./components/agent-run-draft-view"; -import { CreatePresetDialog } from "./components/create-preset-dialog"; -import { useAgentRunsInfinite } from "./use-agent-runs"; -import { AgentRunsSelectorList } from "./components/agent-runs-selector-list"; -import { AgentScheduleDetailsView } from "./components/agent-schedule-details-view"; - -export function OldAgentLibraryView() { - const { id: agentID }: { id: LibraryAgentID } = useParams(); - const [executionId, setExecutionId] = useQueryState("executionId"); - const toastOnFail = useToastOnFail(); - const { toast } = useToast(); - const router = useRouter(); - const api = useBackendAPI(); - - // ============================ STATE ============================= - - const [graph, setGraph] = useState(null); // Graph version corresponding to LibraryAgent - const [agent, setAgent] = useState(null); - const agentRunsQuery = useAgentRunsInfinite(graph?.id); // only runs once graph.id is known - const agentRuns = agentRunsQuery.agentRuns; - const [agentPresets, setAgentPresets] = useState([]); - const [schedules, setSchedules] = useState([]); - const [selectedView, selectView] = useState< - | { type: "run"; id?: GraphExecutionID } - | { type: "preset"; id: LibraryAgentPresetID } - | { type: "schedule"; id: ScheduleID } - >({ type: "run" }); - const [selectedRun, setSelectedRun] = useState< - GraphExecution | GraphExecutionMeta | null - >(null); - const selectedSchedule = - selectedView.type == "schedule" - ? schedules.find((s) => s.id == selectedView.id) - : null; - const [isFirstLoad, setIsFirstLoad] = useState(true); - const [agentDeleteDialogOpen, setAgentDeleteDialogOpen] = - useState(false); - const [confirmingDeleteAgentRun, setConfirmingDeleteAgentRun] = - useState(null); - const [confirmingDeleteAgentPreset, setConfirmingDeleteAgentPreset] = - useState(null); - const [copyAgentDialogOpen, setCopyAgentDialogOpen] = useState(false); - const [creatingPresetFromExecutionID, setCreatingPresetFromExecutionID] = - useState(null); - - // Set page title with agent name - useEffect(() => { - if (agent) { - document.title = `${agent.name} - Library - AutoGPT Platform`; - } - }, [agent]); - - const openRunDraftView = useCallback(() => { - selectView({ type: "run" }); - }, []); - - const selectRun = useCallback((id: GraphExecutionID) => { - selectView({ type: "run", id }); - }, []); - - const selectPreset = useCallback((id: LibraryAgentPresetID) => { - selectView({ type: "preset", id }); - }, []); - - const selectSchedule = useCallback((id: ScheduleID) => { - selectView({ type: "schedule", id }); - }, []); - - const graphVersions = useRef>({}); - const loadingGraphVersions = useRef>>({}); - const getGraphVersion = useCallback( - async (graphID: GraphID, version: number) => { - if (version in graphVersions.current) - return graphVersions.current[version]; - if (version in loadingGraphVersions.current) - return loadingGraphVersions.current[version]; - - const pendingGraph = api.getGraph(graphID, version).then((graph) => { - graphVersions.current[version] = graph; - return graph; - }); - // Cache promise as well to avoid duplicate requests - loadingGraphVersions.current[version] = pendingGraph; - return pendingGraph; - }, - [api, graphVersions, loadingGraphVersions], - ); - - const lastRefresh = useRef(0); - const refreshPageData = useCallback(() => { - if (Date.now() - lastRefresh.current < 2e3) return; // 2 second debounce - lastRefresh.current = Date.now(); - - api.getLibraryAgent(agentID).then((agent) => { - setAgent(agent); - - getGraphVersion(agent.graph_id, agent.graph_version).then( - (_graph) => - (graph && graph.version == _graph.version) || setGraph(_graph), - ); - Promise.all([ - agentRunsQuery.refetchRuns(), - api.listLibraryAgentPresets({ - graph_id: agent.graph_id, - page_size: 100, - }), - ]).then(([runsQueryResult, presets]) => { - setAgentPresets(presets.presets); - - const newestAgentRunsResponse = runsQueryResult.data?.pages[0]; - if (!newestAgentRunsResponse || newestAgentRunsResponse.status != 200) - return; - const newestAgentRuns = newestAgentRunsResponse.data.executions; - // Preload the corresponding graph versions for the latest 10 runs - new Set( - newestAgentRuns.slice(0, 10).map((run) => run.graph_version), - ).forEach((version) => getGraphVersion(agent.graph_id, version)); - }); - }); - }, [api, agentID, getGraphVersion, graph]); - - // On first load: select the latest run - useEffect(() => { - // Only for first load or first execution - if (selectedView.id || !isFirstLoad) return; - if (agentRuns.length == 0 && agentPresets.length == 0) return; - - setIsFirstLoad(false); - if (agentRuns.length > 0) { - // select latest run - const latestRun = agentRuns.reduce((latest, current) => { - if (!latest.started_at && !current.started_at) return latest; - if (!latest.started_at) return current; - if (!current.started_at) return latest; - return latest.started_at > current.started_at ? latest : current; - }, agentRuns[0]); - selectRun(latestRun.id as GraphExecutionID); - } else { - // select top preset - const latestPreset = agentPresets.toSorted( - (a, b) => b.updated_at.getTime() - a.updated_at.getTime(), - )[0]; - selectPreset(latestPreset.id); - } - }, [ - isFirstLoad, - selectedView.id, - agentRuns, - agentPresets, - selectRun, - selectPreset, - ]); - - useEffect(() => { - if (executionId) { - selectRun(executionId as GraphExecutionID); - setExecutionId(null); - } - }, [executionId, selectRun, setExecutionId]); - - // Initial load - useEffect(() => { - refreshPageData(); - - // Show a toast when the WebSocket connection disconnects - let connectionToast: ReturnType | null = null; - const cancelDisconnectHandler = api.onWebSocketDisconnect(() => { - connectionToast ??= toast({ - title: "Connection to server was lost", - variant: "destructive", - description: ( -
- Trying to reconnect... - -
- ), - duration: Infinity, - dismissable: true, - }); - }); - const cancelConnectHandler = api.onWebSocketConnect(() => { - if (connectionToast) - connectionToast.update({ - id: connectionToast.id, - title: "βœ… Connection re-established", - variant: "default", - description: ( -
- Refreshing data... - -
- ), - duration: 2000, - dismissable: true, - }); - connectionToast = null; - }); - return () => { - cancelDisconnectHandler(); - cancelConnectHandler(); - }; - }, []); - - // Subscribe to WebSocket updates for agent runs - useEffect(() => { - if (!agent?.graph_id) return; - - return api.onWebSocketConnect(() => { - refreshPageData(); // Sync up on (re)connect - - // Subscribe to all executions for this agent - api.subscribeToGraphExecutions(agent.graph_id); - }); - }, [api, agent?.graph_id, refreshPageData]); - - // Handle execution updates - useEffect(() => { - const detachExecUpdateHandler = api.onWebSocketMessage( - "graph_execution_event", - (data) => { - if (data.graph_id != agent?.graph_id) return; - - agentRunsQuery.upsertAgentRun(data); - if (data.id === selectedView.id) { - // Update currently viewed run - setSelectedRun(data); - } - }, - ); - - return () => { - detachExecUpdateHandler(); - }; - }, [api, agent?.graph_id, selectedView.id]); - - // Pre-load selectedRun based on selectedView - useEffect(() => { - if (selectedView.type != "run" || !selectedView.id) return; - - const newSelectedRun = agentRuns.find((run) => run.id == selectedView.id); - if (selectedView.id !== selectedRun?.id) { - // Pull partial data from "cache" while waiting for the rest to load - setSelectedRun((newSelectedRun as GraphExecutionMeta) ?? null); - } - }, [api, selectedView, agentRuns, selectedRun?.id]); - - // Load selectedRun based on selectedView; refresh on agent refresh - useEffect(() => { - if (selectedView.type != "run" || !selectedView.id || !agent) return; - - api - .getGraphExecutionInfo(agent.graph_id, selectedView.id) - .then(async (run) => { - // Ensure corresponding graph version is available before rendering I/O - await getGraphVersion(run.graph_id, run.graph_version); - setSelectedRun(run); - }); - }, [api, selectedView, agent, getGraphVersion]); - - const fetchSchedules = useCallback(async () => { - if (!agent) return; - - setSchedules(await api.listGraphExecutionSchedules(agent.graph_id)); - }, [api, agent?.graph_id]); - - useEffect(() => { - fetchSchedules(); - }, [fetchSchedules]); - - // =========================== ACTIONS ============================ - - const deleteRun = useCallback( - async (run: GraphExecutionMeta) => { - if (run.status == "RUNNING" || run.status == "QUEUED") { - await api.stopGraphExecution(run.graph_id, run.id); - } - await api.deleteGraphExecution(run.id); - - setConfirmingDeleteAgentRun(null); - if (selectedView.type == "run" && selectedView.id == run.id) { - openRunDraftView(); - } - agentRunsQuery.removeAgentRun(run.id); - }, - [api, selectedView, openRunDraftView], - ); - - const deletePreset = useCallback( - async (presetID: LibraryAgentPresetID) => { - await api.deleteLibraryAgentPreset(presetID); - - setConfirmingDeleteAgentPreset(null); - if (selectedView.type == "preset" && selectedView.id == presetID) { - openRunDraftView(); - } - setAgentPresets((presets) => presets.filter((p) => p.id !== presetID)); - }, - [api, selectedView, openRunDraftView], - ); - - const deleteSchedule = useCallback( - async (scheduleID: ScheduleID) => { - const removedSchedule = - await api.deleteGraphExecutionSchedule(scheduleID); - - setSchedules((schedules) => { - const newSchedules = schedules.filter( - (s) => s.id !== removedSchedule.id, - ); - if ( - selectedView.type == "schedule" && - selectedView.id == removedSchedule.id - ) { - if (newSchedules.length > 0) { - // Select next schedule if available - selectSchedule(newSchedules[0].id); - } else { - // Reset to draft view if current schedule was deleted - openRunDraftView(); - } - } - return newSchedules; - }); - openRunDraftView(); - }, - [schedules, api], - ); - - const handleCreatePresetFromRun = useCallback( - async (name: string, description: string) => { - if (!creatingPresetFromExecutionID) return; - - await api - .createLibraryAgentPreset({ - name, - description, - graph_execution_id: creatingPresetFromExecutionID, - }) - .then((preset) => { - setAgentPresets((prev) => [...prev, preset]); - selectPreset(preset.id); - setCreatingPresetFromExecutionID(null); - }) - .catch(toastOnFail("create a preset")); - }, - [api, creatingPresetFromExecutionID, selectPreset, toast], - ); - - const downloadGraph = useCallback( - async () => - agent && - // Export sanitized graph from backend - api - .getGraph(agent.graph_id, agent.graph_version, true) - .then((graph) => - exportAsJSONFile(graph, `${graph.name}_v${graph.version}.json`), - ), - [api, agent], - ); - - const copyAgent = useCallback(async () => { - setCopyAgentDialogOpen(false); - api - .forkLibraryAgent(agentID) - .then((newAgent) => { - router.push(`/library/agents/${newAgent.id}`); - }) - .catch((error) => { - console.error("Error copying agent:", error); - toast({ - title: "Error copying agent", - description: `An error occurred while copying the agent: ${error.message}`, - variant: "destructive", - }); - }); - }, [agentID, api, router, toast]); - - const agentActions: ButtonAction[] = useMemo( - () => [ - { - label: "Customize agent", - href: `/build?flowID=${agent?.graph_id}&flowVersion=${agent?.graph_version}`, - disabled: !agent?.can_access_graph, - }, - { label: "Export agent to file", callback: downloadGraph }, - ...(!agent?.can_access_graph - ? [ - { - label: "Edit a copy", - callback: () => setCopyAgentDialogOpen(true), - }, - ] - : []), - { - label: "Delete agent", - callback: () => setAgentDeleteDialogOpen(true), - }, - ], - [agent, downloadGraph], - ); - - const runGraph = - graphVersions.current[selectedRun?.graph_version ?? 0] ?? graph; - - const onCreateSchedule = useCallback( - (schedule: Schedule) => { - setSchedules((prev) => [...prev, schedule]); - selectSchedule(schedule.id); - }, - [selectView], - ); - - const onCreatePreset = useCallback( - (preset: LibraryAgentPreset) => { - setAgentPresets((prev) => [...prev, preset]); - selectPreset(preset.id); - }, - [selectPreset], - ); - - const onUpdatePreset = useCallback( - (updated: LibraryAgentPreset) => { - setAgentPresets((prev) => - prev.map((p) => (p.id === updated.id ? updated : p)), - ); - selectPreset(updated.id); - }, - [selectPreset], - ); - - if (!agent || !graph) { - return ; - } - - return ( -
- {/* Sidebar w/ list of runs */} - {/* TODO: render this below header in sm and md layouts */} - - -
- {/* Header */} -
-

- { - agent.name /* TODO: use dynamic/custom run title - https://github.com/Significant-Gravitas/AutoGPT/issues/9184 */ - } -

-
- - {/* Run / Schedule views */} - {(selectedView.type == "run" && selectedView.id ? ( - selectedRun && runGraph ? ( - setConfirmingDeleteAgentRun(selectedRun)} - doCreatePresetFromRun={() => - setCreatingPresetFromExecutionID(selectedRun.id) - } - /> - ) : null - ) : selectedView.type == "run" ? ( - /* Draft new runs / Create new presets */ - - ) : selectedView.type == "preset" ? ( - /* Edit & update presets */ - preset.id == selectedView.id)! - } - onRun={selectRun} - recommendedScheduleCron={agent?.recommended_schedule_cron || null} - onCreateSchedule={onCreateSchedule} - onUpdatePreset={onUpdatePreset} - doDeletePreset={setConfirmingDeleteAgentPreset} - agentActions={agentActions} - /> - ) : selectedView.type == "schedule" ? ( - selectedSchedule && - graph && ( - - ) - ) : null) || } - - - agent && - api.deleteLibraryAgent(agent.id).then(() => router.push("/library")) - } - /> - - !open && setConfirmingDeleteAgentRun(null)} - onDoDelete={() => - confirmingDeleteAgentRun && deleteRun(confirmingDeleteAgentRun) - } - /> - !open && setConfirmingDeleteAgentPreset(null)} - onDoDelete={() => - confirmingDeleteAgentPreset && - deletePreset(confirmingDeleteAgentPreset) - } - /> - {/* Copy agent confirmation dialog */} - - - - You're making an editable copy - - The original Marketplace agent stays the same and cannot be - edited. We'll save a new version of this agent to your - Library. From there, you can customize it however you'd - like by clicking "Customize agent" β€” this will open - the builder where you can see and modify the inner workings. - - - - - - - - - setCreatingPresetFromExecutionID(null)} - onConfirm={handleCreatePresetFromRun} - /> -
-
- ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-details-view.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-details-view.tsx deleted file mode 100644 index eb5224c958..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-details-view.tsx +++ /dev/null @@ -1,445 +0,0 @@ -"use client"; -import { format, formatDistanceToNow, formatDistanceStrict } from "date-fns"; -import React, { useCallback, useMemo, useEffect } from "react"; - -import { - Graph, - GraphExecution, - GraphExecutionID, - GraphExecutionMeta, - LibraryAgent, -} from "@/lib/autogpt-server-api"; -import { useBackendAPI } from "@/lib/autogpt-server-api/context"; - -import ActionButtonGroup from "@/components/__legacy__/action-button-group"; -import type { ButtonAction } from "@/components/__legacy__/types"; -import { - Card, - CardContent, - CardHeader, - CardTitle, -} from "@/components/__legacy__/ui/card"; -import { - IconRefresh, - IconSquare, - IconCircleAlert, -} from "@/components/__legacy__/ui/icons"; -import { Input } from "@/components/__legacy__/ui/input"; -import LoadingBox from "@/components/__legacy__/ui/loading"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/atoms/Tooltip/BaseTooltip"; -import { useToastOnFail } from "@/components/molecules/Toast/use-toast"; - -import { AgentRunStatus, agentRunStatusMap } from "./agent-run-status-chip"; -import useCredits from "@/hooks/useCredits"; -import { AgentRunOutputView } from "./agent-run-output-view"; -import { analytics } from "@/services/analytics"; -import { PendingReviewsList } from "@/components/organisms/PendingReviewsList/PendingReviewsList"; -import { usePendingReviewsForExecution } from "@/hooks/usePendingReviews"; - -export function AgentRunDetailsView({ - agent, - graph, - run, - agentActions, - onRun, - doDeleteRun, - doCreatePresetFromRun, -}: { - agent: LibraryAgent; - graph: Graph; - run: GraphExecution | GraphExecutionMeta; - agentActions: ButtonAction[]; - onRun: (runID: GraphExecutionID) => void; - doDeleteRun: () => void; - doCreatePresetFromRun: () => void; -}): React.ReactNode { - const api = useBackendAPI(); - const { formatCredits } = useCredits(); - - const runStatus: AgentRunStatus = useMemo( - () => agentRunStatusMap[run.status], - [run], - ); - - const { - pendingReviews, - isLoading: reviewsLoading, - refetch: refetchReviews, - } = usePendingReviewsForExecution(run.id); - - const toastOnFail = useToastOnFail(); - - // Refetch pending reviews when execution status changes to REVIEW - useEffect(() => { - if (runStatus === "review" && run.id) { - refetchReviews(); - } - }, [runStatus, run.id, refetchReviews]); - - const infoStats: { label: string; value: React.ReactNode }[] = useMemo(() => { - if (!run) return []; - return [ - { - label: "Status", - value: runStatus.charAt(0).toUpperCase() + runStatus.slice(1), - }, - { - label: "Started", - value: run.started_at - ? `${formatDistanceToNow(run.started_at, { addSuffix: true })}, ${format(run.started_at, "HH:mm")}` - : "β€”", - }, - ...(run.stats - ? [ - { - label: "Duration", - value: formatDistanceStrict(0, run.stats.duration * 1000), - }, - { label: "Steps", value: run.stats.node_exec_count }, - { label: "Cost", value: formatCredits(run.stats.cost) }, - ] - : []), - ]; - }, [run, runStatus, formatCredits]); - - const agentRunInputs: - | Record< - string, - { - title?: string; - /* type: BlockIOSubType; */ - value: string | number | undefined; - } - > - | undefined = useMemo(() => { - if (!run.inputs) return undefined; - // TODO: show (link to) preset - https://github.com/Significant-Gravitas/AutoGPT/issues/9168 - - // Add type info from agent input schema - return Object.fromEntries( - Object.entries(run.inputs).map(([k, v]) => [ - k, - { - title: graph.input_schema.properties[k]?.title, - // type: graph.input_schema.properties[k].type, // TODO: implement typed graph inputs - value: typeof v == "object" ? JSON.stringify(v, undefined, 2) : v, - }, - ]), - ); - }, [graph, run]); - - const runAgain = useCallback(() => { - if ( - !run.inputs || - !(graph.credentials_input_schema?.required ?? []).every( - (k) => k in (run.credential_inputs ?? {}), - ) - ) - return; - - if (run.preset_id) { - return api - .executeLibraryAgentPreset( - run.preset_id, - run.inputs!, - run.credential_inputs!, - ) - .then(({ id }) => { - analytics.sendDatafastEvent("run_agent", { - name: graph.name, - id: graph.id, - }); - onRun(id); - }) - .catch(toastOnFail("execute agent preset")); - } - - return api - .executeGraph( - graph.id, - graph.version, - run.inputs!, - run.credential_inputs!, - "library", - ) - .then(({ id }) => { - analytics.sendDatafastEvent("run_agent", { - name: graph.name, - id: graph.id, - }); - onRun(id); - }) - .catch(toastOnFail("execute agent")); - }, [api, graph, run, onRun, toastOnFail]); - - const stopRun = useCallback( - () => api.stopGraphExecution(graph.id, run.id), - [api, graph.id, run.id], - ); - - const agentRunOutputs: - | Record< - string, - { - title?: string; - /* type: BlockIOSubType; */ - values: Array; - } - > - | null - | undefined = useMemo(() => { - if (!("outputs" in run)) return undefined; - if (!["running", "success", "failed", "stopped"].includes(runStatus)) - return null; - - // Add type info from agent input schema - return Object.fromEntries( - Object.entries(run.outputs).map(([k, vv]) => [ - k, - { - title: graph.output_schema.properties[k].title, - /* type: agent.output_schema.properties[k].type */ - values: vv.map((v) => - typeof v == "object" ? JSON.stringify(v, undefined, 2) : v, - ), - }, - ]), - ); - }, [graph, run, runStatus]); - - const runActions: ButtonAction[] = useMemo( - () => [ - ...(["running", "queued"].includes(runStatus) - ? ([ - { - label: ( - <> - - Stop run - - ), - variant: "secondary", - callback: stopRun, - }, - ] satisfies ButtonAction[]) - : []), - ...(["success", "failed", "stopped"].includes(runStatus) && - !graph.has_external_trigger && - (graph.credentials_input_schema?.required ?? []).every( - (k) => k in (run.credential_inputs ?? {}), - ) - ? [ - { - label: ( - <> - - Run again - - ), - callback: runAgain, - dataTestId: "run-again-button", - }, - ] - : []), - ...(agent.can_access_graph - ? [ - { - label: "Open run in builder", - href: `/build?flowID=${run.graph_id}&flowVersion=${run.graph_version}&flowExecutionID=${run.id}`, - }, - ] - : []), - { label: "Create preset from run", callback: doCreatePresetFromRun }, - { label: "Delete run", variant: "secondary", callback: doDeleteRun }, - ], - [ - runStatus, - runAgain, - stopRun, - doDeleteRun, - doCreatePresetFromRun, - graph.has_external_trigger, - graph.credentials_input_schema?.required, - agent.can_access_graph, - run.graph_id, - run.graph_version, - run.id, - ], - ); - - return ( -
-
- - - Info - - - -
- {infoStats.map(({ label, value }) => ( -
-

{label}

-

{value}

-
- ))} -
- {run.status === "FAILED" && ( -
-

- Error:{" "} - {run.stats?.error || - "The execution failed due to an internal error. You can re-run the agent to retry."} -

-
- )} -
-
- - {/* Smart Agent Execution Summary */} - {run.stats?.activity_status && ( - - - - Task Summary - - - - - - -

- This AI-generated summary describes how the agent - handled your task. It’s an experimental feature and may - occasionally be inaccurate. -

-
-
-
-
-
- -

- {run.stats.activity_status} -

- - {/* Correctness Score */} - {typeof run.stats.correctness_score === "number" && ( -
-
- - Success Estimate: - -
-
-
= 0.8 - ? "bg-green-500" - : run.stats.correctness_score >= 0.6 - ? "bg-yellow-500" - : run.stats.correctness_score >= 0.4 - ? "bg-orange-500" - : "bg-red-500" - }`} - style={{ - width: `${Math.round(run.stats.correctness_score * 100)}%`, - }} - /> -
- - {Math.round(run.stats.correctness_score * 100)}% - -
-
- - - - - - -

- AI-generated estimate of how well this execution - achieved its intended purpose. This score indicates - {run.stats.correctness_score >= 0.8 - ? " the agent was highly successful." - : run.stats.correctness_score >= 0.6 - ? " the agent was mostly successful with minor issues." - : run.stats.correctness_score >= 0.4 - ? " the agent was partially successful with some gaps." - : " the agent had limited success with significant issues."} -

-
-
-
-
- )} - - - )} - - {agentRunOutputs !== null && ( - - )} - - {/* Pending Reviews Section */} - {runStatus === "review" && ( - - - - Pending Reviews ({pendingReviews.length}) - - - - {reviewsLoading ? ( - - ) : pendingReviews.length > 0 ? ( - - ) : ( -
- No pending reviews for this execution -
- )} -
-
- )} - - - - Input - - - {agentRunInputs !== undefined ? ( - Object.entries(agentRunInputs).map(([key, { title, value }]) => ( -
- - -
- )) - ) : ( - - )} -
-
-
- - {/* Run / Agent Actions */} - -
- ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-output-view.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-output-view.tsx deleted file mode 100644 index 668ac2e215..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-output-view.tsx +++ /dev/null @@ -1,178 +0,0 @@ -"use client"; - -import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag"; -import React, { useMemo } from "react"; - -import { - Card, - CardContent, - CardHeader, - CardTitle, -} from "@/components/__legacy__/ui/card"; - -import LoadingBox from "@/components/__legacy__/ui/loading"; -import type { OutputMetadata } from "../../../../../../../../components/contextual/OutputRenderers"; -import { - globalRegistry, - OutputActions, - OutputItem, -} from "../../../../../../../../components/contextual/OutputRenderers"; - -export function AgentRunOutputView({ - agentRunOutputs, -}: { - agentRunOutputs: - | Record< - string, - { - title?: string; - /* type: BlockIOSubType; */ - values: Array; - } - > - | undefined; -}) { - const enableEnhancedOutputHandling = useGetFlag( - Flag.ENABLE_ENHANCED_OUTPUT_HANDLING, - ); - - // Prepare items for the renderer system - const outputItems = useMemo(() => { - if (!agentRunOutputs) return []; - - const items: Array<{ - key: string; - label: string; - value: unknown; - metadata?: OutputMetadata; - renderer: any; - }> = []; - - Object.entries(agentRunOutputs).forEach(([key, { title, values }]) => { - values.forEach((value, index) => { - // Enhanced metadata extraction - const metadata: OutputMetadata = {}; - - // Type guard to safely access properties - if ( - typeof value === "object" && - value !== null && - !React.isValidElement(value) - ) { - const objValue = value as any; - if (objValue.type) metadata.type = objValue.type; - if (objValue.mimeType) metadata.mimeType = objValue.mimeType; - if (objValue.filename) metadata.filename = objValue.filename; - } - - const renderer = globalRegistry.getRenderer(value, metadata); - if (renderer) { - items.push({ - key: `${key}-${index}`, - label: index === 0 ? title || key : "", - value, - metadata, - renderer, - }); - } else { - const textRenderer = globalRegistry - .getAllRenderers() - .find((r) => r.name === "TextRenderer"); - if (textRenderer) { - items.push({ - key: `${key}-${index}`, - label: index === 0 ? title || key : "", - value: JSON.stringify(value, null, 2), - metadata, - renderer: textRenderer, - }); - } - } - }); - }); - - return items; - }, [agentRunOutputs]); - - return ( - <> - {enableEnhancedOutputHandling ? ( - - -
- Output - {outputItems.length > 0 && ( - ({ - value: item.value, - metadata: item.metadata, - renderer: item.renderer, - }))} - /> - )} -
-
- - - {agentRunOutputs !== undefined ? ( - outputItems.length > 0 ? ( - outputItems.map((item) => ( - - )) - ) : ( -

- No outputs to display -

- ) - ) : ( - - )} -
-
- ) : ( - - - Output - - - - {agentRunOutputs !== undefined ? ( - Object.entries(agentRunOutputs).map( - ([key, { title, values }]) => ( -
- - {values.map((value, i) => ( -

- {value} -

- ))} - {/* TODO: pretty type-dependent rendering */} -
- ), - ) - ) : ( - - )} -
-
- )} - - ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-status-chip.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-status-chip.tsx deleted file mode 100644 index 58f1ee8381..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-status-chip.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from "react"; - -import { Badge } from "@/components/__legacy__/ui/badge"; - -import { GraphExecutionMeta } from "@/lib/autogpt-server-api/types"; - -export type AgentRunStatus = - | "success" - | "failed" - | "queued" - | "running" - | "stopped" - | "scheduled" - | "draft" - | "review"; - -export const agentRunStatusMap: Record< - GraphExecutionMeta["status"], - AgentRunStatus -> = { - INCOMPLETE: "draft", - COMPLETED: "success", - FAILED: "failed", - QUEUED: "queued", - RUNNING: "running", - TERMINATED: "stopped", - REVIEW: "review", -}; - -const statusData: Record< - AgentRunStatus, - { label: string; variant: keyof typeof statusStyles } -> = { - success: { label: "Success", variant: "success" }, - running: { label: "Running", variant: "info" }, - failed: { label: "Failed", variant: "destructive" }, - queued: { label: "Queued", variant: "warning" }, - draft: { label: "Draft", variant: "secondary" }, - stopped: { label: "Stopped", variant: "secondary" }, - scheduled: { label: "Scheduled", variant: "secondary" }, - review: { label: "In Review", variant: "warning" }, -}; - -const statusStyles = { - success: - "bg-green-100 text-green-800 hover:bg-green-100 hover:text-green-800", - destructive: "bg-red-100 text-red-800 hover:bg-red-100 hover:text-red-800", - warning: - "bg-yellow-100 text-yellow-800 hover:bg-yellow-100 hover:text-yellow-800", - info: "bg-blue-100 text-blue-800 hover:bg-blue-100 hover:text-blue-800", - secondary: - "bg-slate-100 text-slate-800 hover:bg-slate-100 hover:text-slate-800", -}; - -export function AgentRunStatusChip({ - status, -}: { - status: AgentRunStatus; -}): React.ReactElement { - return ( - - {statusData[status]?.label} - - ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-summary-card.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-summary-card.tsx deleted file mode 100644 index 6f7d7865bc..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-run-summary-card.tsx +++ /dev/null @@ -1,130 +0,0 @@ -import React from "react"; -import { formatDistanceToNow, isPast } from "date-fns"; - -import { cn } from "@/lib/utils"; - -import { Link2Icon, Link2OffIcon, MoreVertical } from "lucide-react"; -import { Card, CardContent } from "@/components/__legacy__/ui/card"; -import { Button } from "@/components/__legacy__/ui/button"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/__legacy__/ui/dropdown-menu"; - -import { AgentStatus, AgentStatusChip } from "./agent-status-chip"; -import { AgentRunStatus, AgentRunStatusChip } from "./agent-run-status-chip"; -import { PushPinSimpleIcon } from "@phosphor-icons/react"; - -export type AgentRunSummaryProps = ( - | { - type: "run"; - status: AgentRunStatus; - } - | { - type: "preset"; - status?: undefined; - } - | { - type: "preset.triggered"; - status: AgentStatus; - } - | { - type: "schedule"; - status: "scheduled"; - } -) & { - title: string; - timestamp?: number | Date; - selected?: boolean; - onClick?: () => void; - // onRename: () => void; - onDelete: () => void; - onPinAsPreset?: () => void; - className?: string; -}; - -export function AgentRunSummaryCard({ - type, - status, - title, - timestamp, - selected = false, - onClick, - // onRename, - onDelete, - onPinAsPreset, - className, -}: AgentRunSummaryProps): React.ReactElement { - return ( - - - {(type == "run" || type == "schedule") && ( - - )} - {type == "preset" && ( -
- Preset -
- )} - {type == "preset.triggered" && ( -
- - -
- {status == "inactive" ? ( - - ) : ( - - )}{" "} - Trigger -
-
- )} - -
-

- {title} -

- - - - - - - {onPinAsPreset && ( - - Pin as a preset - - )} - - {/* Rename */} - - Delete - - -
- - {timestamp && ( -

- {isPast(timestamp) ? "Ran" : "Runs in"}{" "} - {formatDistanceToNow(timestamp, { addSuffix: true })} -

- )} -
-
- ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-runs-selector-list.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-runs-selector-list.tsx deleted file mode 100644 index 49d93b4319..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-runs-selector-list.tsx +++ /dev/null @@ -1,237 +0,0 @@ -"use client"; -import { Plus } from "lucide-react"; -import React, { useEffect, useState } from "react"; - -import { - GraphExecutionID, - GraphExecutionMeta, - LibraryAgent, - LibraryAgentPreset, - LibraryAgentPresetID, - Schedule, - ScheduleID, -} from "@/lib/autogpt-server-api"; -import { cn } from "@/lib/utils"; - -import { Badge } from "@/components/__legacy__/ui/badge"; -import { Button } from "@/components/atoms/Button/Button"; -import LoadingBox, { LoadingSpinner } from "@/components/__legacy__/ui/loading"; -import { Separator } from "@/components/__legacy__/ui/separator"; -import { ScrollArea } from "@/components/__legacy__/ui/scroll-area"; -import { InfiniteScroll } from "@/components/contextual/InfiniteScroll/InfiniteScroll"; -import { AgentRunsQuery } from "../use-agent-runs"; -import { agentRunStatusMap } from "./agent-run-status-chip"; -import { AgentRunSummaryCard } from "./agent-run-summary-card"; - -interface AgentRunsSelectorListProps { - agent: LibraryAgent; - agentRunsQuery: AgentRunsQuery; - agentPresets: LibraryAgentPreset[]; - schedules: Schedule[]; - selectedView: { type: "run" | "preset" | "schedule"; id?: string }; - allowDraftNewRun?: boolean; - onSelectRun: (id: GraphExecutionID) => void; - onSelectPreset: (preset: LibraryAgentPresetID) => void; - onSelectSchedule: (id: ScheduleID) => void; - onSelectDraftNewRun: () => void; - doDeleteRun: (id: GraphExecutionMeta) => void; - doDeletePreset: (id: LibraryAgentPresetID) => void; - doDeleteSchedule: (id: ScheduleID) => void; - doCreatePresetFromRun?: (id: GraphExecutionID) => void; - className?: string; -} - -export function AgentRunsSelectorList({ - agent, - agentRunsQuery: { - agentRuns, - agentRunCount, - agentRunsLoading, - hasMoreRuns, - fetchMoreRuns, - isFetchingMoreRuns, - }, - agentPresets, - schedules, - selectedView, - allowDraftNewRun = true, - onSelectRun, - onSelectPreset, - onSelectSchedule, - onSelectDraftNewRun, - doDeleteRun, - doDeletePreset, - doDeleteSchedule, - doCreatePresetFromRun, - className, -}: AgentRunsSelectorListProps): React.ReactElement { - const [activeListTab, setActiveListTab] = useState<"runs" | "scheduled">( - "runs", - ); - - useEffect(() => { - if (selectedView.type === "schedule") { - setActiveListTab("scheduled"); - } else { - setActiveListTab("runs"); - } - }, [selectedView]); - - const listItemClasses = "h-28 w-72 lg:w-full lg:h-32"; - - return ( - - ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-schedule-details-view.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-schedule-details-view.tsx deleted file mode 100644 index 30b0a82e65..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/agent-schedule-details-view.tsx +++ /dev/null @@ -1,180 +0,0 @@ -"use client"; -import React, { useCallback, useMemo } from "react"; - -import { - Graph, - GraphExecutionID, - Schedule, - ScheduleID, -} from "@/lib/autogpt-server-api"; -import { useBackendAPI } from "@/lib/autogpt-server-api/context"; - -import ActionButtonGroup from "@/components/__legacy__/action-button-group"; -import type { ButtonAction } from "@/components/__legacy__/types"; -import { - Card, - CardContent, - CardHeader, - CardTitle, -} from "@/components/__legacy__/ui/card"; -import { IconCross } from "@/components/__legacy__/ui/icons"; -import { Input } from "@/components/__legacy__/ui/input"; -import LoadingBox from "@/components/__legacy__/ui/loading"; -import { useToastOnFail } from "@/components/molecules/Toast/use-toast"; -import { humanizeCronExpression } from "@/lib/cron-expression-utils"; -import { formatScheduleTime } from "@/lib/timezone-utils"; -import { useUserTimezone } from "@/lib/hooks/useUserTimezone"; -import { PlayIcon } from "lucide-react"; - -import { AgentRunStatus } from "./agent-run-status-chip"; - -export function AgentScheduleDetailsView({ - graph, - schedule, - agentActions, - onForcedRun, - doDeleteSchedule, -}: { - graph: Graph; - schedule: Schedule; - agentActions: ButtonAction[]; - onForcedRun: (runID: GraphExecutionID) => void; - doDeleteSchedule: (scheduleID: ScheduleID) => void; -}): React.ReactNode { - const api = useBackendAPI(); - - const selectedRunStatus: AgentRunStatus = "scheduled"; - - const toastOnFail = useToastOnFail(); - - // Get user's timezone for displaying schedule times - const userTimezone = useUserTimezone(); - - const infoStats: { label: string; value: React.ReactNode }[] = useMemo(() => { - return [ - { - label: "Status", - value: - selectedRunStatus.charAt(0).toUpperCase() + - selectedRunStatus.slice(1), - }, - { - label: "Schedule", - value: humanizeCronExpression(schedule.cron), - }, - { - label: "Next run", - value: formatScheduleTime(schedule.next_run_time, userTimezone), - }, - ]; - }, [schedule, selectedRunStatus, userTimezone]); - - const agentRunInputs: Record< - string, - { title?: string; /* type: BlockIOSubType; */ value: any } - > = useMemo(() => { - // TODO: show (link to) preset - https://github.com/Significant-Gravitas/AutoGPT/issues/9168 - - // Add type info from agent input schema - return Object.fromEntries( - Object.entries(schedule.input_data).map(([k, v]) => [ - k, - { - title: graph.input_schema.properties[k].title, - /* TODO: type: agent.input_schema.properties[k].type */ - value: v, - }, - ]), - ); - }, [graph, schedule]); - - const runNow = useCallback( - () => - api - .executeGraph( - graph.id, - graph.version, - schedule.input_data, - schedule.input_credentials, - "library", - ) - .then((run) => onForcedRun(run.id)) - .catch(toastOnFail("execute agent")), - [api, graph, schedule, onForcedRun, toastOnFail], - ); - - const runActions: ButtonAction[] = useMemo( - () => [ - { - label: ( - <> - - Run now - - ), - callback: runNow, - }, - { - label: ( - <> - - Delete schedule - - ), - callback: () => doDeleteSchedule(schedule.id), - variant: "destructive", - }, - ], - [runNow], - ); - - return ( -
-
- - - Info - - - -
- {infoStats.map(({ label, value }) => ( -
-

{label}

-

{value}

-
- ))} -
-
-
- - - - Input - - - {agentRunInputs !== undefined ? ( - Object.entries(agentRunInputs).map(([key, { title, value }]) => ( -
- - -
- )) - ) : ( - - )} -
-
-
- - {/* Run / Agent Actions */} - -
- ); -} diff --git a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/create-preset-dialog.tsx b/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/create-preset-dialog.tsx deleted file mode 100644 index 2ca64d5ec5..0000000000 --- a/autogpt_platform/frontend/src/app/(platform)/library/agents/[id]/components/OldAgentLibraryView/components/create-preset-dialog.tsx +++ /dev/null @@ -1,100 +0,0 @@ -"use client"; - -import React, { useState } from "react"; -import { Button } from "@/components/__legacy__/ui/button"; -import { - Dialog, - DialogContent, - DialogDescription, - DialogFooter, - DialogHeader, - DialogTitle, -} from "@/components/__legacy__/ui/dialog"; -import { Input } from "@/components/__legacy__/ui/input"; -import { Textarea } from "@/components/__legacy__/ui/textarea"; - -interface CreatePresetDialogProps { - open: boolean; - onOpenChange: (open: boolean) => void; - onConfirm: (name: string, description: string) => Promise | void; -} - -export function CreatePresetDialog({ - open, - onOpenChange, - onConfirm, -}: CreatePresetDialogProps) { - const [name, setName] = useState(""); - const [description, setDescription] = useState(""); - - const handleSubmit = async () => { - if (name.trim()) { - await onConfirm(name.trim(), description.trim()); - setName(""); - setDescription(""); - onOpenChange(false); - } - }; - - const handleCancel = () => { - setName(""); - setDescription(""); - onOpenChange(false); - }; - - const handleKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { - e.preventDefault(); - handleSubmit(); - } - }; - - return ( - - - - Create Preset - - Give your preset a name and description to help identify it later. - - -
-
- - setName(e.target.value)} - onKeyDown={handleKeyDown} - autoFocus - /> -
-
- -