import { useState, useEffect } from 'react' const API_BASE = import.meta.env.VITE_BRAIN_API ?? '' interface TierData { description: string coach_level: string distillation: boolean agents_new: string[] agents_total: string[] agents_count: number sessions_new: string[] sessions_total: string[] sessions_count: number } interface TiersResponse { version: string tiers: Record tier_chain: string[] } const TIER_COLORS: Record = { free: { emoji: '๐ŸŸข', border: '#22c55e', bg: 'rgba(34,197,94,0.06)', text: '#4ade80' }, featured: { emoji: '๐Ÿ”ต', border: '#3b82f6', bg: 'rgba(59,130,246,0.06)', text: '#60a5fa' }, pro: { emoji: '๐ŸŸ ', border: '#f59e0b', bg: 'rgba(245,158,11,0.06)', text: '#fbbf24' }, full: { emoji: '๐ŸŸฃ', border: '#a855f7', bg: 'rgba(168,85,247,0.06)', text: '#c084fc' }, } const TIER_TITLES: Record = { free: 'Tu forkes, ca marche', featured: 'Le brain te connait', pro: "L'atelier complet", full: 'Ton brain, tes regles', } const COACH_LABELS: Record = { boot: 'Observation โ€” intervient sur risque critique uniquement', full: 'Mentorat complet โ€” bilans, objectifs, progression', L2: 'Mentorat long terme โ€” anticipe, challenge, milestones', } // Comparatif โ€” vue multi-tiers export function TierComparatif() { const [data, setData] = useState(null) const [error, setError] = useState(null) useEffect(() => { fetch(`${API_BASE}/brain-compose/tiers`) .then(r => r.json()) .then(setData) .catch(e => setError(e.message)) }, []) if (error) return
Erreur: {error}
if (!data) return
Chargement...
return (

Comparatif tiers

Donnees live depuis brain-compose.yml v{data.version}

{data.tier_chain.map(tierName => { const tier = data.tiers[tierName] if (!tier) return null const colors = TIER_COLORS[tierName] return (

{colors.emoji} {tierName} โ€” {TIER_TITLES[tierName]}

{tier.agents_count} agents. {tier.sessions_count} sessions. {tier.distillation && Distillation RAG active.}

{tier.description}

) })}

Detail par tier

{data.tier_chain.map(tierName => { const tier = data.tiers[tierName] if (!tier) return null const colors = TIER_COLORS[tierName] return (

{colors.emoji} {tierName}

Sessions ({tier.sessions_count}) :

{tier.sessions_total.join(' ยท ')}

Agents ({tier.agents_count}) :

{tier.agents_total.join(' ยท ')}

Coach : {COACH_LABELS[tier.coach_level] || tier.coach_level}

) })}
) } // Vue single tier export function TierSingle({ tierName }: { tierName: string }) { const [data, setData] = useState(null) const [error, setError] = useState(null) useEffect(() => { fetch(`${API_BASE}/brain-compose/tiers`) .then(r => r.json()) .then(setData) .catch(e => setError(e.message)) }, []) if (error) return
Erreur: {error}
if (!data) return
Chargement...
const tier = data.tiers[tierName] if (!tier) return
Tier "{tierName}" introuvable
const colors = TIER_COLORS[tierName] const chain = data.tier_chain const tierIndex = chain.indexOf(tierName) // Trouver les agents/sessions "nouveaux" par rapport au tier precedent const prevTier = tierIndex > 0 ? data.tiers[chain[tierIndex - 1]] : null const prevAgents = new Set(prevTier?.agents_total || []) const newAgents = tier.agents_total.filter(a => !prevAgents.has(a)) const prevSessions = new Set(prevTier?.sessions_total || []) const newSessions = tier.sessions_total.filter(s => !prevSessions.has(s)) // Tier suivant pour le "ce que tu n'as pas encore" const nextTierName = tierIndex < chain.length - 1 ? chain[tierIndex + 1] : null const nextTier = nextTierName ? data.tiers[nextTierName] : null return (

{colors.emoji} {tierName} โ€” Ce que tu as

Donnees live depuis brain-compose.yml v{data.version}

{tier.agents_count} agents. {tier.sessions_count} sessions. {tier.distillation && Distillation RAG active.}

{tier.description}


Sessions {tierIndex > 0 && newSessions.length > 0 ? `(+${newSessions.length} nouvelles)` : ''}

{tierIndex > 0 && newSessions.length > 0 && ( <>

Ajoutees a ce tier :

    {newSessions.map(s =>
  • {s}
  • )}
)}

Toutes les sessions disponibles :

{tier.sessions_total.join(' ยท ')}


Agents {tierIndex > 0 && newAgents.length > 0 ? `(+${newAgents.length} nouveaux)` : ''}

{tierIndex > 0 && newAgents.length > 0 && ( <>

Ajoutes a ce tier :

{newAgents.join(' ยท ')}

)}

Tous les agents disponibles ({tier.agents_count}) :

{tier.agents_total.join(' ยท ')}


Coach

{tier.coach_level} โ€” {COACH_LABELS[tier.coach_level] || tier.coach_level}

{nextTier && nextTierName && ( <>

Ce que tu n'as pas encore

{TIER_COLORS[nextTierName].emoji} {nextTierName} {' '}te donne : +{nextTier.agents_count - tier.agents_count} agents, +{nextTier.sessions_count - tier.sessions_count} sessions.

{nextTier.description}

)} {tierName === 'full' && ( <>

Tu as tout

C'est ton brain. Tu peux modifier n'importe quel agent, forger les tiens, restructurer le kernel. Le seul gate c'est toi.

)}
) }