oxios 1.10.1

Oxios Agent OS — Agent Operating System powered by oxi-sdk
import { Activity, Brain, Hash, Pin } from 'lucide-react'
import { useTranslation } from 'react-i18next'
import { ErrorState } from '@/components/shared/error-state'
import { LoadingCards } from '@/components/shared/loading'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
import { useMemoryStats } from '@/hooks/use-memory'

const TIER_COLORS: Record<string, string> = {
  hot: '#ef4444',
  warm: '#eab308',
  cold: '#3b82f6',
}

/**
 * One horizontal distribution row: label · bar (scaled to `max`) · count.
 *
 * NOTE: this replaces recharts `<BarChart>`/`<PieChart>` here. recharts 3.x's
 * Bar/Pie components are mis-bundled by rolldown (vite v8) — they render fine in
 * dev but throw `TypeError: t is not a function` in the production bundle.
 * AreaChart (used elsewhere) is unaffected; only Bar/Pie break. A dependency-
 * free bar avoids the defective code path and renders identically in every build.
 */
function DistBar({
  label,
  value,
  max,
  color,
}: {
  label: string
  value: number
  max: number
  color: string
}) {
  const pct = max > 0 ? Math.round((value / max) * 100) : 0
  return (
    <div className="flex items-center gap-3 text-sm">
      <span className="w-20 shrink-0 truncate text-muted-foreground" title={label}>
        {label}
      </span>
      <div className="h-2.5 flex-1 overflow-hidden rounded-full bg-muted">
        <div
          className="h-full rounded-full transition-all"
          style={{ width: `${pct}%`, backgroundColor: color }}
        />
      </div>
      <span className="w-8 shrink-0 text-right font-medium tabular-nums">{value}</span>
    </div>
  )
}

export function MemoryOverview() {
  const { t } = useTranslation()
  const { data: stats, isLoading, isError, refetch } = useMemoryStats()

  if (isLoading) return <LoadingCards count={4} />
  if (isError) return <ErrorState onRetry={() => refetch()} />
  if (!stats) return null

  const tierEntries = Object.entries(stats.by_tier || {})
    .filter(([, v]) => v > 0)
    .map(([name, value]) => [name, value] as [string, number])
  const typeEntries = Object.entries(stats.by_type || {})
    .filter(([, v]) => v > 0)
    .map(([name, value]) => [name, value] as [string, number])
  const tierMax = Math.max(1, ...tierEntries.map(([, v]) => v))
  const typeMax = Math.max(1, ...typeEntries.map(([, v]) => v))

  const statCards = [
    { label: t('memory.totalEntries'), value: stats.total, icon: Brain },
    {
      label: t('memory.vectorIndex'),
      value: stats.by_type ? Object.keys(stats.by_type).length : 0,
      icon: Hash,
    },
    { label: t('memory.pinnedEntries'), value: 0, icon: Pin },
    { label: t('memory.dreamStatus'), value: 'idle', icon: Activity },
  ]

  return (
    <div className="space-y-6">
      <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
        {statCards.map((s) => (
          <Card key={s.label}>
            <CardContent className="p-4 flex items-center gap-3">
              <s.icon className="h-8 w-8 text-muted-foreground" />
              <div>
                <p className="text-2xl font-bold">{s.value}</p>
                <p className="text-xs text-muted-foreground">{s.label}</p>
              </div>
            </CardContent>
          </Card>
        ))}
      </div>
      <div className="grid gap-6 md:grid-cols-2">
        <Card>
          <CardHeader>
            <CardTitle>{t('memory.tierDistribution')}</CardTitle>
          </CardHeader>
          <CardContent className="space-y-3">
            {tierEntries.length > 0 ? (
              tierEntries.map(([name, value]) => (
                <DistBar
                  key={name}
                  label={t(`memory.${name}`, name)}
                  value={value}
                  max={tierMax}
                  color={TIER_COLORS[name] ?? '#888'}
                />
              ))
            ) : (
              <p className="text-sm text-muted-foreground">{t('memory.noData')}</p>
            )}
          </CardContent>
        </Card>
        <Card>
          <CardHeader>
            <CardTitle>{t('memory.typeDistribution')}</CardTitle>
          </CardHeader>
          <CardContent className="space-y-3">
            {typeEntries.length > 0 ? (
              typeEntries.map(([name, value]) => (
                <DistBar
                  key={name}
                  label={t(`memory.${name}`, name)}
                  value={value}
                  max={typeMax}
                  color="#8884d8"
                />
              ))
            ) : (
              <p className="text-sm text-muted-foreground">{t('memory.noData')}</p>
            )}
          </CardContent>
        </Card>
      </div>
    </div>
  )
}