Something went wrong. Try again.
small gleam coding and persistent agent daemon with a detachable cli and a canvas ui forked from okami.mom/albedo
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142import type { Session } from './api';
export type AlertKind = 'finished' | 'attention' | 'mail';export type Mail = { mail_id: string; sender_session_id: string | null; receiver_session_id: string; kind: string };
/** Counts sessions, not turns. A focus clears the unread set. */export class Attention { unread = new Set<string>(); #mail = new Set<string>();
clear() { this.unread.clear(); }
changed(previous: Session | undefined, next: Session, watched: boolean, away: boolean): AlertKind | null { if (!previous || !watched || !away) return null; const blocked = next.status.blocking_reason; if (blocked && JSON.stringify(blocked) !== JSON.stringify(previous.status.blocking_reason)) return this.#mark(next.id, 'attention'); const answerChanged = next.activity.latest_answer?.message_id && next.activity.latest_answer.message_id !== previous.activity.latest_answer?.message_id; if (next.status.phase === 'idle' && (previous.status.phase !== 'idle' || answerChanged)) return this.#mark(next.id, 'finished'); return null; }
mail(mail: Mail, watched: boolean, away: boolean): AlertKind | null { if (this.#mail.has(mail.mail_id)) return null; this.#mail.add(mail.mail_id); if (this.#mail.size > 256) this.#mail.delete(this.#mail.values().next().value!); if (!watched || !away || !mail.sender_session_id || !['message', 'result', 'unreviewed'].includes(mail.kind)) return null; return this.#mark(mail.receiver_session_id, 'mail'); }
prune(ids: Set<string>) { for (const id of this.unread) if (!ids.has(id)) this.unread.delete(id); }
#mark(id: string, kind: AlertKind): AlertKind | null { if (this.unread.has(id)) return null; this.unread.add(id); return kind; }}