Add Hermes operations management layer

This commit is contained in:
Yahya Alhinai
2026-06-28 02:17:23 +00:00
parent 89893110f1
commit 4253921532
29 changed files with 1017 additions and 71 deletions
+19 -4
View File
@@ -1,18 +1,26 @@
import { useEffect, useState, useCallback } from 'react';
import { RoomEvent, type Room } from 'livekit-client';
import type { DataMessage, Intervention, InterventionStatus } from '@podman/shared';
import type { DataMessage, HermesMessage, Intervention, InterventionStatus } from '@podman/shared';
import { DATA_TOPIC } from '@podman/shared';
import { postOutcome } from '../lib/api';
import { createSyncPr, postOutcome } from '../lib/api';
export function useInterventions(room: Room | null) {
const [active, setActive] = useState<Intervention | null>(null);
const [hermes, setHermes] = useState<HermesMessage | null>(null);
const [voiceCue, setVoiceCue] = useState<string | null>(null);
const [actionUrl, setActionUrl] = useState<string | null>(null);
useEffect(() => {
if (!room) return;
const onData = (payload: Uint8Array, _p: unknown, _k: unknown, topic?: string) => {
if (topic !== DATA_TOPIC) return;
const msg = JSON.parse(new TextDecoder().decode(payload)) as DataMessage;
if (msg.type === 'COLLISION') setActive(msg.intervention);
if (msg.type === 'COLLISION') {
setActive(msg.intervention);
setActionUrl(null);
}
if (msg.type === 'HERMES_MESSAGE') setHermes(msg.message);
if (msg.type === 'VOICE_CUE') setVoiceCue(msg.text);
};
room.on(RoomEvent.DataReceived, onData);
return () => {
@@ -23,6 +31,13 @@ export function useInterventions(room: Room | null) {
const respond = useCallback(
async (status: InterventionStatus, accepted: boolean) => {
if (!active) return;
if (accepted && active.suggestedAction.kind === 'open_sync_pr') {
const pr = await createSyncPr({
file: String(active.suggestedAction.params?.file ?? ''),
summary: String(active.suggestedAction.params?.summary ?? active.message),
});
setActionUrl(pr.url);
}
await postOutcome({
interventionId: active.id,
collisionId: active.collisionId,
@@ -37,5 +52,5 @@ export function useInterventions(room: Room | null) {
[active],
);
return { active, respond };
return { active, hermes, voiceCue, actionUrl, respond };
}