Skip to content

Commit 60b44c5

Browse files
authored
Agentex-UI cleanup (#30)
## Changes - Change the Response component -> MarkdownResponse, move it into the agentex directory and delete the ai-elements - Remove CodeBlock (was unused) - Remove all the unused packages - Use types for props instead of interfaces (we were using a bit of both) - Memoize components with the following pattern: - declare a functional component called `ComponentNameImpl` - set `ComponentName = memo(ComponentNameImpl)` - `export { ComponentName }` - Removed more unused packages after removing some unused components (the old input component) - Remove the unused SubmitButton and FileUploadButton - Only export types used in other files - Move utils and `JsonValue` into the lib directory - Use absolute import paths (as opposed to relative), rename components with the words Memoized or Component in the name - Add vitest for the utils
1 parent 6560912 commit 60b44c5

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+3541
-1695
lines changed

agentex-ui/app/agentex-ui-root.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { useCallback, useEffect, useState } from 'react';
44

55
import { ToastContainer } from 'react-toastify';
66

7+
import { PrimaryContent } from '@/app/primary-content';
78
import { TaskSidebar } from '@/components/agentex/task-sidebar';
89
import { TracesSidebar } from '@/components/agentex/traces-sidebar';
910
import { AgentexProvider } from '@/components/providers';
@@ -13,8 +14,6 @@ import {
1314
useSafeSearchParams,
1415
} from '@/hooks/use-safe-search-params';
1516

16-
import { PrimaryContent } from './primary-content';
17-
1817
type AgentexUIRootProps = {
1918
sgpAppURL: string;
2019
agentexAPIBaseURL: string;

agentex-ui/app/chat-view.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useRef } from 'react';
22

33
import { motion } from 'framer-motion';
44

5-
import { MemoizedTaskMessagesComponent } from '@/components/agentex/task-messages';
5+
import { TaskMessages } from '@/components/agentex/task-messages';
66
import { TaskProvider } from '@/components/providers';
77

88
export function ChatView({ taskID }: { taskID: string }) {
@@ -21,7 +21,7 @@ export function ChatView({ taskID }: { taskID: string }) {
2121
<div className="flex min-h-full w-full flex-col items-center px-4 sm:px-6 md:px-8">
2222
<div className="w-full max-w-3xl">
2323
<TaskProvider taskId={taskID}>
24-
<MemoizedTaskMessagesComponent taskId={taskID} />
24+
<TaskMessages taskId={taskID} />
2525
</TaskProvider>
2626
</div>
2727
</div>

agentex-ui/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Geist, Geist_Mono } from 'next/font/google';
33
import { QueryProvider, ThemeProvider } from '@/components/providers';
44

55
import type { Metadata } from 'next';
6-
import './globals.css';
6+
import '@/app/globals.css';
77

88
const geistSans = Geist({
99
variable: '--font-geist-sans',

agentex-ui/app/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { connection } from 'next/server';
22

3-
import { AgentexUIRoot } from './agentex-ui-root';
3+
import { AgentexUIRoot } from '@/app/agentex-ui-root';
44

55
export default async function RootPage() {
66
await connection();

agentex-ui/app/primary-content.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { useState, useRef, useEffect, useCallback } from 'react';
33
import { AnimatePresence, motion } from 'framer-motion';
44
import { ArrowDown } from 'lucide-react';
55

6+
import { ChatView } from '@/app/chat-view';
7+
import { HomeView } from '@/app/home-view';
68
import { IconButton } from '@/components/agentex/icon-button';
79
import { PromptInput } from '@/components/agentex/prompt-input';
810
import { TaskTopBar } from '@/components/agentex/task-top-bar';
@@ -13,13 +15,10 @@ import {
1315
SearchParamKey,
1416
} from '@/hooks/use-safe-search-params';
1517

16-
import { ChatView } from './chat-view';
17-
import { HomeView } from './home-view';
18-
19-
interface ContentAreaProps {
18+
type ContentAreaProps = {
2019
isTracesSidebarOpen: boolean;
2120
toggleTracesSidebar: () => void;
22-
}
21+
};
2322

2423
export function PrimaryContent({
2524
isTracesSidebarOpen,
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { memo } from 'react';
2+
3+
import { motion } from 'framer-motion';
4+
5+
import { useLocalStorageState } from '@/hooks/use-local-storage-state';
6+
import {
7+
SearchParamKey,
8+
useSafeSearchParams,
9+
} from '@/hooks/use-safe-search-params';
10+
11+
import type { Agent } from 'agentex/resources';
12+
13+
type AgentBadgeProps = {
14+
agent: Agent;
15+
};
16+
17+
function AgentBadgeImpl({ agent }: AgentBadgeProps) {
18+
const { agentName, updateParams } = useSafeSearchParams();
19+
const [, setLocalAgentName] = useLocalStorageState<string | undefined>(
20+
'lastSelectedAgent',
21+
undefined
22+
);
23+
const isSelected = agentName === agent.name;
24+
25+
const handleClick = () => {
26+
if (isSelected) {
27+
updateParams({ [SearchParamKey.AGENT_NAME]: null });
28+
setLocalAgentName(undefined);
29+
} else {
30+
updateParams({ [SearchParamKey.AGENT_NAME]: agent.name });
31+
setLocalAgentName(agent.name);
32+
}
33+
};
34+
35+
return (
36+
<motion.button
37+
layout
38+
onClick={handleClick}
39+
className={`relative cursor-pointer overflow-hidden rounded-full px-4 py-2 text-sm font-medium ${
40+
isSelected
41+
? 'bg-primary text-primary-foreground border-primary-foreground border'
42+
: 'border-border border'
43+
} `}
44+
initial={isSelected ? false : { opacity: 0 }}
45+
animate={{
46+
opacity: 1,
47+
scale: 1,
48+
transition: {
49+
delay: isSelected ? 0 : 0.2,
50+
},
51+
}}
52+
exit={{ opacity: 0, transition: { duration: 0.2 } }}
53+
whileHover={{ scale: 1.05 }}
54+
whileTap={{ scale: 0.95 }}
55+
transition={{
56+
type: 'spring',
57+
stiffness: 500,
58+
damping: 40,
59+
}}
60+
>
61+
{agent.name}
62+
</motion.button>
63+
);
64+
}
65+
66+
const AgentBadge = memo(AgentBadgeImpl);
67+
68+
export { AgentBadge };

agentex-ui/components/agentex/agents-list.tsx

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,11 @@ import { useEffect, useRef } from 'react';
33
import { Agent } from 'agentex/resources';
44
import { AnimatePresence, motion } from 'framer-motion';
55

6+
import { AgentBadge } from '@/components/agentex/agent-badge';
67
import { Skeleton } from '@/components/ui/skeleton';
7-
import { useLocalStorageState } from '@/hooks/use-local-storage-state';
8-
import {
9-
SearchParamKey,
10-
useSafeSearchParams,
11-
} from '@/hooks/use-safe-search-params';
8+
import { useSafeSearchParams } from '@/hooks/use-safe-search-params';
129

13-
export type AgentsListProps = {
10+
type AgentsListProps = {
1411
agents: Agent[];
1512
isLoading?: boolean;
1613
};
@@ -49,56 +46,3 @@ export function AgentsList({ agents, isLoading = false }: AgentsListProps) {
4946
</motion.div>
5047
);
5148
}
52-
53-
interface AgentBadgeProps {
54-
agent: Agent;
55-
}
56-
57-
function AgentBadge({ agent }: AgentBadgeProps) {
58-
const { agentName, updateParams } = useSafeSearchParams();
59-
const [, setLocalAgentName] = useLocalStorageState<string | undefined>(
60-
'lastSelectedAgent',
61-
undefined
62-
);
63-
const isSelected = agentName === agent.name;
64-
65-
const handleClick = () => {
66-
if (isSelected) {
67-
updateParams({ [SearchParamKey.AGENT_NAME]: null });
68-
setLocalAgentName(undefined);
69-
} else {
70-
updateParams({ [SearchParamKey.AGENT_NAME]: agent.name });
71-
setLocalAgentName(agent.name);
72-
}
73-
};
74-
75-
return (
76-
<motion.button
77-
layout
78-
onClick={handleClick}
79-
className={`relative cursor-pointer overflow-hidden rounded-full px-4 py-2 text-sm font-medium ${
80-
isSelected
81-
? 'bg-primary text-primary-foreground border-primary-foreground border'
82-
: 'border-border border'
83-
} `}
84-
initial={isSelected ? false : { opacity: 0 }}
85-
animate={{
86-
opacity: 1,
87-
scale: 1,
88-
transition: {
89-
delay: isSelected ? 0 : 0.2,
90-
},
91-
}}
92-
exit={{ opacity: 0, transition: { duration: 0.2 } }}
93-
whileHover={{ scale: 1.05 }}
94-
whileTap={{ scale: 0.95 }}
95-
transition={{
96-
type: 'spring',
97-
stiffness: 500,
98-
damping: 40,
99-
}}
100-
>
101-
{agent.name}
102-
</motion.button>
103-
);
104-
}

agentex-ui/components/agentex/copy-button.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@ import {
1414
} from '@/components/ui/tooltip';
1515
import { cn } from '@/lib/utils';
1616

17-
export interface CopyButtonProps {
17+
type CopyButtonProps = {
1818
tooltip?: string;
1919
onClick?: () => void;
2020
content?: string;
2121
className?: string;
2222
timeout?: number;
23-
}
23+
};
2424

2525
export function CopyButton({
2626
tooltip,

0 commit comments

Comments
 (0)