Skip to content
44 linesCodeBlameRaw
1import type { AgentLook, AgentStatus } from "@g1t/contracts";
2
3import { type FaceState, faceStateOf } from "./agent-face";
4import { Avatar } from "./ui/avatar";
5
6/** What an agent's face is drawn from. */
7export type AgentLike = {
8 id?: string;
9 /** Its handle, or a member's name. */
10 handle?: string;
11 name?: string;
12 avatar?: string | null;
13 avatar_seed?: string | null;
14 /** Its chosen face; null or missing, the seed's. */
15 look?: AgentLook | null;
16 builtin?: boolean;
17 /** Its status, when the place it shows should show it on its face. */
18 status?: AgentStatus | null;
19};
20
21/** The seed an agent's face grows from: its own, else its id, else its handle. */
22export function seedOf(agent: AgentLike): string {
23 return agent.avatar_seed || agent.id || agent.handle || agent.name || "agent";
24}
25
26/**
27 * An agent's face wherever it appears: the shared Avatar with `agent` set
28 * (components/ui/avatar.tsx), so it is an uploaded picture, g1t's pixel 1,
29 * or its bot face, always with the agent marker. `state` says what the
30 * face is doing; left out, the agent's status decides, if it is known.
31 */
32export function AgentAvatar({ agent, size = 20, state, ring }: { agent: AgentLike; size?: number; state?: FaceState; ring?: string }) {
33 const g1t = agent.builtin || agent.handle === "g1t" || agent.name === "g1t";
34 return (
35 <Avatar
36 name={agent.handle ?? agent.name ?? "agent"}
37 image={agent.avatar}
38 system={g1t}
39 size={size}
40 ring={ring}
41 agent={{ look: agent.look ?? null, seed: seedOf(agent), state: state ?? faceStateOf(agent.status) }}
42 />
43 );
44}