Improve latest ss, add queued tasks view (#215)

This commit is contained in:
Kerem Yilmaz
2024-04-22 09:50:34 -07:00
committed by GitHub
parent 55d14db971
commit bb723bff34
6 changed files with 237 additions and 24 deletions

View File

@@ -17,6 +17,7 @@ export const Status = {
Failed: "failed",
Terminated: "terminated",
Completed: "completed",
Queued: "queued",
} as const;
export type Status = (typeof Status)[keyof typeof Status];

View File

@@ -24,6 +24,7 @@ import { cn } from "@/util/utils";
import { PAGE_SIZE } from "../constants";
import { StatusBadge } from "@/components/StatusBadge";
import { basicTimeFormat } from "@/util/timeFormat";
import { QueuedTasks } from "../running/QueuedTasks";
function TaskList() {
const navigate = useNavigate();
@@ -76,6 +77,8 @@ function TaskList() {
<div className="grid grid-cols-4 gap-4">
<RunningTasks />
</div>
<h1 className="text-2xl py-2 border-b-2">Queued Tasks</h1>
<QueuedTasks />
<h1 className="text-2xl py-2 border-b-2">Task History</h1>
<Table>
<TableHeader>

View File

@@ -5,8 +5,8 @@ import {
StepApiResponse,
} from "@/api/types";
import { Skeleton } from "@/components/ui/skeleton";
import { artifactApiBaseUrl } from "@/util/env";
import { useQuery } from "@tanstack/react-query";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { getImageURL } from "../detail/artifactUtils";
type Props = {
id: string;
@@ -14,10 +14,10 @@ type Props = {
function LatestScreenshot({ id }: Props) {
const {
data: screenshotUri,
data: artifact,
isFetching,
isError,
} = useQuery<string | undefined>({
} = useQuery<ArtifactApiResponse | undefined>({
queryKey: ["task", id, "latestScreenshot"],
queryFn: async () => {
const steps: StepApiResponse[] = await client
@@ -38,43 +38,39 @@ function LatestScreenshot({ id }: Props) {
.get(`/tasks/${id}/steps/${latestStep.step_id}/artifacts`)
.then((response) => response.data);
const actionScreenshotUris = artifacts
?.filter(
(artifact) =>
artifact.artifact_type === ArtifactType.ActionScreenshot,
)
.map((artifact) => artifact.uri);
const actionScreenshots = artifacts?.filter(
(artifact) => artifact.artifact_type === ArtifactType.ActionScreenshot,
);
if (actionScreenshotUris.length > 0) {
return actionScreenshotUris[0];
if (actionScreenshots.length > 0) {
return actionScreenshots[0];
}
const llmScreenshotUris = artifacts
?.filter(
(artifact) => artifact.artifact_type === ArtifactType.LLMScreenshot,
)
.map((artifact) => artifact.uri);
const llmScreenshots = artifacts?.filter(
(artifact) => artifact.artifact_type === ArtifactType.LLMScreenshot,
);
if (llmScreenshotUris.length > 0) {
return llmScreenshotUris[0];
if (llmScreenshots.length > 0) {
return llmScreenshots[0];
}
return Promise.reject("No screenshots found");
},
refetchInterval: 2000,
placeholderData: keepPreviousData,
});
if (isFetching) {
if (isFetching && !artifact) {
return <Skeleton className="w-full h-full" />;
}
if (isError || !screenshotUri || typeof screenshotUri !== "string") {
if (isError || !artifact) {
return null;
}
return (
<img
src={`${artifactApiBaseUrl}/artifact/image?path=${screenshotUri.slice(7)}`}
src={getImageURL(artifact)}
className="w-full h-full object-contain"
alt="Latest screenshot"
/>

View File

@@ -0,0 +1,71 @@
import { client } from "@/api/AxiosClient";
import { Status, TaskApiResponse } from "@/api/types";
import { keepPreviousData, useQuery } from "@tanstack/react-query";
import { basicTimeFormat } from "@/util/timeFormat";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import { useNavigate } from "react-router-dom";
import { StatusBadge } from "@/components/StatusBadge";
function QueuedTasks() {
const navigate = useNavigate();
const { data: tasks } = useQuery<Array<TaskApiResponse>>({
queryKey: ["tasks"],
queryFn: async () => {
return client.get("/tasks").then((response) => response.data);
},
refetchInterval: 3000,
placeholderData: keepPreviousData,
});
const queuedTasks = tasks
?.filter((task) => task.status === Status.Queued)
.slice(0, 10);
return (
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-1/3">URL</TableHead>
<TableHead className="w-1/3">Status</TableHead>
<TableHead className="w-1/3">Created At</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{queuedTasks?.length === 0 ? (
<TableRow>
<TableCell colSpan={3}>No queued tasks</TableCell>
</TableRow>
) : (
queuedTasks?.map((task) => {
return (
<TableRow
key={task.task_id}
className="cursor-pointer w-4"
onClick={() => {
navigate(task.task_id);
}}
>
<TableCell className="w-1/3">{task.request.url}</TableCell>
<TableCell className="w-1/3">
<StatusBadge status={task.status} />
</TableCell>
<TableCell className="w-1/3">
{basicTimeFormat(task.created_at)}
</TableCell>
</TableRow>
);
})
)}
</TableBody>
</Table>
);
}
export { QueuedTasks };