Skip to content

Commit

Permalink
Merge branch 'dev' into ntindle/open-1864-add-user-creationlogin-test…
Browse files Browse the repository at this point in the history
…s-and-utilites
  • Loading branch information
Torantulino authored Nov 20, 2024
2 parents 02528e5 + cf43248 commit 0e4e1bc
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ const RunnerUIWrapper = forwardRef<RunnerUIWrapperRef, RunnerUIWrapperProps>(
const outputs = outputBlocks.map((node) => ({
id: node.id,
type: "output" as const,
outputSchema: node.data.outputSchema as BlockIORootSchema,
hardcodedValues: {
name: (node.data.hardcodedValues as any).name || "Output",
description:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { Block, BlockUIType } from "@/lib/autogpt-server-api";
import { Block, BlockUIType, SpecialBlockID } from "@/lib/autogpt-server-api";
import { MagnifyingGlassIcon, PlusIcon } from "@radix-ui/react-icons";
import { IconToyBrick } from "@/components/ui/icons";
import { getPrimaryCategoryColor } from "@/lib/utils";
Expand Down Expand Up @@ -57,7 +57,7 @@ export const BlocksControl: React.FC<BlocksControlProps> = ({
const agentList = flows.map(
(flow) =>
({
id: "e189baac-8c20-45a1-94a7-55177ea42565", // TODO: fetch this programmatically.
id: SpecialBlockID.AGENT,
name: flow.name,
description:
`Ver.${flow.version}` +
Expand Down
174 changes: 125 additions & 49 deletions autogpt_platform/frontend/src/components/monitor/FlowRunInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,79 +1,155 @@
import React, { useCallback } from "react";
import AutoGPTServerAPI, { GraphMeta } from "@/lib/autogpt-server-api";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import AutoGPTServerAPI, {
BlockIORootSchema,
Graph,
GraphMeta,
NodeExecutionResult,
SpecialBlockID,
} from "@/lib/autogpt-server-api";
import { FlowRun } from "@/lib/types";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import Link from "next/link";
import { Button, buttonVariants } from "@/components/ui/button";
import { IconSquare } from "@/components/ui/icons";
import { Pencil2Icon } from "@radix-ui/react-icons";
import { ExitIcon, Pencil2Icon } from "@radix-ui/react-icons";
import moment from "moment/moment";
import { FlowRunStatusBadge } from "@/components/monitor/FlowRunStatusBadge";
import RunnerOutputUI, { BlockOutput } from "../runner-ui/RunnerOutputUI";

export const FlowRunInfo: React.FC<
React.HTMLAttributes<HTMLDivElement> & {
flow: GraphMeta;
flowRun: FlowRun;
}
> = ({ flow, flowRun, ...props }) => {
const [isOutputOpen, setIsOutputOpen] = useState(false);
const [blockOutputs, setBlockOutputs] = useState<BlockOutput[]>([]);
const api = useMemo(() => new AutoGPTServerAPI(), []);

const fetchBlockResults = useCallback(async () => {
const executionResults = await api.getGraphExecutionInfo(
flow.id,
flowRun.id,
);

// Create a map of the latest COMPLETED execution results of output nodes by node_id
const latestCompletedResults = executionResults
.filter(
(result) =>
result.status === "COMPLETED" &&
result.block_id === SpecialBlockID.OUTPUT,
)
.reduce((acc, result) => {
const existing = acc.get(result.node_id);

// Compare dates if there's an existing result
if (existing) {
const existingDate = existing.end_time || existing.add_time;
const currentDate = result.end_time || result.add_time;

if (currentDate > existingDate) {
acc.set(result.node_id, result);
}
} else {
acc.set(result.node_id, result);
}

return acc;
}, new Map<string, NodeExecutionResult>());

// Transform results to BlockOutput format
setBlockOutputs(
Array.from(latestCompletedResults.values()).map((result) => ({
id: result.node_id,
type: "output" as const,
hardcodedValues: {
name: result.input_data.name || "Output",
description: result.input_data.description || "Output from the agent",
value: result.input_data.value,
},
// Change this line to extract the array directly
result: result.output_data?.output || undefined,
})),
);
}, [api, flow.id, flow.version, flowRun.id]);

// Fetch graph and execution data
useEffect(() => {
if (!isOutputOpen || blockOutputs.length > 0) {
return;
}

fetchBlockResults();
}, [isOutputOpen, blockOutputs]);

if (flowRun.graphID != flow.id) {
throw new Error(
`FlowRunInfo can't be used with non-matching flowRun.flowID and flow.id`,
);
}

const handleStopRun = useCallback(() => {
const api = new AutoGPTServerAPI();
api.stopGraphExecution(flow.id, flowRun.id);
}, [flow.id, flowRun.id]);

return (
<Card {...props}>
<CardHeader className="flex-row items-center justify-between space-x-3 space-y-0">
<div>
<CardTitle>
{flow.name} <span className="font-light">v{flow.version}</span>
</CardTitle>
<p className="mt-2">
Agent ID: <code>{flow.id}</code>
<>
<Card {...props}>
<CardHeader className="flex-row items-center justify-between space-x-3 space-y-0">
<div>
<CardTitle>
{flow.name} <span className="font-light">v{flow.version}</span>
</CardTitle>
<p className="mt-2">
Agent ID: <code>{flow.id}</code>
</p>
<p className="mt-1">
Run ID: <code>{flowRun.id}</code>
</p>
</div>
<div className="flex space-x-2">
{flowRun.status === "running" && (
<Button onClick={handleStopRun} variant="destructive">
<IconSquare className="mr-2" /> Stop Run
</Button>
)}
<Button onClick={() => setIsOutputOpen(true)} variant="outline">
<ExitIcon className="mr-2" /> View Outputs
</Button>
<Link
className={buttonVariants({ variant: "default" })}
href={`/build?flowID=${flow.id}`}
>
<Pencil2Icon className="mr-2" /> Open in Builder
</Link>
</div>
</CardHeader>
<CardContent>
<div>
<strong>Status:</strong>{" "}
<FlowRunStatusBadge status={flowRun.status} />
</div>
<p>
<strong>Started:</strong>{" "}
{moment(flowRun.startTime).format("YYYY-MM-DD HH:mm:ss")}
</p>
<p className="mt-1">
Run ID: <code>{flowRun.id}</code>
<p>
<strong>Finished:</strong>{" "}
{moment(flowRun.endTime).format("YYYY-MM-DD HH:mm:ss")}
</p>
</div>
<div className="flex space-x-2">
{flowRun.status === "running" && (
<Button onClick={handleStopRun} variant="destructive">
<IconSquare className="mr-2" /> Stop Run
</Button>
)}
<Link
className={buttonVariants({ variant: "default" })}
href={`/build?flowID=${flow.id}`}
>
<Pencil2Icon className="mr-2" /> Open in Builder
</Link>
</div>
</CardHeader>
<CardContent>
<div>
<strong>Status:</strong>{" "}
<FlowRunStatusBadge status={flowRun.status} />
</div>
<p>
<strong>Started:</strong>{" "}
{moment(flowRun.startTime).format("YYYY-MM-DD HH:mm:ss")}
</p>
<p>
<strong>Finished:</strong>{" "}
{moment(flowRun.endTime).format("YYYY-MM-DD HH:mm:ss")}
</p>
<p>
<strong>Duration (run time):</strong> {flowRun.duration} (
{flowRun.totalRunTime}) seconds
</p>
{/* <p><strong>Total cost:</strong> €1,23</p> */}
</CardContent>
</Card>
<p>
<strong>Duration (run time):</strong> {flowRun.duration} (
{flowRun.totalRunTime}) seconds
</p>
</CardContent>
</Card>
<RunnerOutputUI
isOpen={isOutputOpen}
onClose={() => setIsOutputOpen(false)}
blockOutputs={blockOutputs}
/>
</>
);
};

export default FlowRunInfo;
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import { BlockIORootSchema } from "@/lib/autogpt-server-api/types";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";

interface BlockOutput {
export interface BlockOutput {
id: string;
outputSchema: BlockIORootSchema;
hardcodedValues: {
name: string;
description: string;
Expand Down
11 changes: 9 additions & 2 deletions autogpt_platform/frontend/src/lib/autogpt-server-api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,11 +241,12 @@ export type GraphExecuteResponse = {

/* Mirror of backend/data/execution.py:ExecutionResult */
export type NodeExecutionResult = {
graph_exec_id: string;
node_exec_id: string;
graph_id: string;
graph_version: number;
graph_exec_id: string;
node_exec_id: string;
node_id: string;
block_id: string;
status: "INCOMPLETE" | "QUEUED" | "RUNNING" | "COMPLETED" | "FAILED";
input_data: { [key: string]: any };
output_data: { [key: string]: Array<any> };
Expand Down Expand Up @@ -319,6 +320,12 @@ export enum BlockUIType {
AGENT = "Agent",
}

export enum SpecialBlockID {
AGENT = "e189baac-8c20-45a1-94a7-55177ea42565",
INPUT = "c0a8e994-ebf1-4a9c-a4d8-89d09c86741b",
OUTPUT = "363ae599-353e-4804-937e-b2ee3cef3da4",
}

export type AnalyticsMetrics = {
metric_name: string;
metric_value: number;
Expand Down

0 comments on commit 0e4e1bc

Please sign in to comment.