Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions agentex-ui/app/error.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,28 @@ export default function Error({
}) {
return (
<div className="fixed inset-0 flex">
{/* Main Content Area */}
<div className="bg-task-background flex h-full flex-1 flex-col">
<TaskTopBar taskId={null} />

{/* Error Message - Centered */}
<div className="flex flex-1 flex-col items-center justify-center p-8">
<div className="w-full max-w-md space-y-6 text-center">
<div className="flex justify-center">
<div className="bg-destructive/10 rounded-full p-4">
<AlertCircle className="text-destructive h-12 w-12" />
</div>
</div>

<div className="space-y-2">
<h1 className="text-2xl font-semibold">Something went wrong</h1>
<p className="text-muted-foreground">
We encountered an error while loading the agent.
</p>
</div>

{error.message && (
<div className="bg-destructive/10 rounded-lg p-4 text-left text-sm">
<p className="text-destructive font-mono break-words">
{error.message}
</p>
</div>
)}

<div className="flex justify-center gap-3">
<Button onClick={reset} variant="default">
Try again
Expand Down
147 changes: 42 additions & 105 deletions agentex-ui/app/globals.css
Original file line number Diff line number Diff line change
@@ -1,141 +1,78 @@
@import 'tailwindcss';
@import 'tw-animate-css';
@source "../node_modules/streamdown/dist/index.js";
@source '../node_modules/streamdown/dist/index.js';

@custom-variant dark (&:is(.dark *));

@theme inline {
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive-foreground: var(--destructive-foreground);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-foreground: var(--foreground);
--color-input: var(--input);
--color-loading: var(--loading);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-ring: var(--ring);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--font-mono: var(--font-geist-mono);
--font-sans: var(--font-geist-sans);
--radius-lg: var(--radius);
--radius-md: calc(var(--radius) - 2px);
--radius-sm: calc(var(--radius) - 4px);
--radius-xl: calc(var(--radius) + 4px);
--color-sidebar-destructive-foreground: var(--sidebar-destructive-foreground);
--color-sidebar-destructive: var(--sidebar-destructive);
--color-sidebar-secondary-foreground: var(--sidebar-secondary-foreground);
--color-sidebar-secondary: var(--sidebar-secondary);
--color-destructive-foreground: var(--destructive-foreground);
--color-textarea-input: var(--textarea-input);
--color-textarea-foreground: var(--textarea-foreground);
--color-loading: var(--loading);
}

:root {
--max-page-content-width: var(--spacing) * 256;
--radius: 0.625rem;
--accent-foreground: #2d3748;
--accent: #c5d0e6;
--background: #ffffff;
--border: oklch(0.922 0 0);
--destructive-foreground: #fdb0ba;
--destructive: #710025;
--foreground: #35363b;
--card: oklch(1 0 0);
--card-foreground: oklch(0.145 0 0);
--popover: oklch(1 0 0);
--input: oklch(0.922 0 0);
--loading: oklch(0.92 0 0);
--muted-foreground: oklch(0.442 0 0);
--muted: oklch(0.97 0 0);
--popover-foreground: oklch(0.145 0 0);
--primary: #e3e8f4;
--popover: oklch(1 0 0);
--primary-foreground: #714dff;
--secondary: #45464f;
--secondary-foreground: #ffffff;
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.556 0 0);
--accent: #dae1f0;
--accent-foreground: #5b6579;
--destructive: #710025;
--destructive-foreground: #fdb0ba;
--border: oklch(0.922 0 0);
--input: oklch(0.922 0 0);
--primary: #f0f1ff;
--ring: #19202f;
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.145 0 0);
--sidebar-primary: #e3e8f4;
--sidebar-primary-foreground: #714dff;
--sidebar-secondary: #45464f;
--sidebar-secondary-foreground: #ffffff;
--sidebar-accent: #dae1f0;
--sidebar-accent-foreground: #5b6579;
--sidebar-border: oklch(0.922 0 0);
--sidebar-destructive: #710025;
--sidebar-destructive-foreground: #fdb0ba;
--sidebar-ring: #19202f;
--textarea-input: #ffffff;
--textarea-foreground: #35363b;
--loading: oklch(0.92 0 0);
--secondary-foreground: #ffffff;
--secondary: #45464f;
}

.dark {
--accent-foreground: #e5e7eb;
--accent: #2b3039;
--background: #151618;
--border: oklch(1 0 0 / 10%);
--destructive-foreground: #ffced5;
--destructive: #7a1331;
--foreground: #ffffff;
--card: oklch(0.205 0 0);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.205 0 0);
--input: #28292a;
--loading: #2a2b2d;
--muted-foreground: #9ca3af;
--muted: #212224;
--popover-foreground: oklch(0.985 0 0);
--primary: rgba(255, 255, 255, 0.05);
--popover: oklch(0.205 0 0);
--primary-foreground: #714dff;
--secondary: rgba(255, 255, 255, 0.05);
--secondary-foreground: oklch(0.985 0 0);
--muted: #212224;
--muted-foreground: #ffffff;
--accent: #2b3039;
--accent-foreground: #d1d5db;
--destructive: #7a1331;
--destructive-foreground: #ffced5;
--border: oklch(1 0 0 / 10%);
--input: #28292a;
--primary: rgba(147, 92, 255, 0.08);
--ring: #d1d5db;
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: #1c1d1f;
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: #1c1d1f;
--sidebar-primary-foreground: #714dff;
--sidebar-secondary: rgba(255, 255, 255, 0.05);
--sidebar-secondary-foreground: oklch(0.985 0 0);
--sidebar-accent: #714dff;
--sidebar-accent-foreground: #ffffff;
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-destructive: #7a1331;
--sidebar-destructive-foreground: #ffced5;
--sidebar-ring: #d1d5db;
--textarea-input: #28292a;
--textarea-foreground: #d1d5db;
--loading: #2a2b2d;
--secondary-foreground: oklch(0.985 0 0);
--secondary: rgba(255, 255, 255, 0.08);
}

@layer base {
Expand Down
2 changes: 1 addition & 1 deletion agentex-ui/app/home-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export function HomeView() {
updateParams({ [SearchParamKey.AGENT_NAME]: null });
setLocalAgentName(undefined);
}}
className={`text-muted-foreground cursor-pointer text-xs transition-opacity duration-200 hover:underline ${
className={`text-accent-foreground cursor-pointer text-xs transition-opacity duration-200 hover:underline ${
agentName ? 'opacity-100' : 'pointer-events-none opacity-0'
}`}
>
Expand Down
2 changes: 1 addition & 1 deletion agentex-ui/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export default function RootLayout({
<QueryProvider>
<ThemeProvider
attribute="class"
defaultTheme="dark"
defaultTheme="light"
enableSystem={false}
disableTransitionOnChange
>
Expand Down
39 changes: 6 additions & 33 deletions agentex-ui/app/loading.tsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,55 @@
'use client';

import { Suspense } from 'react';

import { ArrowUp } from 'lucide-react';

import { IconButton } from '@/components/agentex/icon-button';
import { Skeleton } from '@/components/ui/skeleton';
import { useSafeSearchParams } from '@/hooks/use-safe-search-params';

function LoadingContent() {
export default function Loading() {
const { taskID } = useSafeSearchParams();

// If there's a task ID, show the task/chat loading state
if (taskID) {
return (
<div className="fixed inset-0 flex w-full">
{/* Sidebar Skeleton */}
<div className="bg-sidebar border-sidebar-border flex h-full w-64 flex-col border-r">
{/* Header Section */}
<div className="border-sidebar-border border-b pt-4 pr-4 pb-6 pl-2">
<div className="flex items-center gap-2 pb-4 pl-2">
<div className="bg-background border-border flex h-full w-64 flex-col border-r">
<div className="border-border border-b p-4">
<div className="flex items-center gap-2 pb-4">
<Skeleton className="h-6 w-24" />
</div>
<Skeleton className="h-10 w-full" />
</div>

{/* Task List */}
<div className="flex flex-col gap-5 overflow-y-auto py-4 pr-2 pl-4">
{[...Array(8)].map((_, i) => (
<Skeleton key={i} className="h-5 w-full" />
))}
</div>
</div>

{/* Main Content Area Skeleton */}
<div className="bg-task-background flex h-full flex-1 flex-col">
{/* Top Bar */}
<div className="border-border border-b px-4 py-3">
<Skeleton className="h-8 w-48" />
</div>

{/* Messages Area */}
<div className="flex flex-1 flex-col items-center overflow-y-auto px-4 pt-4">
<div className="flex w-full max-w-[800px] flex-col gap-4">
{/* User Message Skeleton */}
<div className="flex justify-end">
<Skeleton className="h-15 w-1/4 rounded-lg" />
</div>

{/* Agent Message Skeleton */}
<div className="flex flex-col justify-start gap-3">
<Skeleton className="h-4 w-5/6" />
<Skeleton className="h-4 w-7/8" />
<Skeleton className="h-4 w-5/8" />
</div>

{/* User Message Skeleton */}
<div className="flex justify-end">
<Skeleton className="h-15 w-1/4 rounded-lg" />
</div>

{/* Agent Message Skeleton */}
<div className="flex flex-col justify-start gap-3">
<Skeleton className="h-4 w-5/6" />
<Skeleton className="h-4 w-7/8" />
<Skeleton className="h-4 w-5/8" />
</div>
</div>
</div>

{/* Input Form Skeleton */}
<div className="flex w-full justify-center px-4 py-8 sm:px-6 md:px-8">
<div className="w-full max-w-3xl">
<Skeleton className="h-[58px] w-full rounded-full" />
Expand All @@ -80,6 +60,7 @@ function LoadingContent() {
);
}

// If there's no task ID, show the home loading state
return (
<div className="fixed inset-0 flex w-full">
<div className="flex h-full flex-1 flex-col justify-center">
Expand All @@ -96,7 +77,7 @@ function LoadingContent() {
<div className="flex w-full justify-center px-4 py-8 sm:px-6 md:px-8">
<div className="w-full max-w-3xl">
<div className="w-full opacity-50">
<div className="border-input dark:bg-input/30 disabled:bg-muted flex w-full justify-between rounded-full border bg-transparent py-2 pr-2 pl-6 disabled:cursor-not-allowed">
<div className="border-input dark:bg-input/30 disabled:bg-accent flex w-full justify-between rounded-full border bg-transparent py-2 pr-2 pl-6 disabled:cursor-not-allowed">
<input
type="text"
value=""
Expand All @@ -118,11 +99,3 @@ function LoadingContent() {
</div>
);
}

export default function Loading() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LoadingContent />
</Suspense>
);
}
2 changes: 1 addition & 1 deletion agentex-ui/app/primary-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function PrimaryContent({
const { scrollTop, scrollHeight, clientHeight } = container;
const distanceFromBottom = scrollHeight - scrollTop - clientHeight;

const scrollThreshold = 100; // pixels from bottom
const scrollThreshold = 100;
const isNearBottom = distanceFromBottom < scrollThreshold;

setShowScrollButton(!isNearBottom);
Expand Down
4 changes: 2 additions & 2 deletions agentex-ui/components/agentex/agent-badge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ function AgentBadgeImpl({ agent }: AgentBadgeProps) {
onClick={handleClick}
className={`relative cursor-pointer overflow-hidden rounded-full px-4 py-2 text-sm font-medium ${
isSelected
? 'bg-primary text-primary-foreground border-primary-foreground border'
: 'border-border border'
? 'bg-primary text-primary-foreground border-primary-foreground border shadow-md'
: 'border-border border shadow-xs'
} `}
initial={isSelected ? false : { opacity: 0 }}
animate={{
Expand Down
1 change: 0 additions & 1 deletion agentex-ui/components/agentex/agents-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export function AgentsList({ agents, isLoading = false }: AgentsListProps) {
hasMounted.current = true;
}, []);

// Filter agents: show only selected agent if one is selected, otherwise show all
const displayedAgents = selectedAgentName
? agents.filter(agent => agent.name === selectedAgentName)
: agents;
Expand Down
6 changes: 1 addition & 5 deletions agentex-ui/components/agentex/copy-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export function CopyButton({
const timeoutRef = useRef<NodeJS.Timeout | null>(null);

const handleCopy = useCallback(() => {
// Clear any existing timeout
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
Expand Down Expand Up @@ -68,10 +67,7 @@ export function CopyButton({
variant="ghost"
iconSize="sm"
onClick={handleCopy}
className={cn(
'hover:bg-muted hover:text-muted-foreground size-6 transition-colors',
className
)}
className={cn('size-6 transition-colors', className)}
Comment thread
declan-scale marked this conversation as resolved.
aria-label={isCopying ? 'Copied' : 'Copy'}
/>
);
Expand Down
Loading