Skip to content

Commit e64d3d9

Browse files
authored
feat(frontend): implement agent outputs viewer and improve UI/UX in new builder (#11421)
This PR introduces several improvements to the new builder experience: **1. Agent Outputs Feature** ✨ - Implemented a new `AgentOutputs` component that displays execution outputs from OUTPUT blocks - Added a slide-out sheet UI to view agent outputs with proper formatting - Integrated with existing output renderers from the library view - Shows output block names, descriptions, and rendered values - Added beta badge to indicate feature is still experimental **2. UI/UX Improvements** 🎨 - Fixed graph loading spinner color from violet to neutral zinc for better consistency - Adjusted node shadow styling for better visual hierarchy (reduced shadow when not selected) - Fixed credential field button spacing to prevent layout overflow - Improved array editor widget delete button positioning - Added proper link handling for integration redirects (opens in new tab) - Fixed object editor to handle null values gracefully **3. Performance & State Management** 🚀 - Fixed race condition in run input dialog by awaiting execution before closing - Added proper history initialization after graph loads - Added `outputSchema` to graph store for tracking output blocks - Fixed search bar to maintain query state properly - Added automatic fit view on graph load for better initial viewport **4. Build Actions Bar** 🔧 - Reduced padding for more compact appearance - Enabled/disabled Agent Outputs button based on presence of output blocks - Removed loading icon from manual run button when not executing ### 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] Created and executed an agent with OUTPUT blocks to verify outputs display correctly - [x] Tested output viewer with different data types (text, JSON, images, etc.) - [x] Verified credential field layouts don't overflow in constrained spaces - [x] Tested array editor delete functionality and button positioning - [x] Confirmed graph loads with proper fit view and history initialization - [x] Tested run input dialog closes only after execution starts - [x] Verified integration links open in new tabs - [x] Tested object editor with null values
1 parent 41dc39b commit e64d3d9

File tree

22 files changed

+1772
-74
lines changed

22 files changed

+1772
-74
lines changed

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/BuilderActions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export const BuilderActions = memo(() => {
99
flowID: parseAsString,
1010
});
1111
return (
12-
<div className="absolute bottom-4 left-[50%] z-[100] flex -translate-x-1/2 items-center gap-4 rounded-full bg-white p-2 px-4 shadow-lg">
12+
<div className="absolute bottom-4 left-[50%] z-[100] flex -translate-x-1/2 items-center gap-4 rounded-full bg-white p-2 px-2 shadow-lg">
1313
<AgentOutputs flowID={flowID} />
1414
<RunGraph flowID={flowID} />
1515
<ScheduleGraph flowID={flowID} />

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/AgentOutputs/AgentOutputs.tsx

Lines changed: 119 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,25 +4,138 @@ import {
44
TooltipProvider,
55
TooltipTrigger,
66
} from "@/components/atoms/Tooltip/BaseTooltip";
7+
import {
8+
Sheet,
9+
SheetContent,
10+
SheetDescription,
11+
SheetHeader,
12+
SheetTitle,
13+
SheetTrigger,
14+
} from "@/components/__legacy__/ui/sheet";
715
import { BuilderActionButton } from "../BuilderActionButton";
816
import { BookOpenIcon } from "@phosphor-icons/react";
17+
import { useGraphStore } from "@/app/(platform)/build/stores/graphStore";
18+
import { useShallow } from "zustand/react/shallow";
19+
import { useNodeStore } from "@/app/(platform)/build/stores/nodeStore";
20+
import { BlockUIType } from "@/app/(platform)/build/components/types";
21+
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
22+
import { Label } from "@/components/__legacy__/ui/label";
23+
import { useMemo } from "react";
24+
import {
25+
globalRegistry,
26+
OutputItem,
27+
OutputActions,
28+
} from "@/app/(platform)/library/agents/[id]/components/AgentRunsView/components/OutputRenderers";
929

1030
export const AgentOutputs = ({ flowID }: { flowID: string | null }) => {
31+
const hasOutputs = useGraphStore(useShallow((state) => state.hasOutputs));
32+
const nodes = useNodeStore(useShallow((state) => state.nodes));
33+
34+
const outputs = useMemo(() => {
35+
const outputNodes = nodes.filter(
36+
(node) => node.data.uiType === BlockUIType.OUTPUT,
37+
);
38+
39+
return outputNodes
40+
.map((node) => {
41+
const executionResult = node.data.nodeExecutionResult;
42+
const outputData = executionResult?.output_data?.output;
43+
44+
const renderer = globalRegistry.getRenderer(outputData);
45+
46+
return {
47+
metadata: {
48+
name: node.data.hardcodedValues?.name || "Output",
49+
description:
50+
node.data.hardcodedValues?.description || "Output from the agent",
51+
},
52+
value: outputData ?? "No output yet",
53+
renderer,
54+
};
55+
})
56+
.filter(
57+
(
58+
output,
59+
): output is typeof output & {
60+
renderer: NonNullable<typeof output.renderer>;
61+
} => output.renderer !== null,
62+
);
63+
}, [nodes]);
64+
65+
const actionItems = useMemo(() => {
66+
return outputs.map((output) => ({
67+
value: output.value,
68+
metadata: {},
69+
renderer: output.renderer,
70+
}));
71+
}, [outputs]);
72+
1173
return (
12-
<>
74+
<Sheet>
1375
<TooltipProvider>
1476
<Tooltip>
1577
<TooltipTrigger asChild>
16-
{/* Todo: Implement Agent Outputs */}
17-
<BuilderActionButton disabled={!flowID}>
18-
<BookOpenIcon className="size-6" />
19-
</BuilderActionButton>
78+
<SheetTrigger asChild>
79+
<BuilderActionButton disabled={!flowID || !hasOutputs()}>
80+
<BookOpenIcon className="size-6" />
81+
</BuilderActionButton>
82+
</SheetTrigger>
2083
</TooltipTrigger>
2184
<TooltipContent>
2285
<p>Agent Outputs</p>
2386
</TooltipContent>
2487
</Tooltip>
2588
</TooltipProvider>
26-
</>
89+
<SheetContent className="flex h-full w-full flex-col overflow-hidden sm:max-w-[600px]">
90+
<SheetHeader className="px-2 py-2">
91+
<div className="flex items-center justify-between">
92+
<div>
93+
<SheetTitle className="text-xl">Run Outputs</SheetTitle>
94+
<SheetDescription className="mt-1 text-sm text-muted-foreground">
95+
<span className="inline-flex items-center gap-1.5">
96+
<span className="rounded-md bg-yellow-100 px-2 py-0.5 text-xs font-medium text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400">
97+
Beta
98+
</span>
99+
<span>This feature is in beta and may contain bugs</span>
100+
</span>
101+
</SheetDescription>
102+
</div>
103+
{outputs.length > 0 && <OutputActions items={actionItems} />}
104+
</div>
105+
</SheetHeader>
106+
<div className="flex-grow overflow-y-auto px-2 py-2">
107+
<ScrollArea className="h-full overflow-auto pr-4">
108+
<div className="space-y-6">
109+
{outputs && outputs.length > 0 ? (
110+
outputs.map((output, i) => (
111+
<div key={i} className="space-y-2">
112+
<div>
113+
<Label className="text-base font-semibold">
114+
{output.metadata.name || "Unnamed Output"}
115+
</Label>
116+
{output.metadata.description && (
117+
<Label className="mt-1 block text-sm text-gray-600">
118+
{output.metadata.description}
119+
</Label>
120+
)}
121+
</div>
122+
123+
<OutputItem
124+
value={output.value}
125+
metadata={{}}
126+
renderer={output.renderer}
127+
/>
128+
</div>
129+
))
130+
) : (
131+
<div className="flex h-full items-center justify-center text-gray-500">
132+
<p>No output blocks available.</p>
133+
</div>
134+
)}
135+
</div>
136+
</ScrollArea>
137+
</div>
138+
</SheetContent>
139+
</Sheet>
27140
);
28141
};

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/RunInputDialog.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ export const RunInputDialog = ({
105105
onClick={handleManualRun}
106106
loading={isExecutingGraph}
107107
>
108-
<PlayIcon className="size-5 transition-transform group-hover:scale-110" />
108+
{!isExecutingGraph && (
109+
<PlayIcon className="size-5 transition-transform group-hover:scale-110" />
110+
)}
109111
<span className="font-semibold">Manual Run</span>
110112
</Button>
111113
)}

autogpt_platform/frontend/src/app/(platform)/build/components/BuilderActions/components/RunInputDialog/useRunInputDialog.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,13 @@ export const useRunInputDialog = ({
7878
return dynamicUiSchema;
7979
}, [credentialsSchema]);
8080

81-
const handleManualRun = () => {
82-
setIsOpen(false);
83-
executeGraph({
81+
const handleManualRun = async () => {
82+
await executeGraph({
8483
graphId: flowID ?? "",
8584
graphVersion: flowVersion || null,
8685
data: { inputs: inputValues, credentials_inputs: credentialValues },
8786
});
87+
setIsOpen(false);
8888
};
8989

9090
const handleInputChange = (inputValues: Record<string, any>) => {

0 commit comments

Comments
 (0)