Skip to content
28 linesCodeBlameRaw
1/**
2 * An agent session's live card in chat (`card.kind === "session"`): the
3 * agent posts it when the session starts and changes it in place as the
4 * session moves (`message.updated`), so its state chip is always current.
5 */
6
7/** The states an agent session's card shows. */
8export const SESSION_STATES = ["Queued", "Working", "Waiting on helpers", "Needs approval", "Done", "Stopped", "Failed"] as const;
9
10export type SessionState = (typeof SESSION_STATES)[number];
11
12/** How a state reads: its badge tone, and whether it is happening now (a soft pulse). */
13export type SessionChip = { tone: "neutral" | "accent" | "info" | "warn" | "success" | "danger"; live: boolean };
14
15const CHIPS: Record<string, SessionChip> = {
16 queued: { tone: "neutral", live: false },
17 working: { tone: "accent", live: true },
18 "waiting on helpers": { tone: "info", live: true },
19 "needs approval": { tone: "warn", live: false },
20 done: { tone: "success", live: false },
21 stopped: { tone: "neutral", live: false },
22 failed: { tone: "danger", live: false },
23};
24
25/** A session card's state chip; a state it does not know reads quietly. */
26export function sessionChip(state: string | null | undefined): SessionChip {
27 return CHIPS[String(state ?? "").trim().toLowerCase()] ?? { tone: "neutral", live: false };
28}