Skip to content

Commit 8414dee

Browse files
feat: remove chat from agent edit
- made header sticky - adds animation and Try it Out! CTA to open agent in new tab - removes footer with chat actions and save status Signed-off-by: Ryan Hopper-Lowe <[email protected]>
1 parent 82f65b4 commit 8414dee

15 files changed

+263
-319
lines changed

ui/admin/app/components/agent/Agent.tsx

Lines changed: 104 additions & 174 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import { GearIcon } from "@radix-ui/react-icons";
2-
import { BlocksIcon, LibraryIcon, PlusIcon, WrenchIcon } from "lucide-react";
2+
import { BlocksIcon, LibraryIcon, WrenchIcon } from "lucide-react";
33
import { useCallback, useEffect, useState } from "react";
44

55
import { Agent as AgentType } from "~/lib/model/agents";
66
import { AssistantNamespace } from "~/lib/model/assistants";
7-
import { cn } from "~/lib/utils";
87

98
import { AgentAlias } from "~/components/agent/AgentAlias";
109
import { useAgent } from "~/components/agent/AgentContext";
1110
import { AgentForm } from "~/components/agent/AgentForm";
1211
import { AgentIntroForm } from "~/components/agent/AgentIntroForm";
13-
import { PastThreads } from "~/components/agent/PastThreads";
1412
import { ToolForm } from "~/components/agent/ToolForm";
1513
import { AgentCapabilityForm } from "~/components/agent/shared/AgentCapabilityForm";
1614
import { AgentModelSelect } from "~/components/agent/shared/AgentModelSelect";
@@ -24,23 +22,13 @@ import {
2422
AccordionItem,
2523
AccordionTrigger,
2624
} from "~/components/ui/accordion";
27-
import { Button } from "~/components/ui/button";
2825
import { CardDescription } from "~/components/ui/card";
29-
import { ScrollArea } from "~/components/ui/scroll-area";
3026
import { useDebounce } from "~/hooks/useDebounce";
3127

32-
type AgentProps = {
33-
className?: string;
34-
currentThreadId?: string | null;
35-
onRefresh?: (threadId: string | null) => void;
36-
};
37-
38-
export function Agent({ className, currentThreadId, onRefresh }: AgentProps) {
39-
const { agent, updateAgent, refreshAgent, isUpdating, lastUpdated, error } =
40-
useAgent();
28+
export function Agent() {
29+
const { agent, updateAgent, refreshAgent } = useAgent();
4130

4231
const [agentUpdates, setAgentUpdates] = useState(agent);
43-
const [enableScrollStick, setEnableScrollStick] = useState(false);
4432

4533
useEffect(() => {
4634
setAgentUpdates((prev) => {
@@ -75,167 +63,109 @@ export function Agent({ className, currentThreadId, onRefresh }: AgentProps) {
7563
[agent, agentUpdates, debouncedUpdateAgent]
7664
);
7765

78-
const handleThreadSelect = useCallback(
79-
(threadId: string) => {
80-
onRefresh?.(threadId);
81-
},
82-
[onRefresh]
83-
);
84-
85-
const handleAccordionValueChange = useCallback((value: string[]) => {
86-
setEnableScrollStick(value.includes("model"));
87-
}, []);
88-
8966
return (
90-
<div className="flex h-full flex-col">
91-
<ScrollArea
92-
className={cn("h-full", className)}
93-
enableScrollStick={enableScrollStick ? "bottom" : undefined}
94-
>
95-
<AgentAlias agent={agentUpdates} onChange={partialSetAgent} />
96-
97-
<div className="m-4 p-4">
98-
<AgentForm agent={agentUpdates} onChange={partialSetAgent} />
99-
</div>
100-
101-
<div className="m-4 p-4">
102-
<AgentIntroForm agent={agentUpdates} onChange={partialSetAgent} />
103-
</div>
104-
105-
<div className="m-4 space-y-4 p-4">
106-
<h4 className="flex items-center gap-2 border-b pb-2">
107-
<BlocksIcon />
108-
Capabilities
109-
</h4>
110-
111-
<CardDescription>
112-
Capabilities define how users can interact with this agent in the
113-
chat interface. Each capability enables specific features that users
114-
can access when using the agent.
115-
</CardDescription>
116-
117-
<AgentCapabilityForm
118-
entity={agentUpdates}
119-
onChange={partialSetAgent}
120-
/>
121-
</div>
122-
123-
<div className="m-4 space-y-4 p-4">
124-
<h4 className="flex items-center gap-2 border-b pb-2">
125-
<WrenchIcon />
126-
Tools
127-
</h4>
128-
129-
<CardDescription>
130-
Add tools that allow the agent to perform useful actions such as
131-
searching the web, reading files, or interacting with other systems.
132-
</CardDescription>
133-
134-
<ToolForm
135-
agent={agentUpdates}
136-
onChange={({ tools, oauthApps }) =>
137-
partialSetAgent(convertTools(tools, oauthApps))
138-
}
139-
renderActions={renderActions}
140-
/>
141-
</div>
142-
143-
<div className="m-4 space-y-4 p-4">
144-
<h4 className="flex items-center gap-2 border-b pb-2">
145-
<LibraryIcon />
146-
Knowledge
147-
</h4>
148-
149-
<CardDescription>
150-
Provide knowledge to the agent in the form of files, website, or
151-
external links in order to give it context about various topics.
152-
</CardDescription>
153-
154-
<AgentKnowledgePanel
155-
agentId={agent.id}
156-
agent={agent}
157-
updateAgent={partialSetAgent}
158-
addTool={(tool) => {
159-
if (agent?.tools?.includes(tool)) return;
160-
161-
partialSetAgent({
162-
tools: [...(agent.tools || []), tool],
163-
});
164-
}}
165-
/>
166-
</div>
167-
168-
<WorkspaceFilesSection entityId={agent.id} />
169-
170-
<Accordion
171-
type="multiple"
172-
className="m-4 p-4"
173-
onValueChange={handleAccordionValueChange}
174-
>
175-
<AccordionItem value="model">
176-
<AccordionTrigger className="border-b">
177-
<h4 className="flex items-center gap-2">
178-
<GearIcon className="size-5" />
179-
Advanced
180-
</h4>
181-
</AccordionTrigger>
182-
183-
<AccordionContent className="space-y-8 py-4">
184-
<div className="flex flex-col gap-4">
185-
<h4>Model</h4>
186-
187-
<CardDescription>
188-
The model to use for the agent.
189-
</CardDescription>
190-
191-
<AgentModelSelect
192-
entity={agentUpdates}
193-
onChange={(updates) => partialSetAgent(updates)}
194-
/>
195-
</div>
196-
197-
<EnvironmentVariableSection
198-
entity={agent}
199-
onUpdate={partialSetAgent}
200-
entityType="agent"
67+
<div className="relative flex h-full flex-col">
68+
<AgentAlias agent={agentUpdates} onChange={partialSetAgent} />
69+
70+
<div className="m-4 p-4">
71+
<AgentForm agent={agentUpdates} onChange={partialSetAgent} />
72+
</div>
73+
74+
<div className="m-4 p-4">
75+
<AgentIntroForm agent={agentUpdates} onChange={partialSetAgent} />
76+
</div>
77+
78+
<div className="m-4 space-y-4 p-4">
79+
<h4 className="flex items-center gap-2 border-b pb-2">
80+
<BlocksIcon />
81+
Capabilities
82+
</h4>
83+
84+
<CardDescription>
85+
Capabilities define how users can interact with this agent in the chat
86+
interface. Each capability enables specific features that users can
87+
access when using the agent.
88+
</CardDescription>
89+
90+
<AgentCapabilityForm entity={agentUpdates} onChange={partialSetAgent} />
91+
</div>
92+
93+
<div className="m-4 space-y-4 p-4">
94+
<h4 className="flex items-center gap-2 border-b pb-2">
95+
<WrenchIcon />
96+
Tools
97+
</h4>
98+
99+
<CardDescription>
100+
Add tools that allow the agent to perform useful actions such as
101+
searching the web, reading files, or interacting with other systems.
102+
</CardDescription>
103+
104+
<ToolForm
105+
agent={agentUpdates}
106+
onChange={({ tools, oauthApps }) =>
107+
partialSetAgent(convertTools(tools, oauthApps))
108+
}
109+
renderActions={renderActions}
110+
/>
111+
</div>
112+
113+
<div className="m-4 space-y-4 p-4">
114+
<h4 className="flex items-center gap-2 border-b pb-2">
115+
<LibraryIcon />
116+
Knowledge
117+
</h4>
118+
119+
<CardDescription>
120+
Provide knowledge to the agent in the form of files, website, or
121+
external links in order to give it context about various topics.
122+
</CardDescription>
123+
124+
<AgentKnowledgePanel
125+
agentId={agent.id}
126+
agent={agent}
127+
updateAgent={partialSetAgent}
128+
addTool={(tool) => {
129+
if (agent?.tools?.includes(tool)) return;
130+
131+
partialSetAgent({
132+
tools: [...(agent.tools || []), tool],
133+
});
134+
}}
135+
/>
136+
</div>
137+
138+
<WorkspaceFilesSection entityId={agent.id} />
139+
140+
<Accordion type="multiple" className="m-4 p-4">
141+
<AccordionItem value="model">
142+
<AccordionTrigger className="border-b">
143+
<h4 className="flex items-center gap-2">
144+
<GearIcon className="size-5" />
145+
Advanced
146+
</h4>
147+
</AccordionTrigger>
148+
149+
<AccordionContent className="space-y-8 py-4">
150+
<div className="flex flex-col gap-4">
151+
<h4>Model</h4>
152+
153+
<CardDescription>The model to use for the agent.</CardDescription>
154+
155+
<AgentModelSelect
156+
entity={agentUpdates}
157+
onChange={(updates) => partialSetAgent(updates)}
201158
/>
202-
</AccordionContent>
203-
</AccordionItem>
204-
</Accordion>
205-
</ScrollArea>
206-
207-
<footer className="flex items-center justify-between gap-4 px-8 py-4 shadow-inner">
208-
<div className="text-muted-foreground">
209-
{error ? (
210-
<p>Error saving agent</p>
211-
) : isUpdating ? (
212-
<p>Saving...</p>
213-
) : lastUpdated ? (
214-
<p>Saved</p>
215-
) : (
216-
<div />
217-
)}
218-
</div>
219-
220-
<div className="flex gap-2">
221-
<PastThreads
222-
currentThreadId={currentThreadId}
223-
agentId={agent.id}
224-
onThreadSelect={handleThreadSelect}
225-
/>
226-
227-
<Button
228-
variant="outline"
229-
className="flex gap-2"
230-
onClick={() => {
231-
onRefresh?.(null);
232-
}}
233-
>
234-
<PlusIcon />
235-
New Thread
236-
</Button>
237-
</div>
238-
</footer>
159+
</div>
160+
161+
<EnvironmentVariableSection
162+
entity={agent}
163+
onUpdate={partialSetAgent}
164+
entityType="agent"
165+
/>
166+
</AccordionContent>
167+
</AccordionItem>
168+
</Accordion>
239169
</div>
240170
);
241171

ui/admin/app/components/agent/AgentAlias.tsx

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import { ArrowRightIcon } from "lucide-react";
12
import { useMemo } from "react";
2-
import { Link, useNavigate } from "react-router";
3+
import { useNavigate } from "react-router";
34
import { $path } from "safe-routes";
45
import useSWR from "swr";
56

@@ -13,6 +14,8 @@ import { Publish } from "~/components/agent/Publish";
1314
import { CopyText } from "~/components/composed/CopyText";
1415
import { WarningAlert } from "~/components/composed/WarningAlert";
1516
import { LoadingSpinner } from "~/components/ui/LoadingSpinner";
17+
import { AnimateResize } from "~/components/ui/animate/animate-resize";
18+
import { Link } from "~/components/ui/link";
1619

1720
type AgentAliasProps = {
1821
agent: Agent;
@@ -40,7 +43,7 @@ export function AgentAlias({ agent, onChange }: AgentAliasProps) {
4043
);
4144

4245
return (
43-
<div className="flex w-full flex-col gap-4 px-8 pt-4">
46+
<div className="sticky top-0 z-10 flex h-16 w-full flex-col gap-4 border-b bg-background px-8 pt-4">
4447
<div className="flex w-full justify-between gap-4">
4548
<div className="flex flex-col gap-2">
4649
{agent.aliasAssigned === undefined &&
@@ -57,24 +60,28 @@ export function AgentAlias({ agent, onChange }: AgentAliasProps) {
5760
/>
5861

5962
<Link
63+
as="button"
64+
to={agentUrl}
6065
target="_blank"
6166
rel="noreferrer"
62-
className="text-muted-foreground underline"
63-
to={agentUrl}
67+
className="group flex items-center gap-2"
6468
>
65-
{agentUrl}
69+
<AnimateResize>
70+
<span className="group-hover:hidden">Try it Out!</span>
71+
<span className="hidden group-hover:block">{agentUrl}</span>
72+
</AnimateResize>
73+
<ArrowRightIcon />
6674
</Link>
67-
68-
<Publish
69-
alias={agent.alias}
70-
id={agent.id}
71-
onPublish={(alias) => onChange({ alias })}
72-
/>
7375
</div>
7476
)}
7577
</div>
7678

7779
<div className="flex gap-2">
80+
<Publish
81+
alias={agent.alias}
82+
id={agent.id}
83+
onPublish={(alias) => onChange({ alias })}
84+
/>
7885
<AgentAccessControl agent={agent} />
7986
<DeleteAgent id={agent.id} onSuccess={() => navigate("/agents")} />
8087
</div>

0 commit comments

Comments
 (0)