);
}
/**
* Polling component that checks task status and shows player when complete
*/
function PodcastTaskPoller({ taskId, title }: { taskId: string; title: string }) {
const [taskStatus, setTaskStatus] = useState({ status: "processing" });
const pollingRef = useRef(null);
// Set active podcast state when this component mounts
useEffect(() => {
setActivePodcastTaskId(taskId);
// Clear when component unmounts
return () => {
// Only clear if this task is still the active one
clearActivePodcastTaskId();
};
}, [taskId]);
// Poll for task status
useEffect(() => {
const pollStatus = async () => {
try {
const response = await baseApiService.get(
`/api/v1/podcasts/task/${taskId}/status`
);
setTaskStatus(response);
// Stop polling if task is complete or errored
if (response.status !== "processing") {
if (pollingRef.current) {
clearInterval(pollingRef.current);
pollingRef.current = null;
}
// Clear the active podcast state when task completes
clearActivePodcastTaskId();
}
} catch (err) {
console.error("Error polling task status:", err);
// Don't stop polling on network errors, continue polling
}
};
// Initial poll
pollStatus();
// Poll every 5 seconds
pollingRef.current = setInterval(pollStatus, 5000);
return () => {
if (pollingRef.current) {
clearInterval(pollingRef.current);
}
};
}, [taskId]);
// Show loading state while processing
if (taskStatus.status === "processing") {
return ;
}
// Show error state
if (taskStatus.status === "error") {
return ;
}
// Show player when complete
if (taskStatus.status === "success" && taskStatus.podcast_id) {
return (
);
}
// Fallback
return ;
}
/**
* Generate Podcast Tool UI Component
*
* This component is registered with assistant-ui to render custom UI
* when the generate_podcast tool is called by the agent.
*
* It polls for task completion and auto-updates when the podcast is ready.
*/
export const GeneratePodcastToolUI = makeAssistantToolUI<
GeneratePodcastArgs,
GeneratePodcastResult
>({
toolName: "generate_podcast",
render: function GeneratePodcastUI({ args, result, status }) {
const title = args.podcast_title || "SurfSense Podcast";
// Loading state - tool is still running (agent processing)
if (status.type === "running" || status.type === "requires-action") {
return ;
}
// Incomplete/cancelled state
if (status.type === "incomplete") {
if (status.reason === "cancelled") {
return (
Podcast generation cancelled
);
}
if (status.reason === "error") {
return (
);
}
}
// No result yet
if (!result) {
return ;
}
// Error result
if (result.status === "error") {
return ;
}
// Already generating - show simple warning, don't create another poller
// The FIRST tool call will display the podcast when ready
if (result.status === "already_generating") {
return (
Podcast already in progress
Please wait for the current podcast to complete.
);
}
// Processing - poll for completion
if (result.status === "processing" && result.task_id) {
return ;
}
// Success with podcast_id (direct result, not via polling)
if (result.status === "success" && result.podcast_id) {
return (
);
}
// Fallback - missing required data
return ;
},
});