diff --git a/ui/src/components/monitoring/auth-monitor.tsx b/ui/src/components/monitoring/auth-monitor.tsx
deleted file mode 100644
index 61cbaf8b..00000000
--- a/ui/src/components/monitoring/auth-monitor.tsx
+++ /dev/null
@@ -1,465 +0,0 @@
-/**
- * Auth Monitor Component with Account Flow Visualization
- * Shows request flow from accounts to providers using custom SVG bezier curves
- * Uses glass panel aesthetic with hover interactions and glow effects
- */
-
-import { useState, useMemo, useEffect } from 'react';
-import { useCliproxyAuth } from '@/hooks/use-cliproxy';
-import { useCliproxyStats, type AccountUsageStats } from '@/hooks/use-cliproxy-stats';
-import { cn, STATUS_COLORS } from '@/lib/utils';
-import { getProviderDisplayName, PROVIDER_COLORS } from '@/lib/provider-config';
-import { Skeleton } from '@/components/ui/skeleton';
-import { ProviderIcon } from '@/components/shared/provider-icon';
-import { AccountFlowViz } from '@/components/account-flow-viz';
-import { usePrivacy } from '@/contexts/privacy-context';
-import type { AuthStatus, OAuthAccount } from '@/lib/api-client';
-import { Activity, CheckCircle2, XCircle, ChevronRight, Radio } from 'lucide-react';
-
-interface AccountRow {
- id: string;
- email: string;
- provider: string;
- displayName: string;
- isDefault: boolean;
- successCount: number;
- failureCount: number;
- lastUsedAt?: string;
- color: string;
-}
-
-interface ProviderStats {
- provider: string;
- displayName: string;
- totalRequests: number;
- successCount: number;
- failureCount: number;
- accountCount: number;
- accounts: AccountRow[];
-}
-
-function getSuccessRate(success: number, failure: number): number {
- const total = success + failure;
- if (total === 0) return 100;
- return Math.round((success / total) * 100);
-}
-
-/** Strip common email domains for cleaner display */
-function cleanEmail(email: string): string {
- return email.replace(/@(gmail|yahoo|hotmail|outlook|icloud)\.com$/i, '');
-}
-
-// Vibrant colors for account segments - darker for light theme contrast
-const ACCOUNT_COLORS = [
- '#1e6091', // Deep Cerulean (was #277da1)
- '#2d8a6e', // Deep Seaweed (was #43aa8b)
- '#d4a012', // Dark Tuscan (was #f9c74f)
- '#c92a2d', // Deep Strawberry (was #f94144)
- '#c45a1a', // Deep Pumpkin (was #f3722c)
- '#6b9c4d', // Dark Willow (was #90be6d)
- '#3d5a73', // Deep Blue Slate (was #577590)
- '#cc7614', // Dark Carrot (was #f8961e)
- '#3a7371', // Deep Cyan (was #4d908e)
- '#7c5fc4', // Deep Purple (was #a78bfa)
-];
-
-/** Enhanced live pulse indicator with multi-ring animation */
-function LivePulse() {
- return (
-
- {/* Outer ping ring */}
-
- {/* Middle pulse ring */}
-
- {/* Inner solid dot */}
-
-
- );
-}
-
-/** Inline success/failure badge for provider cards */
-function InlineStatsBadge({ success, failure }: { success: number; failure: number }) {
- if (success === 0 && failure === 0) {
- return no activity;
- }
-
- return (
-
-
-
-
- {success.toLocaleString()}
-
-
- {failure > 0 && (
-
-
-
- {failure.toLocaleString()}
-
-
- )}
-
- );
-}
-
-export function AuthMonitor() {
- const { data, isLoading, error } = useCliproxyAuth();
- const { data: statsData, isLoading: statsLoading, dataUpdatedAt } = useCliproxyStats();
- const { privacyMode } = usePrivacy();
- const [selectedProvider, setSelectedProvider] = useState(null);
- const [hoveredProvider, setHoveredProvider] = useState(null);
- const [timeSinceUpdate, setTimeSinceUpdate] = useState('');
-
- // Live countdown showing time since last data update
- useEffect(() => {
- if (!dataUpdatedAt) return;
- const updateTime = () => {
- const diff = Math.floor((Date.now() - dataUpdatedAt) / 1000);
- if (diff < 60) {
- setTimeSinceUpdate(`${diff}s ago`);
- } else {
- setTimeSinceUpdate(`${Math.floor(diff / 60)}m ago`);
- }
- };
- updateTime();
- const interval = setInterval(updateTime, 1000);
- return () => clearInterval(interval);
- }, [dataUpdatedAt]);
-
- // Build a map of account email -> usage stats from CLIProxy
- const accountStatsMap = useMemo(() => {
- if (!statsData?.accountStats) return new Map();
- return new Map(Object.entries(statsData.accountStats));
- }, [statsData?.accountStats]);
-
- // Transform auth status data into account rows
- const { accounts, totalSuccess, totalFailure, totalRequests, providerStats } = useMemo(() => {
- if (!data?.authStatus) {
- return {
- accounts: [],
- totalSuccess: 0,
- totalFailure: 0,
- totalRequests: 0,
- providerStats: [],
- };
- }
-
- const accountsList: AccountRow[] = [];
- const providerMap = new Map<
- string,
- { success: number; failure: number; accounts: AccountRow[] }
- >();
- let tSuccess = 0;
- let tFailure = 0;
- let colorIndex = 0;
-
- data.authStatus.forEach((status: AuthStatus) => {
- const providerKey = status.provider;
- if (!providerMap.has(providerKey)) {
- providerMap.set(providerKey, { success: 0, failure: 0, accounts: [] });
- }
- const providerData = providerMap.get(providerKey);
- if (!providerData) return;
-
- status.accounts?.forEach((account: OAuthAccount) => {
- // Get real stats from CLIProxy - try email first, then id
- const accountEmail = account.email || account.id;
- const realStats = accountStatsMap.get(accountEmail);
- const success = realStats?.successCount ?? 0;
- const failure = realStats?.failureCount ?? 0;
- tSuccess += success;
- tFailure += failure;
- providerData.success += success;
- providerData.failure += failure;
-
- const row: AccountRow = {
- id: account.id,
- email: account.email || account.id,
- provider: status.provider,
- displayName: status.displayName,
- isDefault: account.isDefault,
- successCount: success,
- failureCount: failure,
- lastUsedAt: realStats?.lastUsedAt ?? account.lastUsedAt,
- color: ACCOUNT_COLORS[colorIndex % ACCOUNT_COLORS.length],
- };
- accountsList.push(row);
- providerData.accounts.push(row);
- colorIndex++;
- });
- });
-
- // Build provider stats array
- const providerStatsArr: ProviderStats[] = [];
- providerMap.forEach((pData, provider) => {
- if (pData.accounts.length === 0) return;
- providerStatsArr.push({
- provider,
- displayName: getProviderDisplayName(provider),
- totalRequests: pData.success + pData.failure,
- successCount: pData.success,
- failureCount: pData.failure,
- accountCount: pData.accounts.length,
- accounts: pData.accounts,
- });
- });
- providerStatsArr.sort((a, b) => b.totalRequests - a.totalRequests);
-
- return {
- accounts: accountsList,
- totalSuccess: tSuccess,
- totalFailure: tFailure,
- totalRequests: tSuccess + tFailure,
- providerStats: providerStatsArr,
- };
- }, [data?.authStatus, accountStatsMap]);
-
- const overallSuccessRate =
- totalRequests > 0 ? Math.round((totalSuccess / totalRequests) * 100) : 100;
-
- // Get selected provider data for detail view
- const selectedProviderData = selectedProvider
- ? providerStats.find((ps) => ps.provider === selectedProvider)
- : null;
-
- if (isLoading || statsLoading) {
- return (
-
-
-
-
-
-
-
- {[1, 2, 3, 4].map((i) => (
-
- ))}
-
-
-
-
- );
- }
-
- if (error || !data?.authStatus || accounts.length === 0) {
- return null;
- }
-
- return (
-
- {/* Enhanced Live Header with gradient glow */}
-
-
-
- LIVE
- Account Monitor
-
-
-
-
- Updated {timeSinceUpdate || 'now'}
-
-
|
-
{accounts.length} accounts
-
{totalRequests.toLocaleString()} req
-
-
-
- {/* Summary Stats Row */}
-
- }
- label="Accounts"
- value={accounts.length}
- color="var(--accent)"
- />
- }
- label="Success"
- value={totalSuccess.toLocaleString()}
- color={STATUS_COLORS.success}
- />
- }
- label="Failed"
- value={totalFailure.toLocaleString()}
- color={totalFailure > 0 ? STATUS_COLORS.failed : undefined}
- />
- }
- label="Success Rate"
- value={`${overallSuccessRate}%`}
- color={
- overallSuccessRate === 100
- ? STATUS_COLORS.success
- : overallSuccessRate >= 95
- ? STATUS_COLORS.degraded
- : STATUS_COLORS.failed
- }
- />
-
-
- {/* Flow Visualization */}
-
- {selectedProviderData ? (
- // Account-level flow view
-
setSelectedProvider(null)}
- />
- ) : (
- // Provider cards view
-
-
- Request Distribution by Provider
-
-
- {providerStats.map((ps) => {
- const successRate = getSuccessRate(ps.successCount, ps.failureCount);
- const providerColor = PROVIDER_COLORS[ps.provider.toLowerCase()] || '#6b7280';
- const isHovered = hoveredProvider === ps.provider;
-
- return (
-
- );
- })}
-
-
- )}
-
-
- );
-}
-
-// Summary Card Component
-function SummaryCard({
- icon,
- label,
- value,
- color,
-}: {
- icon: React.ReactNode;
- label: string;
- value: string | number;
- color?: string;
-}) {
- return (
-
-
- {icon}
-
-
-
{label}
-
- {value}
-
-
-
- );
-}
diff --git a/ui/src/components/monitoring/auth-monitor/components/inline-stats-badge.tsx b/ui/src/components/monitoring/auth-monitor/components/inline-stats-badge.tsx
new file mode 100644
index 00000000..bd60db8f
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/components/inline-stats-badge.tsx
@@ -0,0 +1,35 @@
+/**
+ * InlineStatsBadge - Inline success/failure badge for provider cards
+ */
+
+import { CheckCircle2, XCircle } from 'lucide-react';
+
+interface InlineStatsBadgeProps {
+ success: number;
+ failure: number;
+}
+
+export function InlineStatsBadge({ success, failure }: InlineStatsBadgeProps) {
+ if (success === 0 && failure === 0) {
+ return no activity;
+ }
+
+ return (
+
+
+
+
+ {success.toLocaleString()}
+
+
+ {failure > 0 && (
+
+
+
+ {failure.toLocaleString()}
+
+
+ )}
+
+ );
+}
diff --git a/ui/src/components/monitoring/auth-monitor/components/live-pulse.tsx b/ui/src/components/monitoring/auth-monitor/components/live-pulse.tsx
new file mode 100644
index 00000000..adc006ad
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/components/live-pulse.tsx
@@ -0,0 +1,27 @@
+/**
+ * LivePulse - Enhanced live pulse indicator with multi-ring animation
+ */
+
+import { STATUS_COLORS } from '@/lib/utils';
+
+export function LivePulse() {
+ return (
+
+ {/* Outer ping ring */}
+
+ {/* Middle pulse ring */}
+
+ {/* Inner solid dot */}
+
+
+ );
+}
diff --git a/ui/src/components/monitoring/auth-monitor/components/provider-card.tsx b/ui/src/components/monitoring/auth-monitor/components/provider-card.tsx
new file mode 100644
index 00000000..d7faf5f9
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/components/provider-card.tsx
@@ -0,0 +1,123 @@
+/**
+ * ProviderCard - Provider status card with account color dots and stats
+ */
+
+import type React from 'react';
+import { ChevronRight } from 'lucide-react';
+import { cn, STATUS_COLORS } from '@/lib/utils';
+import { PROVIDER_COLORS } from '@/lib/provider-config';
+import { ProviderIcon } from '@/components/shared/provider-icon';
+import type { ProviderStats } from '../types';
+import { getSuccessRate, cleanEmail } from '../utils';
+import { InlineStatsBadge } from './inline-stats-badge';
+
+interface ProviderCardProps {
+ stats: ProviderStats;
+ isHovered: boolean;
+ privacyMode: boolean;
+ onSelect: () => void;
+ onMouseEnter: () => void;
+ onMouseLeave: () => void;
+}
+
+export function ProviderCard({
+ stats,
+ isHovered,
+ privacyMode,
+ onSelect,
+ onMouseEnter,
+ onMouseLeave,
+}: ProviderCardProps) {
+ const successRate = getSuccessRate(stats.successCount, stats.failureCount);
+ const providerColor = PROVIDER_COLORS[stats.provider.toLowerCase()] || '#6b7280';
+
+ return (
+
+ );
+}
diff --git a/ui/src/components/monitoring/auth-monitor/components/summary-card.tsx b/ui/src/components/monitoring/auth-monitor/components/summary-card.tsx
new file mode 100644
index 00000000..380d5d03
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/components/summary-card.tsx
@@ -0,0 +1,37 @@
+/**
+ * SummaryCard - Summary stats card with icon and value display
+ */
+
+import type React from 'react';
+
+interface SummaryCardProps {
+ icon: React.ReactNode;
+ label: string;
+ value: string | number;
+ color?: string;
+}
+
+export function SummaryCard({ icon, label, value, color }: SummaryCardProps) {
+ return (
+
+
+ {icon}
+
+
+
{label}
+
+ {value}
+
+
+
+ );
+}
diff --git a/ui/src/components/monitoring/auth-monitor/hooks.ts b/ui/src/components/monitoring/auth-monitor/hooks.ts
new file mode 100644
index 00000000..1640f037
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/hooks.ts
@@ -0,0 +1,148 @@
+/**
+ * Hooks for Auth Monitor data aggregation and state management
+ */
+
+import { useState, useMemo, useEffect } from 'react';
+import { useCliproxyAuth } from '@/hooks/use-cliproxy';
+import { useCliproxyStats, type AccountUsageStats } from '@/hooks/use-cliproxy-stats';
+import { getProviderDisplayName } from '@/lib/provider-config';
+import type { AuthStatus, OAuthAccount } from '@/lib/api-client';
+import type { AccountRow, ProviderStats } from './types';
+import { ACCOUNT_COLORS } from './utils';
+
+export interface AuthMonitorData {
+ accounts: AccountRow[];
+ totalSuccess: number;
+ totalFailure: number;
+ totalRequests: number;
+ providerStats: ProviderStats[];
+ overallSuccessRate: number;
+ isLoading: boolean;
+ error: Error | null;
+ timeSinceUpdate: string;
+}
+
+/** Hook for computing auth monitor data from CLIProxy auth and stats */
+export function useAuthMonitorData(): AuthMonitorData {
+ const { data, isLoading, error } = useCliproxyAuth();
+ const { data: statsData, isLoading: statsLoading, dataUpdatedAt } = useCliproxyStats();
+ const [timeSinceUpdate, setTimeSinceUpdate] = useState('');
+
+ // Live countdown showing time since last data update
+ useEffect(() => {
+ if (!dataUpdatedAt) return;
+ const updateTime = () => {
+ const diff = Math.floor((Date.now() - dataUpdatedAt) / 1000);
+ if (diff < 60) {
+ setTimeSinceUpdate(`${diff}s ago`);
+ } else {
+ setTimeSinceUpdate(`${Math.floor(diff / 60)}m ago`);
+ }
+ };
+ updateTime();
+ const interval = setInterval(updateTime, 1000);
+ return () => clearInterval(interval);
+ }, [dataUpdatedAt]);
+
+ // Build a map of account email -> usage stats from CLIProxy
+ const accountStatsMap = useMemo(() => {
+ if (!statsData?.accountStats) return new Map();
+ return new Map(Object.entries(statsData.accountStats));
+ }, [statsData?.accountStats]);
+
+ // Transform auth status data into account rows
+ const { accounts, totalSuccess, totalFailure, totalRequests, providerStats } = useMemo(() => {
+ if (!data?.authStatus) {
+ return {
+ accounts: [] as AccountRow[],
+ totalSuccess: 0,
+ totalFailure: 0,
+ totalRequests: 0,
+ providerStats: [] as ProviderStats[],
+ };
+ }
+
+ const accountsList: AccountRow[] = [];
+ const providerMap = new Map<
+ string,
+ { success: number; failure: number; accounts: AccountRow[] }
+ >();
+ let tSuccess = 0;
+ let tFailure = 0;
+ let colorIndex = 0;
+
+ data.authStatus.forEach((status: AuthStatus) => {
+ const providerKey = status.provider;
+ if (!providerMap.has(providerKey)) {
+ providerMap.set(providerKey, { success: 0, failure: 0, accounts: [] });
+ }
+ const providerData = providerMap.get(providerKey);
+ if (!providerData) return;
+
+ status.accounts?.forEach((account: OAuthAccount) => {
+ const accountEmail = account.email || account.id;
+ const realStats = accountStatsMap.get(accountEmail);
+ const success = realStats?.successCount ?? 0;
+ const failure = realStats?.failureCount ?? 0;
+ tSuccess += success;
+ tFailure += failure;
+ providerData.success += success;
+ providerData.failure += failure;
+
+ const row: AccountRow = {
+ id: account.id,
+ email: account.email || account.id,
+ provider: status.provider,
+ displayName: status.displayName,
+ isDefault: account.isDefault,
+ successCount: success,
+ failureCount: failure,
+ lastUsedAt: realStats?.lastUsedAt ?? account.lastUsedAt,
+ color: ACCOUNT_COLORS[colorIndex % ACCOUNT_COLORS.length],
+ };
+ accountsList.push(row);
+ providerData.accounts.push(row);
+ colorIndex++;
+ });
+ });
+
+ // Build provider stats array
+ const providerStatsArr: ProviderStats[] = [];
+ providerMap.forEach((pData, provider) => {
+ if (pData.accounts.length === 0) return;
+ providerStatsArr.push({
+ provider,
+ displayName: getProviderDisplayName(provider),
+ totalRequests: pData.success + pData.failure,
+ successCount: pData.success,
+ failureCount: pData.failure,
+ accountCount: pData.accounts.length,
+ accounts: pData.accounts,
+ });
+ });
+ providerStatsArr.sort((a, b) => b.totalRequests - a.totalRequests);
+
+ return {
+ accounts: accountsList,
+ totalSuccess: tSuccess,
+ totalFailure: tFailure,
+ totalRequests: tSuccess + tFailure,
+ providerStats: providerStatsArr,
+ };
+ }, [data?.authStatus, accountStatsMap]);
+
+ const overallSuccessRate =
+ totalRequests > 0 ? Math.round((totalSuccess / totalRequests) * 100) : 100;
+
+ return {
+ accounts,
+ totalSuccess,
+ totalFailure,
+ totalRequests,
+ providerStats,
+ overallSuccessRate,
+ isLoading: isLoading || statsLoading,
+ error: error ?? null,
+ timeSinceUpdate,
+ };
+}
diff --git a/ui/src/components/monitoring/auth-monitor/index.tsx b/ui/src/components/monitoring/auth-monitor/index.tsx
new file mode 100644
index 00000000..d43e1d48
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/index.tsx
@@ -0,0 +1,151 @@
+/**
+ * Auth Monitor Component with Account Flow Visualization
+ * Shows request flow from accounts to providers using custom SVG bezier curves
+ * Uses glass panel aesthetic with hover interactions and glow effects
+ */
+
+import { useState } from 'react';
+import { STATUS_COLORS } from '@/lib/utils';
+import { Skeleton } from '@/components/ui/skeleton';
+import { AccountFlowViz } from '@/components/account-flow-viz';
+import { usePrivacy } from '@/contexts/privacy-context';
+import { Activity, CheckCircle2, XCircle, Radio } from 'lucide-react';
+
+import { useAuthMonitorData } from './hooks';
+import { LivePulse } from './components/live-pulse';
+import { ProviderCard } from './components/provider-card';
+import { SummaryCard } from './components/summary-card';
+
+export function AuthMonitor() {
+ const {
+ accounts,
+ totalSuccess,
+ totalFailure,
+ totalRequests,
+ providerStats,
+ overallSuccessRate,
+ isLoading,
+ error,
+ timeSinceUpdate,
+ } = useAuthMonitorData();
+
+ const { privacyMode } = usePrivacy();
+ const [selectedProvider, setSelectedProvider] = useState(null);
+ const [hoveredProvider, setHoveredProvider] = useState(null);
+
+ // Get selected provider data for detail view
+ const selectedProviderData = selectedProvider
+ ? providerStats.find((ps) => ps.provider === selectedProvider)
+ : null;
+
+ if (isLoading) {
+ return (
+
+
+
+
+
+
+
+ {[1, 2, 3, 4].map((i) => (
+
+ ))}
+
+
+
+
+ );
+ }
+
+ if (error || accounts.length === 0) {
+ return null;
+ }
+
+ return (
+
+ {/* Enhanced Live Header with gradient glow */}
+
+
+
+ LIVE
+ Account Monitor
+
+
+
+
+ Updated {timeSinceUpdate || 'now'}
+
+
|
+
{accounts.length} accounts
+
{totalRequests.toLocaleString()} req
+
+
+
+ {/* Summary Stats Row */}
+
+ }
+ label="Accounts"
+ value={accounts.length}
+ color="var(--accent)"
+ />
+ }
+ label="Success"
+ value={totalSuccess.toLocaleString()}
+ color={STATUS_COLORS.success}
+ />
+ }
+ label="Failed"
+ value={totalFailure.toLocaleString()}
+ color={totalFailure > 0 ? STATUS_COLORS.failed : undefined}
+ />
+ }
+ label="Success Rate"
+ value={`${overallSuccessRate}%`}
+ color={
+ overallSuccessRate === 100
+ ? STATUS_COLORS.success
+ : overallSuccessRate >= 95
+ ? STATUS_COLORS.degraded
+ : STATUS_COLORS.failed
+ }
+ />
+
+
+ {/* Flow Visualization */}
+
+ {selectedProviderData ? (
+
setSelectedProvider(null)}
+ />
+ ) : (
+
+
+ Request Distribution by Provider
+
+
+ {providerStats.map((ps) => (
+
setSelectedProvider(ps.provider)}
+ onMouseEnter={() => setHoveredProvider(ps.provider)}
+ onMouseLeave={() => setHoveredProvider(null)}
+ />
+ ))}
+
+
+ )}
+
+
+ );
+}
+
+// Re-export types for barrel
+export type { AccountRow, ProviderStats } from './types';
diff --git a/ui/src/components/monitoring/auth-monitor/types.ts b/ui/src/components/monitoring/auth-monitor/types.ts
new file mode 100644
index 00000000..1eb61953
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/types.ts
@@ -0,0 +1,25 @@
+/**
+ * Type definitions for Auth Monitor components
+ */
+
+export interface AccountRow {
+ id: string;
+ email: string;
+ provider: string;
+ displayName: string;
+ isDefault: boolean;
+ successCount: number;
+ failureCount: number;
+ lastUsedAt?: string;
+ color: string;
+}
+
+export interface ProviderStats {
+ provider: string;
+ displayName: string;
+ totalRequests: number;
+ successCount: number;
+ failureCount: number;
+ accountCount: number;
+ accounts: AccountRow[];
+}
diff --git a/ui/src/components/monitoring/auth-monitor/utils.ts b/ui/src/components/monitoring/auth-monitor/utils.ts
new file mode 100644
index 00000000..28272ac7
--- /dev/null
+++ b/ui/src/components/monitoring/auth-monitor/utils.ts
@@ -0,0 +1,29 @@
+/**
+ * Utility functions and constants for Auth Monitor
+ */
+
+/** Calculate success rate percentage */
+export function getSuccessRate(success: number, failure: number): number {
+ const total = success + failure;
+ if (total === 0) return 100;
+ return Math.round((success / total) * 100);
+}
+
+/** Strip common email domains for cleaner display */
+export function cleanEmail(email: string): string {
+ return email.replace(/@(gmail|yahoo|hotmail|outlook|icloud)\.com$/i, '');
+}
+
+// Vibrant colors for account segments - darker for light theme contrast
+export const ACCOUNT_COLORS = [
+ '#1e6091', // Deep Cerulean
+ '#2d8a6e', // Deep Seaweed
+ '#d4a012', // Dark Tuscan
+ '#c92a2d', // Deep Strawberry
+ '#c45a1a', // Deep Pumpkin
+ '#6b9c4d', // Dark Willow
+ '#3d5a73', // Deep Blue Slate
+ '#cc7614', // Dark Carrot
+ '#3a7371', // Deep Cyan
+ '#7c5fc4', // Deep Purple
+];
diff --git a/ui/src/components/monitoring/index.ts b/ui/src/components/monitoring/index.ts
index 3d66966d..4f9ac659 100644
--- a/ui/src/components/monitoring/index.ts
+++ b/ui/src/components/monitoring/index.ts
@@ -4,6 +4,7 @@
// Main monitoring components
export { AuthMonitor } from './auth-monitor';
+export type { AccountRow, ProviderStats } from './auth-monitor';
export { ProxyStatusWidget } from './proxy-status-widget';
// Error logs (from subdirectory)