Skip to content

Commit 6239980

Browse files
committed
minor refactor, add settings pane
1 parent 0c17cdd commit 6239980

29 files changed

+412
-35
lines changed

python/packages/autogen-studio/frontend/src/components/sidebar.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ const Sidebar = ({ link, meta, isMobile }: SidebarProps) => {
220220
],
221221
})
222222
}
223-
className="group hidden flex gap-x-3 rounded-md p-2 text-sm font-medium text-primary hover:text-accent hover:bg-secondary justify-center"
223+
className="group flex gap-x-3 rounded-md p-2 text-sm font-medium text-primary hover:text-accent hover:bg-secondary justify-center"
224224
>
225225
<Settings className="h-6 w-6 shrink-0 text-secondary group-hover:text-accent" />
226226
</Link>
@@ -248,7 +248,7 @@ const Sidebar = ({ link, meta, isMobile }: SidebarProps) => {
248248
) : (
249249
<div className="flex items-center gap-2">
250250
<div className="w-full ">
251-
<div className="hidden">
251+
<div className="">
252252
{" "}
253253
<Link
254254
to="/settings"

python/packages/autogen-studio/frontend/src/components/views/atoms.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const TruncatableText = memo(
9191
<div className="relative">
9292
<div
9393
className={`
94-
transition-[max-height,opacity] overflow-auto duration-500 ease-in-out
94+
transition-[max-height,opacity] overflow-auto scroll duration-500 ease-in-out
9595
${
9696
shouldTruncate && !isExpanded
9797
? "max-h-[300px]"

python/packages/autogen-studio/frontend/src/components/views/session/chat/runview.tsx python/packages/autogen-studio/frontend/src/components/views/playground/chat/runview.tsx

+22-15
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
1-
import React, { useState, useRef, useEffect } from "react";
1+
import React, { useState, useRef, useEffect, useMemo } from "react";
22
import {
33
StopCircle,
44
MessageSquare,
55
Loader2,
66
CheckCircle,
77
AlertTriangle,
88
TriangleAlertIcon,
9-
GroupIcon,
109
ChevronDown,
1110
ChevronUp,
1211
Bot,
1312
PanelRightClose,
14-
PanelLeftOpen,
1513
PanelRightOpen,
1614
} from "lucide-react";
1715
import { Run, Message, TeamConfig, Component } from "../../../types/datamodel";
1816
import AgentFlow from "./agentflow/agentflow";
1917
import { RenderMessage } from "./rendermessage";
2018
import InputRequestView from "./inputrequest";
2119
import { Tooltip } from "antd";
22-
import {
23-
getRelativeTimeString,
24-
LoadingDots,
25-
TruncatableText,
26-
} from "../../atoms";
20+
import { getRelativeTimeString, LoadingDots } from "../../atoms";
21+
import { useSettingsStore } from "../../settings/store";
2722

2823
interface RunViewProps {
2924
run: Run;
@@ -62,6 +57,18 @@ const RunView: React.FC<RunViewProps> = ({
6257
const isActive = run.status === "active" || run.status === "awaiting_input";
6358
const [isFlowVisible, setIsFlowVisible] = useState(true);
6459

60+
const showLLMEvents = useSettingsStore(
61+
(state) => state.playground.showLLMEvents
62+
);
63+
console.log("showLLMEvents", showLLMEvents);
64+
65+
const visibleMessages = useMemo(() => {
66+
if (showLLMEvents) {
67+
return run.messages;
68+
}
69+
return run.messages.filter((msg) => msg.config.source !== "llm_call_event");
70+
}, [run.messages, showLLMEvents]);
71+
6572
// Replace existing scroll effect with this simpler one
6673
useEffect(() => {
6774
setTimeout(() => {
@@ -140,7 +147,7 @@ const RunView: React.FC<RunViewProps> = ({
140147
};
141148

142149
const lastResultMessage = run.team_result?.task_result.messages.slice(-1)[0];
143-
const lastMessage = getLastMeaningfulMessage(run.messages);
150+
const lastMessage = getLastMeaningfulMessage(visibleMessages);
144151

145152
return (
146153
<div className="space-y-6 mr-2 ">
@@ -233,7 +240,7 @@ const RunView: React.FC<RunViewProps> = ({
233240

234241
{/* Thread Section */}
235242
<div className="">
236-
{run.messages.length > 0 && (
243+
{visibleMessages.length > 0 && (
237244
<div className="mt-2 pl-4 border-secondary rounded-b border-l-2 border-secondary/30">
238245
<div className="flex pt-2">
239246
<div className="flex-1">
@@ -267,8 +274,8 @@ const RunView: React.FC<RunViewProps> = ({
267274
</div>
268275

269276
<div className="text-sm text-secondary">
270-
{calculateThreadTokens(run.messages)} tokens |{" "}
271-
{run.messages.length} messages
277+
{calculateThreadTokens(visibleMessages)} tokens |{" "}
278+
{visibleMessages.length} messages
272279
</div>
273280
</div>
274281

@@ -295,14 +302,14 @@ const RunView: React.FC<RunViewProps> = ({
295302
{" "}
296303
<span className=" inline-block h-6"></span>{" "}
297304
</div>
298-
{run.messages.map((msg, idx) => (
305+
{visibleMessages.map((msg, idx) => (
299306
<div
300307
key={"message_id" + idx + run.id}
301308
className=" mr-2"
302309
>
303310
<RenderMessage
304311
message={msg.config}
305-
isLast={idx === run.messages.length - 1}
312+
isLast={idx === visibleMessages.length - 1}
306313
/>
307314
</div>
308315
))}
@@ -342,7 +349,7 @@ const RunView: React.FC<RunViewProps> = ({
342349
teamConfig={teamConfig}
343350
run={{
344351
...run,
345-
messages: getAgentMessages(run.messages),
352+
messages: getAgentMessages(visibleMessages),
346353
}}
347354
/>
348355
)}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
import React, { useState, useEffect } from "react";
2+
import { ChevronRight, RotateCcw } from "lucide-react";
3+
import { Switch, Button, Tooltip } from "antd";
4+
import { MessagesSquare } from "lucide-react";
5+
import { useSettingsStore } from "./store";
6+
import { SettingsSidebar } from "./sidebar";
7+
import { SettingsSection } from "./types";
8+
import { LucideIcon } from "lucide-react";
9+
10+
interface SettingToggleProps {
11+
checked: boolean;
12+
onChange: (checked: boolean) => void;
13+
label: string;
14+
description?: string;
15+
}
16+
17+
interface SectionHeaderProps {
18+
title: string;
19+
icon: LucideIcon;
20+
onReset: () => void;
21+
}
22+
23+
const SettingToggle: React.FC<SettingToggleProps> = ({
24+
checked,
25+
onChange,
26+
label,
27+
description,
28+
}) => (
29+
<div className="flex justify-between items-start p-4 hover:bg-secondary/5 rounded-lg transition-colors">
30+
<div className="flex flex-col gap-1">
31+
<label className="font-medium">{label}</label>
32+
{description && (
33+
<span className="text-sm text-secondary">{description}</span>
34+
)}
35+
</div>
36+
<Switch defaultValue={checked} onChange={onChange} />
37+
</div>
38+
);
39+
40+
const SectionHeader: React.FC<SectionHeaderProps> = ({
41+
title,
42+
icon: Icon,
43+
onReset,
44+
}) => (
45+
<div className="flex items-center justify-between mb-6">
46+
<div className="flex items-center gap-2">
47+
<Icon className="text-accent" size={20} />
48+
<h2 className="text-lg font-semibold">{title}</h2>
49+
</div>
50+
<Tooltip title="Reset section settings">
51+
<Button
52+
icon={<RotateCcw className="w-4 h-4" />}
53+
onClick={onReset}
54+
type="text"
55+
/>
56+
</Tooltip>
57+
</div>
58+
);
59+
60+
export const SettingsManager: React.FC = () => {
61+
const [isSidebarOpen, setIsSidebarOpen] = useState(() => {
62+
if (typeof window !== "undefined") {
63+
const stored = localStorage.getItem("settingsSidebar");
64+
return stored !== null ? JSON.parse(stored) : true;
65+
}
66+
return true;
67+
});
68+
69+
const {
70+
playground,
71+
updatePlaygroundSettings,
72+
resetPlaygroundSettings,
73+
resetAllSettings,
74+
} = useSettingsStore();
75+
76+
const sections: SettingsSection[] = [
77+
{
78+
id: "playground",
79+
title: "Playground",
80+
icon: MessagesSquare,
81+
content: () => (
82+
<>
83+
<SectionHeader
84+
title="Playground"
85+
icon={MessagesSquare}
86+
onReset={resetPlaygroundSettings}
87+
/>
88+
<div className="space-y-2 rounded-xl border border-secondary">
89+
<SettingToggle
90+
checked={playground.showLLMEvents}
91+
onChange={(checked) =>
92+
updatePlaygroundSettings({ showLLMEvents: checked })
93+
}
94+
label={"Show LLM Events" + playground.showLLMEvents}
95+
description="Display detailed LLM call logs in the message thread"
96+
/>
97+
</div>
98+
</>
99+
),
100+
},
101+
];
102+
103+
const [currentSection, setCurrentSection] = useState<SettingsSection>(
104+
sections[0]
105+
);
106+
107+
useEffect(() => {
108+
if (typeof window !== "undefined") {
109+
localStorage.setItem("settingsSidebar", JSON.stringify(isSidebarOpen));
110+
}
111+
}, [isSidebarOpen]);
112+
113+
return (
114+
<div className="relative flex h-full w-full">
115+
<div
116+
className={`absolute left-0 top-0 h-full transition-all duration-200 ease-in-out ${
117+
isSidebarOpen ? "w-64" : "w-12"
118+
}`}
119+
>
120+
<SettingsSidebar
121+
isOpen={isSidebarOpen}
122+
sections={sections}
123+
currentSection={currentSection}
124+
onToggle={() => setIsSidebarOpen(!isSidebarOpen)}
125+
onSelectSection={setCurrentSection}
126+
/>
127+
</div>
128+
129+
<div
130+
className={`flex-1 transition-all max-w-5xl -mr-6 duration-200 ${
131+
isSidebarOpen ? "ml-64" : "ml-12"
132+
}`}
133+
>
134+
<div className="p-4 pt-2">
135+
<div className="flex items-center gap-2 mb-4 text-sm">
136+
<span className="text-primary font-medium">Settings</span>
137+
<ChevronRight className="w-4 h-4 text-secondary" />
138+
<span className="text-secondary">{currentSection.title}</span>
139+
</div>
140+
141+
<currentSection.content />
142+
143+
<div className="mt-12 pt-6 border-t border-secondary flex justify-between items-center">
144+
<p className="text-xs text-secondary">
145+
Settings are automatically saved and synced across browser
146+
sessions
147+
</p>
148+
<Button
149+
type="text"
150+
danger
151+
icon={<RotateCcw className="w-4 h-4 mr-1" />}
152+
onClick={resetAllSettings}
153+
>
154+
Reset All Settings
155+
</Button>
156+
</div>
157+
</div>
158+
</div>
159+
</div>
160+
);
161+
};
162+
163+
export default SettingsManager;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import React from "react";
2+
import { Button, Tooltip } from "antd";
3+
import { PanelLeftClose, PanelLeftOpen } from "lucide-react";
4+
import { SettingsSection } from "./types";
5+
6+
interface SettingsSidebarProps {
7+
isOpen: boolean;
8+
sections: SettingsSection[];
9+
currentSection: SettingsSection;
10+
onToggle: () => void;
11+
onSelectSection: (section: SettingsSection) => void;
12+
}
13+
14+
export const SettingsSidebar: React.FC<SettingsSidebarProps> = ({
15+
isOpen,
16+
sections,
17+
currentSection,
18+
onToggle,
19+
onSelectSection,
20+
}) => {
21+
// Render collapsed state
22+
if (!isOpen) {
23+
return (
24+
<div className="h-full border-r border-secondary">
25+
<div className="p-2 -ml-2">
26+
<Tooltip title={`Settings (${sections.length})`}>
27+
<button
28+
onClick={onToggle}
29+
className="p-2 rounded-md hover:bg-secondary hover:text-accent text-secondary transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-opacity-50"
30+
>
31+
<PanelLeftOpen strokeWidth={1.5} className="h-6 w-6" />
32+
</button>
33+
</Tooltip>
34+
</div>
35+
</div>
36+
);
37+
}
38+
39+
return (
40+
<div className="h-full border-r border-secondary">
41+
{/* Header */}
42+
<div className="flex items-center justify-between pt-0 p-4 pl-2 pr-2 border-b border-secondary">
43+
<div className="flex items-center gap-2">
44+
<span className="text-primary font-medium">Settings</span>
45+
<span className="px-2 py-0.5 text-xs bg-accent/10 text-accent rounded">
46+
{sections.length}
47+
</span>
48+
</div>
49+
<Tooltip title="Close Sidebar">
50+
<button
51+
onClick={onToggle}
52+
className="p-2 rounded-md hover:bg-secondary hover:text-accent text-secondary transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-opacity-50"
53+
>
54+
<PanelLeftClose strokeWidth={1.5} className="h-6 w-6" />
55+
</button>
56+
</Tooltip>
57+
</div>
58+
59+
<div className="overflow-y-auto h-[calc(100%-64px)]">
60+
{sections.map((section) => (
61+
<div key={section.id} className="relative">
62+
<div
63+
className={`absolute top-1 left-0.5 z-50 h-[calc(100%-8px)] w-1 bg-opacity-80 rounded
64+
${
65+
currentSection.id === section.id ? "bg-accent" : "bg-tertiary"
66+
}`}
67+
/>
68+
<div
69+
className={`group ml-1 flex flex-col p-3 rounded-l cursor-pointer hover:bg-secondary
70+
${
71+
currentSection.id === section.id
72+
? "border-accent bg-secondary"
73+
: "border-transparent"
74+
}`}
75+
onClick={() => onSelectSection(section)}
76+
>
77+
<div className="flex items-center gap-2">
78+
<section.icon className="w-4 h-4" />
79+
<span className="text-sm">{section.title}</span>
80+
</div>
81+
</div>
82+
</div>
83+
))}
84+
</div>
85+
</div>
86+
);
87+
};

0 commit comments

Comments
 (0)