mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-04-08 03:00:28 -04:00
feat(frontend): use new output renderers on new run page (#10876)
## Changes 🏗️ Integrating the great work @ntindle did on the rich agent output renderers into the new Agent run page in the library 💜 - Implemented enhanced output rendering in `<RunDetails />` using the shared output-renderers - Added `<RunOutputs />` sub-component at `RunDetails/components/RunOutputs.tsx` that: - [x] builds items from `run.outputs`, extracts metadata, picks a renderer via `globalRegistry`, and falls back to `TextRenderer` - [x] renders `<OutputActions />` for copy/download and a list of `<OutputItems />`. ## Checklist 📋 ### For code changes: - [x] I have clearly listed my changes in the PR description - [x] I have made a test plan - [x] I have tested my changes according to the test plan: - [x] Run an agent on the view which outputs rich content - [x] See the output use the new renderers, for example code is higlighted ### For configuration changes: None
This commit is contained in:
@@ -14,6 +14,7 @@ import { ErrorCard } from "@/components/molecules/ErrorCard/ErrorCard";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import { AgentInputsReadOnly } from "../AgentInputsReadOnly/AgentInputsReadOnly";
|
||||
import { RunDetailCard } from "../RunDetailCard/RunDetailCard";
|
||||
import { RunOutputs } from "./components/RunOutputs";
|
||||
|
||||
interface RunDetailsProps {
|
||||
agent: LibraryAgent;
|
||||
@@ -74,28 +75,10 @@ export function RunDetails({
|
||||
<RunDetailCard>
|
||||
{isLoading ? (
|
||||
<div className="text-neutral-500">Loading…</div>
|
||||
) : !run ||
|
||||
!("outputs" in run) ||
|
||||
Object.keys(run.outputs || {}).length === 0 ? (
|
||||
<div className="text-neutral-600">No output from this run.</div>
|
||||
) : run && "outputs" in run ? (
|
||||
<RunOutputs outputs={run.outputs as any} />
|
||||
) : (
|
||||
<div className="flex flex-col gap-4">
|
||||
{Object.entries(run.outputs).map(([key, values]) => (
|
||||
<div key={key} className="flex flex-col gap-1.5">
|
||||
<label className="text-sm font-medium">{key}</label>
|
||||
{values.map((value, i) => (
|
||||
<p
|
||||
key={i}
|
||||
className="whitespace-pre-wrap break-words text-sm text-neutral-700"
|
||||
>
|
||||
{typeof value === "object"
|
||||
? JSON.stringify(value, undefined, 2)
|
||||
: String(value)}
|
||||
</p>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-neutral-600">No output from this run.</div>
|
||||
)}
|
||||
</RunDetailCard>
|
||||
</TabsLineContent>
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
"use client";
|
||||
|
||||
import React, { useMemo } from "react";
|
||||
import {
|
||||
globalRegistry,
|
||||
OutputItem,
|
||||
OutputActions,
|
||||
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
|
||||
import type {
|
||||
OutputMetadata,
|
||||
OutputRenderer,
|
||||
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
|
||||
|
||||
type OutputsRecord = Record<string, Array<unknown>>;
|
||||
|
||||
interface RunOutputsProps {
|
||||
outputs: OutputsRecord;
|
||||
}
|
||||
|
||||
export function RunOutputs({ outputs }: RunOutputsProps) {
|
||||
const items = useMemo(() => {
|
||||
const list: Array<{
|
||||
key: string;
|
||||
label: string;
|
||||
value: unknown;
|
||||
metadata?: OutputMetadata;
|
||||
renderer: OutputRenderer;
|
||||
}> = [];
|
||||
|
||||
Object.entries(outputs || {}).forEach(([key, values]) => {
|
||||
(values || []).forEach((value, index) => {
|
||||
const metadata: OutputMetadata = {};
|
||||
if (
|
||||
typeof value === "object" &&
|
||||
value !== null &&
|
||||
!React.isValidElement(value)
|
||||
) {
|
||||
const obj = value as Record<string, unknown>;
|
||||
if (typeof obj["type"] === "string")
|
||||
metadata.type = obj["type"] as string;
|
||||
if (typeof obj["mimeType"] === "string")
|
||||
metadata.mimeType = obj["mimeType"] as string;
|
||||
if (typeof obj["filename"] === "string")
|
||||
metadata.filename = obj["filename"] as string;
|
||||
if (typeof obj["language"] === "string")
|
||||
metadata.language = obj["language"] as string;
|
||||
}
|
||||
|
||||
const renderer = globalRegistry.getRenderer(value, metadata);
|
||||
if (renderer) {
|
||||
list.push({
|
||||
key: `${key}-${index}`,
|
||||
label: index === 0 ? key : "",
|
||||
value,
|
||||
metadata,
|
||||
renderer,
|
||||
});
|
||||
} else {
|
||||
const textRenderer = globalRegistry
|
||||
.getAllRenderers()
|
||||
.find((r) => r.name === "TextRenderer");
|
||||
if (textRenderer) {
|
||||
list.push({
|
||||
key: `${key}-${index}`,
|
||||
label: index === 0 ? key : "",
|
||||
value:
|
||||
typeof value === "string"
|
||||
? value
|
||||
: JSON.stringify(value, null, 2),
|
||||
metadata,
|
||||
renderer: textRenderer,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return list;
|
||||
}, [outputs]);
|
||||
|
||||
if (!items.length) {
|
||||
return <div className="text-neutral-600">No output from this run.</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<div className="flex items-center justify-end">
|
||||
<OutputActions
|
||||
items={items.map((item) => ({
|
||||
value: item.value,
|
||||
metadata: item.metadata,
|
||||
renderer: item.renderer,
|
||||
}))}
|
||||
/>
|
||||
</div>
|
||||
{items.map((item) => (
|
||||
<OutputItem
|
||||
key={item.key}
|
||||
value={item.value}
|
||||
metadata={item.metadata}
|
||||
renderer={item.renderer}
|
||||
label={item.label}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -6,8 +6,12 @@ import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
import LoadingBox from "@/components/ui/loading";
|
||||
import { globalRegistry, OutputItem, OutputActions } from "./output-renderers";
|
||||
import type { OutputMetadata } from "./output-renderers";
|
||||
import {
|
||||
globalRegistry,
|
||||
OutputItem,
|
||||
OutputActions,
|
||||
} from "../../AgentRunsView/components/OutputRenderers";
|
||||
import type { OutputMetadata } from "../../AgentRunsView/components/OutputRenderers";
|
||||
|
||||
export function AgentRunOutputView({
|
||||
agentRunOutputs,
|
||||
|
||||
Reference in New Issue
Block a user