| 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. */ |
| 8 | export const SESSION_STATES = ["Queued", "Working", "Waiting on helpers", "Needs approval", "Done", "Stopped", "Failed"] as const; |
| 9 | |
| 10 | export type SessionState = (typeof SESSION_STATES)[number]; |
| 11 | |
| 12 | /** How a state reads: its badge tone, and whether it is happening now (a soft pulse). */ |
| 13 | export type SessionChip = { tone: "neutral" | "accent" | "info" | "warn" | "success" | "danger"; live: boolean }; |
| 14 | |
| 15 | const 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. */ |
| 26 | export function sessionChip(state: string | null | undefined): SessionChip { |
| 27 | return CHIPS[String(state ?? "").trim().toLowerCase()] ?? { tone: "neutral", live: false }; |
| 28 | } |