Skip to content

Commit cf9cf4e

Browse files
authored
refactor(frontend): Move OttoChatWidget out of root layout (#9951)
- Resolves #9950 ### Changes 🏗️ - Move `<OttoChatWidget>` from root layout into `FlowEditor` - Pass graph info directly into `OttoChatWidget` instead of using `useAgentGraph` - Rearrange z-indices of elements in the builder ### 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: - Go to `/build` - [x] -> chat widget should show up in the bottom right corner - Open the widget and ask Otto something - [x] -> should work normally - Add a few blocks and save the graph - [x] -> "Include graph data" should show up - Click "Include graph data" and ask Otto something about your graph - [x] -> Otto should be aware of the graph structure and metadata
1 parent 0a79e1c commit cf9cf4e

File tree

5 files changed

+49
-34
lines changed

5 files changed

+49
-34
lines changed

autogpt_platform/frontend/src/app/layout.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import "./globals.css";
1010
import { Toaster } from "@/components/ui/toaster";
1111
import { Providers } from "@/app/providers";
1212
import TallyPopupSimple from "@/components/TallyPopup";
13-
import OttoChatWidget from "@/components/OttoChatWidget";
1413
import { GoogleAnalytics } from "@/components/analytics/google-analytics";
1514

1615
const inter = Inter({ subsets: ["latin"], variable: "--font-inter" });
@@ -57,9 +56,6 @@ export default async function RootLayout({
5756
<div className="flex min-h-screen flex-col items-stretch justify-items-stretch">
5857
{children}
5958
<TallyPopupSimple />
60-
<Suspense fallback={null}>
61-
<OttoChatWidget />
62-
</Suspense>
6359
</div>
6460
<Toaster />
6561
</Providers>

autogpt_platform/frontend/src/components/Flow.tsx

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"use client";
22
import React, {
3+
createContext,
34
useState,
45
useCallback,
56
useEffect,
67
useRef,
78
MouseEvent,
8-
createContext,
9+
Suspense,
910
} from "react";
1011
import {
1112
ReactFlow,
@@ -48,6 +49,7 @@ import RunnerUIWrapper, {
4849
RunnerUIWrapperRef,
4950
} from "@/components/RunnerUIWrapper";
5051
import PrimaryActionBar from "@/components/PrimaryActionButton";
52+
import OttoChatWidget from "@/components/OttoChatWidget";
5153
import { useToast } from "@/components/ui/use-toast";
5254
import { useCopyPaste } from "../hooks/useCopyPaste";
5355
import { CronScheduler } from "./cronScheduler";
@@ -676,7 +678,7 @@ const FlowEditor: React.FC<{
676678
<Controls />
677679
<Background className="dark:bg-slate-800" />
678680
<ControlPanel
679-
className="absolute z-10"
681+
className="absolute z-20"
680682
controls={editorControls}
681683
topChildren={
682684
<BlocksControl
@@ -701,6 +703,7 @@ const FlowEditor: React.FC<{
701703
}
702704
></ControlPanel>
703705
<PrimaryActionBar
706+
className="absolute bottom-0 left-1/2 z-20 -translate-x-1/2"
704707
onClickAgentOutputs={() => runnerUIRef.current?.openRunnerOutput()}
705708
onClickRunAgent={() => {
706709
if (!savedAgent) {
@@ -740,6 +743,12 @@ const FlowEditor: React.FC<{
740743
scheduleRunner={scheduleRunner}
741744
requestSaveAndRun={requestSaveAndRun}
742745
/>
746+
<Suspense fallback={null}>
747+
<OttoChatWidget
748+
graphID={flowID}
749+
className="fixed bottom-4 right-4 z-20"
750+
/>
751+
</Suspense>
743752
</FlowContext.Provider>
744753
);
745754
};

autogpt_platform/frontend/src/components/OttoChatWidget.tsx

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
11
"use client";
22

33
import React, { useEffect, useState, useRef } from "react";
4-
import { useSearchParams, usePathname } from "next/navigation";
5-
import { useToast } from "@/components/ui/use-toast";
6-
import useAgentGraph from "../hooks/useAgentGraph";
74
import ReactMarkdown from "react-markdown";
8-
import { GraphID } from "@/lib/autogpt-server-api/types";
5+
6+
import type { GraphID } from "@/lib/autogpt-server-api/types";
97
import { askOtto } from "@/app/(platform)/build/actions";
8+
import { cn } from "@/lib/utils";
109

1110
interface Message {
1211
type: "user" | "assistant";
1312
content: string;
1413
}
1514

16-
const OttoChatWidget = () => {
15+
export default function OttoChatWidget({
16+
graphID,
17+
className,
18+
}: {
19+
graphID?: GraphID;
20+
className?: string;
21+
}): React.ReactNode {
1722
const [isOpen, setIsOpen] = useState(false);
1823
const [messages, setMessages] = useState<Message[]>([]);
1924
const [inputValue, setInputValue] = useState("");
2025
const [isProcessing, setIsProcessing] = useState(false);
2126
const [includeGraphData, setIncludeGraphData] = useState(false);
2227
const messagesEndRef = useRef<HTMLDivElement>(null);
23-
const searchParams = useSearchParams();
24-
const pathname = usePathname();
25-
const flowID = searchParams.get("flowID");
26-
const { nodes, edges } = useAgentGraph(
27-
flowID ? (flowID as GraphID) : undefined,
28-
);
29-
const { toast } = useToast();
3028

3129
useEffect(() => {
3230
// Add welcome message when component mounts
3331
if (messages.length === 0) {
3432
setMessages([
3533
{
3634
type: "assistant",
37-
content: "Hello im Otto! Ask me anything about AutoGPT!",
35+
content: "Hello, I am Otto! Ask me anything about AutoGPT!",
3836
},
3937
]);
4038
}
@@ -84,7 +82,7 @@ const OttoChatWidget = () => {
8482
userMessage,
8583
conversationHistory,
8684
includeGraphData,
87-
flowID || undefined,
85+
graphID,
8886
);
8987

9088
// Check if the response contains an error
@@ -131,13 +129,13 @@ const OttoChatWidget = () => {
131129
};
132130

133131
// Don't render the chat widget if we're not on the build page or in local mode
134-
if (process.env.NEXT_PUBLIC_BEHAVE_AS !== "CLOUD" || pathname !== "/build") {
132+
if (process.env.NEXT_PUBLIC_BEHAVE_AS !== "CLOUD") {
135133
return null;
136134
}
137135

138136
if (!isOpen) {
139137
return (
140-
<div className="fixed bottom-4 right-4 z-50">
138+
<div className={className}>
141139
<button
142140
onClick={() => setIsOpen(true)}
143141
className="inline-flex h-14 w-14 items-center justify-center whitespace-nowrap rounded-2xl bg-[rgba(65,65,64,1)] text-neutral-50 shadow transition-colors hover:bg-neutral-900/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-neutral-950 disabled:pointer-events-none disabled:opacity-50 dark:bg-neutral-50 dark:text-neutral-900 dark:hover:bg-neutral-50/90 dark:focus-visible:ring-neutral-300"
@@ -160,7 +158,13 @@ const OttoChatWidget = () => {
160158
}
161159

162160
return (
163-
<div className="fixed bottom-4 right-4 z-50 flex h-[600px] w-[600px] flex-col rounded-lg border bg-background shadow-xl">
161+
<div
162+
className={cn(
163+
"flex h-[600px] w-[600px] flex-col rounded-lg border bg-background shadow-xl",
164+
className,
165+
"z-40",
166+
)}
167+
>
164168
{/* Header */}
165169
<div className="flex items-center justify-between border-b p-4">
166170
<h2 className="font-semibold">Otto Assistant</h2>
@@ -269,7 +273,7 @@ const OttoChatWidget = () => {
269273
Send
270274
</button>
271275
</div>
272-
{nodes && edges && (
276+
{graphID && (
273277
<button
274278
type="button"
275279
onClick={() => {
@@ -303,6 +307,4 @@ const OttoChatWidget = () => {
303307
</form>
304308
</div>
305309
);
306-
};
307-
308-
export default OttoChatWidget;
310+
}

autogpt_platform/frontend/src/components/PrimaryActionButton.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import React, { useState } from "react";
2-
import { Button } from "./ui/button";
3-
import { Clock, LogOut, ChevronLeft } from "lucide-react";
1+
import React from "react";
2+
import { cn } from "@/lib/utils";
3+
import { Button } from "@/components/ui/button";
4+
import { FaSpinner } from "react-icons/fa";
5+
import { Clock, LogOut } from "lucide-react";
46
import { IconPlay, IconSquare } from "@/components/ui/icons";
57
import {
68
Tooltip,
79
TooltipContent,
810
TooltipTrigger,
911
} from "@/components/ui/tooltip";
10-
import { FaSpinner } from "react-icons/fa";
1112

1213
interface PrimaryActionBarProps {
1314
onClickAgentOutputs: () => void;
@@ -18,6 +19,7 @@ interface PrimaryActionBarProps {
1819
isScheduling: boolean;
1920
requestStopRun: () => void;
2021
runAgentTooltip: string;
22+
className?: string;
2123
}
2224

2325
const PrimaryActionBar: React.FC<PrimaryActionBarProps> = ({
@@ -29,6 +31,7 @@ const PrimaryActionBar: React.FC<PrimaryActionBarProps> = ({
2931
isScheduling,
3032
requestStopRun,
3133
runAgentTooltip,
34+
className,
3235
}) => {
3336
const runButtonLabel = !isRunning ? "Run" : "Stop";
3437

@@ -37,8 +40,13 @@ const PrimaryActionBar: React.FC<PrimaryActionBarProps> = ({
3740
const runButtonOnClick = !isRunning ? onClickRunAgent : requestStopRun;
3841

3942
return (
40-
<div className="absolute bottom-0 left-1/2 z-50 flex w-fit -translate-x-1/2 transform select-none items-center justify-center p-4">
41-
<div className={`flex gap-1 md:gap-4`}>
43+
<div
44+
className={cn(
45+
"flex w-fit select-none items-center justify-center p-4",
46+
className,
47+
)}
48+
>
49+
<div className="flex gap-1 md:gap-4">
4250
<Tooltip key="ViewOutputs" delayDuration={500}>
4351
<TooltipTrigger asChild>
4452
<Button

autogpt_platform/frontend/src/components/TallyPopup.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const TallyPopupSimple = () => {
5656
};
5757

5858
return (
59-
<div className="fixed bottom-1 right-24 z-50 hidden select-none items-center gap-4 p-3 transition-all duration-300 ease-in-out md:flex">
59+
<div className="fixed bottom-1 right-24 z-20 hidden select-none items-center gap-4 p-3 transition-all duration-300 ease-in-out md:flex">
6060
{show_tutorial && (
6161
<Button
6262
variant="default"

0 commit comments

Comments
 (0)