2026-06-25 00:28:23 +00:00
|
|
|
import { useRef, useState } from 'react'
|
|
|
|
|
import { useClock } from './hooks/useClock'
|
|
|
|
|
import { useCommandCenter } from './hooks/useCommandCenter'
|
|
|
|
|
import { useLiveMetrics } from './hooks/useLiveMetrics'
|
|
|
|
|
import { SideNav } from './components/layout/SideNav'
|
|
|
|
|
import { TopBar } from './components/layout/TopBar'
|
|
|
|
|
import { AgentFleet } from './components/features/AgentFleet'
|
|
|
|
|
import { ApprovalInbox } from './components/features/ApprovalInbox'
|
|
|
|
|
import { ChatDrawer } from './components/features/ChatDrawer'
|
|
|
|
|
import { GpuMonitor } from './components/features/GpuMonitor'
|
|
|
|
|
import { InfraQuickAccess } from './components/features/InfraQuickAccess'
|
|
|
|
|
import { InspectorPanel } from './components/features/InspectorPanel'
|
|
|
|
|
import { PlatformTopology } from './components/features/PlatformTopology'
|
|
|
|
|
import { PresentationView } from './components/features/PresentationView'
|
|
|
|
|
import { DataQualityView } from './components/features/DataQualityView'
|
|
|
|
|
import { KnowledgeChatView } from './components/features/KnowledgeChatView'
|
|
|
|
|
import { StorageView } from './components/features/StorageView'
|
2026-06-25 00:53:11 +00:00
|
|
|
import { SearchView } from './components/features/SearchView'
|
2026-06-25 00:28:23 +00:00
|
|
|
import { TerminalDock } from './components/features/TerminalDock'
|
2026-06-25 01:10:57 +00:00
|
|
|
import { WorkbenchPanel } from './components/features/WorkbenchPanel'
|
2026-06-25 00:28:23 +00:00
|
|
|
import { resolveInfraNode } from './lib/infraCatalog'
|
|
|
|
|
import { cn } from './lib/utils'
|
2026-06-23 15:07:51 +02:00
|
|
|
|
|
|
|
|
export default function App() {
|
2026-06-25 00:28:23 +00:00
|
|
|
const clock = useClock()
|
|
|
|
|
const cc = useCommandCenter()
|
|
|
|
|
const [gpuChatActive, setGpuChatActive] = useState(false)
|
|
|
|
|
const gpuBoost = gpuChatActive || cc.mainView === 'knowledge'
|
|
|
|
|
const { agentLoads, gpuLive } = useLiveMetrics(cc.agents, cc.gpu, cc.anims, gpuBoost)
|
|
|
|
|
const mainScrollRef = useRef<HTMLDivElement>(null)
|
2026-06-23 15:07:51 +02:00
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
const isPlatform = cc.mainView === 'platform'
|
2026-06-23 15:07:51 +02:00
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
const openApprovals = () => {
|
|
|
|
|
cc.setMainView('approvals')
|
|
|
|
|
mainScrollRef.current?.scrollTo({ top: 0, behavior: 'smooth' })
|
2026-06-23 15:07:51 +02:00
|
|
|
}
|
|
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
const terminalSubject = cc.terminalSubjectId
|
|
|
|
|
const terminalLabel = (() => {
|
|
|
|
|
if (cc.selectedAgent) return cc.selectedAgent.name.split(' ·')[0]
|
|
|
|
|
const infra = resolveInfraNode(terminalSubject)
|
|
|
|
|
if (infra) return infra.label
|
|
|
|
|
if (cc.selectedNode) return cc.selectedNode.label
|
|
|
|
|
return 'Lab'
|
|
|
|
|
})()
|
2026-06-23 15:07:51 +02:00
|
|
|
|
|
|
|
|
return (
|
2026-06-25 00:28:23 +00:00
|
|
|
<div className="flex h-full flex-col overflow-hidden bg-surface">
|
|
|
|
|
<TopBar
|
|
|
|
|
clock={clock}
|
|
|
|
|
status={cc.status}
|
|
|
|
|
workload={cc.workload}
|
|
|
|
|
agents={cc.agents}
|
|
|
|
|
approvals={cc.approvals}
|
|
|
|
|
onApprovalsClick={openApprovals}
|
|
|
|
|
/>
|
2026-06-23 15:07:51 +02:00
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
<div className="flex min-h-0 flex-1 overflow-hidden">
|
|
|
|
|
<SideNav
|
|
|
|
|
agents={cc.agents}
|
|
|
|
|
animations={cc.anims}
|
|
|
|
|
gpu={cc.gpu}
|
|
|
|
|
gpuLive={gpuLive}
|
|
|
|
|
gpuBoost={gpuBoost}
|
|
|
|
|
selectedAgentId={cc.selectedAgentId}
|
|
|
|
|
selectedNodeId={cc.selectedNodeId}
|
|
|
|
|
mainView={cc.mainView}
|
|
|
|
|
approvalCount={cc.approvals.length}
|
|
|
|
|
agentsLoading={cc.agentsLoading}
|
|
|
|
|
onSetMainView={cc.setMainView}
|
|
|
|
|
onOpenApprovals={openApprovals}
|
|
|
|
|
onSelectAgent={cc.selectAgent}
|
|
|
|
|
onSelectZone={cc.selectNode}
|
|
|
|
|
/>
|
2026-06-23 15:07:51 +02:00
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
<div ref={mainScrollRef} className="scrollbar-thin flex min-h-0 min-w-0 flex-1 flex-col overflow-y-auto bg-surface">
|
|
|
|
|
<div className={cn('flex min-h-0 flex-1', isPlatform ? '' : 'flex-col')}>
|
|
|
|
|
<div className={cn('flex min-w-0 flex-1 flex-col gap-2', isPlatform ? 'p-2' : 'min-h-0 p-3')}>
|
|
|
|
|
{isPlatform && (
|
|
|
|
|
<>
|
|
|
|
|
<div className="grid shrink-0 grid-cols-1 gap-2 xl:grid-cols-[1fr_auto]">
|
|
|
|
|
<AgentFleet
|
|
|
|
|
agents={cc.agents}
|
|
|
|
|
animations={cc.anims}
|
|
|
|
|
selectedId={cc.selectedAgentId}
|
|
|
|
|
loads={agentLoads}
|
|
|
|
|
approvalCount={cc.approvals.length}
|
|
|
|
|
onSelect={cc.selectAgent}
|
|
|
|
|
onOpenApprovals={openApprovals}
|
|
|
|
|
/>
|
|
|
|
|
<GpuMonitor gpu={cc.gpu} live={gpuLive} />
|
2026-06-23 15:07:51 +02:00
|
|
|
</div>
|
2026-06-25 00:28:23 +00:00
|
|
|
<InfraQuickAccess
|
|
|
|
|
workload={cc.workload}
|
|
|
|
|
agents={cc.agents}
|
|
|
|
|
selectedNodeId={cc.selectedNodeId}
|
|
|
|
|
busy={cc.nodeBusy}
|
|
|
|
|
onSelectNode={cc.selectNode}
|
|
|
|
|
onSelectAgent={cc.selectAgent}
|
|
|
|
|
onProbe={cc.probeNodeId}
|
|
|
|
|
onOpenTerminal={cc.openTerminal}
|
|
|
|
|
/>
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
|
2026-06-25 01:10:57 +00:00
|
|
|
<div className={cn('flex min-h-0 flex-col', isPlatform ? 'min-h-[300px] flex-1' : 'min-h-0 flex-1')}>
|
2026-06-25 00:28:23 +00:00
|
|
|
{cc.mainView === 'platform' ? (
|
|
|
|
|
<PlatformTopology
|
|
|
|
|
workload={cc.workload}
|
|
|
|
|
animations={cc.anims}
|
|
|
|
|
selectedNodeId={cc.selectedNodeId}
|
|
|
|
|
onNodeClick={cc.selectNode}
|
|
|
|
|
/>
|
|
|
|
|
) : cc.mainView === 'presentation' ? (
|
|
|
|
|
<PresentationView />
|
|
|
|
|
) : cc.mainView === 'dataquality' ? (
|
|
|
|
|
<DataQualityView />
|
|
|
|
|
) : cc.mainView === 'knowledge' ? (
|
|
|
|
|
<KnowledgeChatView onGpuActivity={setGpuChatActive} />
|
|
|
|
|
) : cc.mainView === 'storage' ? (
|
|
|
|
|
<StorageView />
|
2026-06-25 00:53:11 +00:00
|
|
|
) : cc.mainView === 'search' ? (
|
|
|
|
|
<SearchView />
|
2026-06-25 00:28:23 +00:00
|
|
|
) : (
|
|
|
|
|
<ApprovalInbox agents={cc.agents} livePending={cc.approvals} onDecide={cc.decide} />
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
2026-06-25 01:10:57 +00:00
|
|
|
|
|
|
|
|
{isPlatform && cc.workbenchMode && (
|
|
|
|
|
<WorkbenchPanel
|
|
|
|
|
mode={cc.workbenchMode}
|
|
|
|
|
agent={cc.selectedAgent}
|
|
|
|
|
lines={cc.inspectorLines}
|
|
|
|
|
busy={cc.nodeBusy || cc.promptBusy}
|
|
|
|
|
onSendPrompt={cc.sendPrompt}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2026-06-23 15:07:51 +02:00
|
|
|
</div>
|
|
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
{isPlatform && (
|
|
|
|
|
<div className="flex w-[340px] shrink-0 flex-col border-l border-border">
|
|
|
|
|
<InspectorPanel
|
|
|
|
|
node={cc.selectedNode}
|
|
|
|
|
nodeDetail={cc.nodeDetail}
|
|
|
|
|
agent={cc.selectedAgent}
|
|
|
|
|
agents={cc.agents}
|
|
|
|
|
workload={cc.workload}
|
|
|
|
|
gpu={cc.gpu}
|
|
|
|
|
feed={cc.feed}
|
|
|
|
|
lines={cc.inspectorLines}
|
|
|
|
|
busy={cc.nodeBusy}
|
|
|
|
|
onProbe={cc.probeNode}
|
|
|
|
|
onAsk={cc.askNode}
|
|
|
|
|
onSelectAgent={cc.selectAgent}
|
|
|
|
|
onSendPrompt={cc.sendPrompt}
|
|
|
|
|
onClear={cc.clearSelection}
|
|
|
|
|
onOpenTerminal={cc.openTerminal}
|
|
|
|
|
onProbeNodeId={cc.probeNodeId}
|
|
|
|
|
/>
|
2026-06-25 01:10:57 +00:00
|
|
|
{!cc.workbenchMode && (
|
|
|
|
|
<TerminalDock
|
|
|
|
|
subjectId={terminalSubject}
|
|
|
|
|
subjectLabel={terminalLabel}
|
|
|
|
|
lines={cc.inspectorLines}
|
|
|
|
|
busy={cc.nodeBusy || cc.promptBusy}
|
|
|
|
|
expanded={cc.terminalExpanded}
|
|
|
|
|
onToggle={() => cc.setTerminalExpanded(!cc.terminalExpanded)}
|
|
|
|
|
/>
|
|
|
|
|
)}
|
2026-06-23 15:07:51 +02:00
|
|
|
</div>
|
2026-06-25 00:28:23 +00:00
|
|
|
)}
|
2026-06-23 15:07:51 +02:00
|
|
|
</div>
|
2026-06-25 00:28:23 +00:00
|
|
|
</div>
|
2026-06-23 15:07:51 +02:00
|
|
|
</div>
|
|
|
|
|
|
2026-06-25 00:28:23 +00:00
|
|
|
<ChatDrawer
|
|
|
|
|
expanded={cc.chatExpanded}
|
|
|
|
|
onToggle={() => cc.setChatExpanded(!cc.chatExpanded)}
|
|
|
|
|
chat={cc.chat}
|
|
|
|
|
feed={cc.feed}
|
|
|
|
|
agents={cc.agents}
|
|
|
|
|
approvals={cc.approvals}
|
|
|
|
|
selectedAgent={cc.selectedAgent}
|
|
|
|
|
promptBusy={cc.promptBusy}
|
|
|
|
|
approvalHighlight={cc.approvalHighlight}
|
|
|
|
|
filterAgentId={cc.selectedAgentId}
|
|
|
|
|
onSendPrompt={cc.sendPrompt}
|
|
|
|
|
onDecide={cc.decide}
|
|
|
|
|
onDismissHighlight={() => cc.setApprovalHighlight(false)}
|
|
|
|
|
/>
|
2026-06-23 15:07:51 +02:00
|
|
|
</div>
|
|
|
|
|
)
|
|
|
|
|
}
|