mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-31 03:12:16 +00:00
* feat(ui): update design tokens — system-ui font, warmer palette, accent triad - Remove Merriweather serif font, switch to system-ui font stack - Warmer dark mode neutrals (#161618 bg instead of #09090b) - Add amber/purple accent tokens for signature color triad - Update borders to rgba for softer feel - Tighter line-height (1.5) and letter-spacing (-0.01em) - Update PWA theme_color to match new palette Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(ui): frosted glass sidebar with backdrop-blur Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(ui): initialize shadcn/ui with button, dialog, input, select, tooltip, sonner Set up shadcn/ui (v4) for Tailwind CSS v4 with CSS-first config. Added path aliases (@/) to tsconfig.json and vite.config.ts. Installed six components (button, dialog, input, select, tooltip, sonner) and wired Sonner's <Toaster> into App.tsx for toast notifications. Removed the next-themes dependency since this is a Vite/React project, not Next.js. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ui): disable create agent when unavailable, replace errors with toasts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(ui): add System Pulse bar and health check banner - 3px gradient bar at top reflecting system state (idle/inferencing/agent) - Health check banner when backend is unreachable - Pulse colors: blue (inference), purple (agents), dim blue (idle) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(ui): add X-Ray message footers with collapsible telemetry - MessageTelemetry type on ChatMessage (engine, model, speed, TTFT, timing) - Capture timing data during SSE streaming in InputArea - XRayFooter component: collapsed one-liner + expandable trace grid - Integrated into MessageBubble, replacing old token count display Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(ui): resolve shadcn/ui CSS token conflicts with design system - Namespace shadcn @theme inline variables (--color-cn-*) to avoid overriding project's --color-border, --color-accent, --radius-* tokens - Remove @apply border-border, bg-background, text-foreground, font-sans that conflicted with our explicit CSS custom properties - Remove dead Geist font import (we use system-ui) - Remove ---break--- comment artifacts from shadcn CLI Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { useAppStore } from '../lib/store';
|
|
import { fetchManagedAgents } from '../lib/api';
|
|
|
|
type PulseState = 'idle' | 'inferencing' | 'agent-active' | 'hidden';
|
|
|
|
const PULSE_CONFIG: Record<Exclude<PulseState, 'hidden'>, { color: string; animation: string }> = {
|
|
idle: {
|
|
color: 'rgba(59, 130, 246, 0.3)',
|
|
animation: 'none',
|
|
},
|
|
inferencing: {
|
|
color: '#3b82f6',
|
|
animation: 'pulse-glow 2s ease-in-out infinite',
|
|
},
|
|
'agent-active': {
|
|
color: '#8b5cf6',
|
|
animation: 'pulse-travel 3s linear infinite',
|
|
},
|
|
};
|
|
|
|
export function SystemPulse({ apiReachable }: { apiReachable: boolean | null }) {
|
|
const isStreaming = useAppStore((s) => s.streamState.isStreaming);
|
|
const [hasRunningAgent, setHasRunningAgent] = useState(false);
|
|
|
|
// Poll for running agents every 30s
|
|
useEffect(() => {
|
|
if (apiReachable === false) return;
|
|
const check = () =>
|
|
fetchManagedAgents()
|
|
.then((agents) => setHasRunningAgent(agents.some((a) => a.status === 'running')))
|
|
.catch(() => {});
|
|
check();
|
|
const interval = setInterval(check, 30000);
|
|
return () => clearInterval(interval);
|
|
}, [apiReachable]);
|
|
|
|
if (apiReachable === false) return null;
|
|
|
|
// Priority: agent-active > inferencing > idle
|
|
let state: PulseState = 'idle';
|
|
if (isStreaming) state = 'inferencing';
|
|
if (hasRunningAgent) state = 'agent-active';
|
|
|
|
const config = PULSE_CONFIG[state];
|
|
const isTravel = state === 'agent-active';
|
|
|
|
return (
|
|
<div
|
|
className="fixed top-0 left-0 right-0 h-[3px] z-50"
|
|
style={{
|
|
background: isTravel
|
|
? `linear-gradient(90deg, transparent, ${config.color}, transparent)`
|
|
: `linear-gradient(90deg, transparent 5%, ${config.color} 30%, ${config.color} 70%, transparent 95%)`,
|
|
backgroundSize: isTravel ? '200% 100%' : '100% 100%',
|
|
animation: config.animation,
|
|
}}
|
|
/>
|
|
);
|
|
}
|