"use client";
import { useRealtime } from "@/lib/realtime-client";
import { useState, useCallback } from "react";
interface WorkflowStep {
stepName: string;
result?: unknown;
}
interface WaitingState {
eventId: string;
message: string;
}
export function useWorkflowWithRealtime() {
const [workflowRunId, setWorkflowRunId] = useState<string | null>(null);
const [steps, setSteps] = useState<WorkflowStep[]>([]);
const [waitingState, setWaitingState] = useState<WaitingState | null>(null);
const [isTriggering, setIsTriggering] = useState(false);
const [isRunFinished, setIsRunFinished] = useState(false);
useRealtime({
enabled: !!workflowRunId,
channels: workflowRunId ? [workflowRunId] : [],
events: [
"workflow.stepFinish",
"workflow.runFinish",
"workflow.waitingForInput",
"workflow.inputResolved",
],
onData({ event, data }) {
if (event === "workflow.stepFinish") {
setSteps((prev) => [
...prev,
{
stepName: data.stepName,
result: data.result,
},
]);
} else if (event === "workflow.runFinish") {
setIsRunFinished(true);
} else if (event === "workflow.inputResolved") {
// Clear waiting state if it matches
setWaitingState((prev) =>
prev?.eventId === data.eventId ? null : prev
);
} else if (event === "workflow.waitingForInput") {
setWaitingState({
eventId: data.eventId,
message: data.message,
});
}
},
});
const trigger = useCallback(async () => {
setIsTriggering(true);
setSteps([]);
setWaitingState(null);
setIsRunFinished(false);
const response = await fetch("/api/trigger", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ workflowType: "human-in-loop" }),
});
const data = await response.json();
setWorkflowRunId(data.workflowRunId);
setIsTriggering(false);
}, []);
const continueWorkflow = useCallback(
async (data: { approved: boolean }) => {
if (!waitingState) {
throw new Error("No workflow waiting for input");
}
const response = await fetch("/api/notify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
eventId: waitingState.eventId,
eventData: data,
}),
});
if (!response.ok) {
throw new Error("Failed to notify workflow");
}
// The waiting state will be cleared when we receive inputResolved event
},
[waitingState]
);
return {
trigger,
continueWorkflow,
isTriggering,
workflowRunId,
steps,
waitingState,
isRunFinished,
};
}