import type { BeastSnapshot, EntitySnapshot, HouseSnapshot, ResourceNodeSnapshot, } from "../types"; import { TooltipLabel } from "./TooltipLabel"; type AgentPanelProps = { entity: EntitySnapshot | null; beast?: BeastSnapshot | null; resource?: ResourceNodeSnapshot | null; house?: HouseSnapshot | null; entities?: EntitySnapshot[]; onSelectEntity?: (id: string) => void; }; export function AgentPanel({ entity, beast = null, resource = null, house = null, entities = [], onSelectEntity, }: AgentPanelProps) { if (beast) { return ; } if (resource) { return ; } if (house) { return ; } const selectedName = entity?.label ?? "No NPC"; const selectedRole = entity ? [entity.country_id, entity.special_status ?? entity.role].filter(Boolean).join(" / ") : "world"; return ( ); } function BeastPanel({ beast }: { beast: BeastSnapshot }) { const suffix = beast.id.replace(/^beast[_-]?/, ""); const beastName = suffix ? `Beast ${suffix}` : "Beast"; const healthLabel = `${beast.health} / ${beast.max_health} HP`; const positionLabel = `x ${beast.position.x.toFixed(1)} / z ${beast.position.z.toFixed(1)}`; return ( ); } function ResourcePanel({ resource }: { resource: ResourceNodeSnapshot }) { const title = resource.type ? `${resource.type.charAt(0).toUpperCase()}${resource.type.slice(1)} node` : "Resource node"; const amountLabel = resource.max_amount ? `${resource.amount} / ${resource.max_amount}` : `${resource.amount} left`; const positionLabel = `x ${resource.position.x.toFixed(1)} / z ${resource.position.z.toFixed(1)}`; return ( ); } type HousePanelProps = { house: HouseSnapshot; entities: EntitySnapshot[]; onSelectEntity?: (id: string) => void; }; function HousePanel({ house, entities, onSelectEntity }: HousePanelProps) { const isComplete = house.state === "completed"; const suffix = house.id.replace(/^house[_-]?/, ""); const title = suffix ? `Home ${suffix}` : "Home"; const buildRatio = Math.min(1, house.build_progress / 10); const statusLabel = isComplete ? house.hp < house.max_hp ? "damaged" : "intact" : `building ${Math.round(buildRatio * 100)}%`; const positionLabel = `x ${house.position.x.toFixed(1)} / z ${house.position.z.toFixed(1)}`; return ( ); } type HouseResidentListProps = { label: string; ids: string[]; emptyLabel: string; entities: EntitySnapshot[]; onSelectEntity?: (id: string) => void; }; function HouseResidentList({ label, ids, emptyLabel, entities, onSelectEntity }: HouseResidentListProps) { return (
{label}
{ids.length === 0 ? ( {emptyLabel} ) : ( ids.map((id) => { const npc = entities.find((entity) => entity.id === id); return ( ); }) )}
); } type AgentDetailsProps = { entity: EntitySnapshot; }; function AgentDetails({ entity }: AgentDetailsProps) { return ( <> ); } function SurvivalReadout({ entity }: { entity: EntitySnapshot }) { const { hunger, fear, safety, age, max_age, importance, goal, inventory } = entity.state; if ( hunger === undefined && fear === undefined && safety === undefined && age === undefined && importance === undefined && goal === undefined && !inventory ) { return null; } const inventoryLabel = inventory ? `food ${inventory.food} / herbs ${inventory.herbs} / wood ${inventory.wood} / coins ${inventory.coins} / wpn ${inventory.weapon}` : "-"; return (
{hunger !== undefined ? ( ) : null} {fear !== undefined ? ( ) : null} {safety !== undefined ? ( ) : null} {age !== undefined && max_age !== undefined ? ( ) : null} {importance !== undefined ? ( ) : null} {goal ? : null}
); } function AgentReadout({ entity }: { entity: EntitySnapshot }) { const selectedHealth = `${entity.state.health} / ${entity.state.max_health} HP`; const selectedAttackDamage = `DMG ${entity.state.attack_damage}`; const selectedPosition = `x ${entity.position.x.toFixed(1)} / z ${entity.position.z.toFixed(1)}`; return (
); } function ThinkingBlock({ entity }: { entity: EntitySnapshot }) { const reasoning = entity.state.last_reasoning; if (!reasoning || !reasoning.trim()) { return null; } const tick = entity.state.last_reasoning_tick; return (

{reasoning}

); } function RelationshipList({ entity }: { entity: EntitySnapshot }) { const relationships = Object.entries(entity.state.relationships ?? {}) .sort((left, right) => Math.abs(right[1]) - Math.abs(left[1]) || left[0].localeCompare(right[0])) .slice(0, 3); if (relationships.length === 0) { return null; } return (
{relationships.map(([id, trust]) => ( = 0 ? "+" : ""}${trust.toFixed(2)}`} /> ))}
); } function MemoryList({ entity }: { entity: EntitySnapshot }) { const recentEpisodes = entity.state.recent_episodes ?? []; return (
{entity.state.memory_summary ? (

{entity.state.memory_summary}

) : null} {recentEpisodes .slice() .reverse() .map((episode) => (

{episode.summary}

))} {entity.state.memories .slice() .reverse() .map((memory) => (

{memory.text}

))}
); } function EmptyAgentReadout() { return (
); }