Spaces:
Sleeping
Sleeping
File size: 5,586 Bytes
43d708a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 | "use client"
import { useEffect, useRef } from "react"
type ChatMessage = {
agent_id: string
text: string
type?: 'message' | 'death' | 'alliance_proposal' | 'alliance_accept' | 'alliance_reject' | 'leadership_vote' | 'leader_elected' | 'water_collected' | 'fire_extinguished'
to_model?: string
from_model?: string
candidates?: string[]
}
export default function ChatFeed({ messages }: { messages: ChatMessage[] }) {
const bottomRef = useRef<HTMLDivElement>(null)
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: "smooth" })
}, [messages])
function getAgentName(id: string) {
return id.split("/").at(-1)?.split("-")[0].toUpperCase() || id
}
function getAgentColor(name: string) {
let hash = 0
for (let i = 0; i < name.length; i++) {
hash = name.charCodeAt(i) + ((hash << 5) - hash)
}
return `hsl(${hash % 360}, 70%, 60%)`
}
return (
<div className="flex-1 overflow-y-auto py-4 space-y-3 min-h-0 custom-scrollbar">
{messages.map((msg, i) => {
const color = getAgentColor(msg.agent_id)
if (msg.type === 'death') {
return (
<div key={i} className="mx-4 p-2 bg-red-500/10 border-l-2 border-red-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-red-500 uppercase font-bold tracking-widest">
π {getAgentName(msg.agent_id)} was consumed by the fire
</span>
</div>
)
}
if (msg.type === 'alliance_proposal') {
return (
<div key={i} className="mx-4 p-2 bg-yellow-500/10 border-l-2 border-yellow-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-yellow-500 uppercase font-bold tracking-widest">
π€ {getAgentName(msg.agent_id)} proposed an alliance to {msg.to_model ? getAgentName(msg.to_model) : 'someone'}
</span>
</div>
)
}
if (msg.type === 'alliance_accept') {
return (
<div key={i} className="mx-4 p-2 bg-emerald-500/10 border-l-2 border-emerald-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-emerald-400 uppercase font-bold tracking-widest">
β
{getAgentName(msg.agent_id)} accepted the alliance{msg.to_model ? ` with ${getAgentName(msg.to_model)}` : ''}
</span>
</div>
)
}
if (msg.type === 'alliance_reject') {
return (
<div key={i} className="mx-4 p-2 bg-orange-500/10 border-l-2 border-orange-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-orange-400 uppercase font-bold tracking-widest">
β {getAgentName(msg.agent_id)} rejected the alliance{msg.to_model ? ` from ${getAgentName(msg.to_model)}` : ''}
</span>
</div>
)
}
if (msg.type === 'leadership_vote') {
return (
<div key={i} className="mx-4 p-2 bg-purple-500/10 border-l-2 border-purple-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-purple-400 uppercase font-bold tracking-widest">
π³οΈ {getAgentName(msg.agent_id)} voted for {msg.candidates ? getAgentName(msg.candidates[0]) : 'someone'}
</span>
</div>
)
}
if (msg.type === 'leader_elected') {
return (
<div key={i} className="mx-4 p-2 bg-yellow-500/10 border-l-2 border-yellow-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-yellow-400 uppercase font-bold tracking-widest">
π {getAgentName(msg.agent_id)} elected as leader!
</span>
</div>
)
}
if (msg.type === 'water_collected') {
return (
<div key={i} className="mx-4 p-2 bg-cyan-500/10 border-l-2 border-cyan-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-cyan-400 uppercase font-bold tracking-widest">
π§ {getAgentName(msg.agent_id)} collected water!
</span>
</div>
)
}
if (msg.type === 'fire_extinguished') {
return (
<div key={i} className="mx-4 p-2 bg-green-500/10 border-l-2 border-green-500 animate-in slide-in-from-left duration-300">
<span className="font-mono text-[10px] text-green-400 uppercase font-bold tracking-widest">
π₯ Fire being extinguished! Intensity dropping...
</span>
</div>
)
}
return (
<div key={i} className="px-4 group animate-in fade-in duration-500">
<div className="flex items-baseline gap-2">
<span
className="font-mono text-[10px] font-bold shrink-0 px-1.5 rounded bg-white/5"
style={{ color }}
>
{getAgentName(msg.agent_id)}
</span>
<span className="font-mono text-[12px] text-white/80 leading-relaxed break-words">
{msg.text}
</span>
</div>
</div>
)
})}
<div ref={bottomRef} />
</div>
)
}
|