feat(web): emailgen events in Orchestrator page

The SSE pipe at /orchestrator/events/stream was already streaming
'orchestrator.email.{decky_uuid}' events (the subscription is for the
'orchestrator.>' wildcard), but the consumer side dropped them on the
floor.  Three fixes to close the loop:

* useOrchestratorStream.ts now registers an 'email' SSE listener — the
  EventSource silently ignores frames whose event name has no listener,
  so missing this entry meant every email frame was dropped before
  reaching the page's onEvent handler.

* /api/v1/orchestrator/events accepts kind=email and dispatches to
  list_orchestrator_emails, adapting rows to the existing wire shape:
  subject -> action, sender_email -> src_decky_uuid, recipient_email
  -> dst_decky_uuid, plus email-specific extras (thread_id, language,
  mail_decky_uuid, message_id, in_reply_to) ride along as top-level
  keys.

* Orchestrator.tsx gains an 'email' tab in the kind filter and a
  branch in the row renderer / inspector that:
   - shows full sender / recipient (no UUID truncation),
   - chips the language code next to the subject,
   - relabels ACTION as SUBJECT in the inspector and surfaces
     thread / in-reply-to / mail-decky details.

The 'all' tab continues to show traffic+file only (today's behavior);
operators see emails by switching to the email tab.  A union view at
the API layer is the obvious follow-up but not necessary for now.
This commit is contained in:
2026-04-26 22:56:48 -04:00
parent f97ec4c2c1
commit 818aebadfc
6 changed files with 282 additions and 31 deletions

View File

@@ -212,6 +212,10 @@
}
.orchestrator-root .kind-chip.traffic { border-color: var(--matrix); color: var(--matrix); }
.orchestrator-root .kind-chip.file { border-color: var(--violet); color: var(--violet); }
/* Emailgen rows — distinct accent so the eye separates LLM-driven mail
from SSH/file activity at a glance. Falls back to --accent when the
theme doesn't define --amber. */
.orchestrator-root .kind-chip.email { border-color: var(--amber, var(--accent)); color: var(--amber, var(--accent)); }
/* OK indicator */
.orchestrator-root .ok-yes { color: var(--matrix); font-weight: 700; }