Add Command Center v2: DQ/RAG integration, S3 browser, Jupyter, GPU matrix.
Mirror mo/atc-GPU layout with config/, docs/, scripts/ for Gitea deploy.
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
import { MessageSquare } from 'lucide-react'
|
||||
import type { Agent, ChatMessage } from '../../types'
|
||||
import { getAgentMeta } from '../../lib/agentMeta'
|
||||
import { cn } from '../../lib/utils'
|
||||
|
||||
type Props = {
|
||||
messages: ChatMessage[]
|
||||
agents: Agent[]
|
||||
selectedAgent: Agent | null
|
||||
busy: boolean
|
||||
}
|
||||
|
||||
export function CommsPanel({ messages, agents, selectedAgent, busy }: Props) {
|
||||
const bottomRef = useRef<HTMLDivElement>(null)
|
||||
const meta = selectedAgent ? getAgentMeta(selectedAgent.id) : null
|
||||
|
||||
useEffect(() => {
|
||||
bottomRef.current?.scrollIntoView({ behavior: 'smooth' })
|
||||
}, [messages, busy])
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col">
|
||||
<div className="flex shrink-0 items-center justify-between border-b border-border px-3 py-2">
|
||||
<h3 className="flex items-center gap-1.5 text-xs font-semibold text-foreground">
|
||||
<MessageSquare className="h-3.5 w-3.5 text-docker" /> Comms
|
||||
</h3>
|
||||
{selectedAgent && meta && (
|
||||
<span className="truncate font-mono text-[9px]" style={{ color: meta.accent }}>
|
||||
{selectedAgent.name.split(' ·')[0]}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="scrollbar-thin flex-1 space-y-2 overflow-y-auto p-2">
|
||||
{!messages.length && (
|
||||
<div className="flex h-full flex-col items-center justify-center py-6 text-center">
|
||||
<MessageSquare className="mb-2 h-6 w-6 text-foreground-faint" />
|
||||
<p className="max-w-[200px] text-[10px] text-foreground-muted">
|
||||
Send a command below — routing selects the right specialist automatically.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
{messages.map((m, i) => {
|
||||
const ag = m.role === 'agent' ? agents.find((a) => a.id === m.agent) : null
|
||||
const agMeta = ag ? getAgentMeta(ag.id) : null
|
||||
return (
|
||||
<div key={i} className={cn('flex gap-2', m.role === 'user' && 'flex-row-reverse')}>
|
||||
<div className={cn('max-w-[85%] rounded-lg border px-2 py-1.5', m.role === 'user' ? 'border-docker/25 bg-docker-light' : 'border-border bg-surface-overlay')}>
|
||||
<p className="mb-0.5 text-[8px] text-foreground-muted">
|
||||
{m.role === 'user' ? 'You' : ag?.name || m.agent}
|
||||
{m.ts && ` · ${new Date(m.ts).toLocaleTimeString('en-US', { hour12: false })}`}
|
||||
</p>
|
||||
<p className="whitespace-pre-wrap text-[11px] text-foreground">{m.text}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
{busy && (
|
||||
<div className="flex items-center gap-2 px-2 py-2 text-[10px] text-foreground-muted">
|
||||
<span className="h-1.5 w-1.5 animate-bounce rounded-full bg-accent" />
|
||||
<span>Agent verzamelt cluster-data en vraagt Llama 70B… verwacht ~30–90 sec</span>
|
||||
</div>
|
||||
)}
|
||||
<div ref={bottomRef} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user