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:
@@ -5,7 +5,11 @@
|
||||
*/
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export type OrchestratorStreamEventName = 'snapshot' | 'traffic' | 'file';
|
||||
export type OrchestratorStreamEventName =
|
||||
| 'snapshot'
|
||||
| 'traffic'
|
||||
| 'file'
|
||||
| 'email';
|
||||
|
||||
export interface OrchestratorStreamEvent {
|
||||
name: OrchestratorStreamEventName | string;
|
||||
@@ -21,7 +25,13 @@ export interface UseOrchestratorStreamOptions {
|
||||
onStatus?: (status: 'connecting' | 'live' | 'error') => void;
|
||||
}
|
||||
|
||||
const NAMED_EVENTS: OrchestratorStreamEventName[] = ['snapshot', 'traffic', 'file'];
|
||||
// Must include every leaf the SSE endpoint emits — the EventSource
|
||||
// silently drops frames whose `event:` name has no listener registered.
|
||||
// New leaves on the bus need a corresponding entry here or the
|
||||
// dashboard ignores them despite the SSE pipe carrying them through.
|
||||
const NAMED_EVENTS: OrchestratorStreamEventName[] = [
|
||||
'snapshot', 'traffic', 'file', 'email',
|
||||
];
|
||||
|
||||
export function useOrchestratorStream({
|
||||
enabled,
|
||||
|
||||
Reference in New Issue
Block a user