fix: fix review comments

This commit is contained in:
Abhishek Kumar 2026-05-21 15:17:14 +05:30
parent dfee942f9a
commit c7e0d06a2b
13 changed files with 477 additions and 253 deletions

View file

@ -78,6 +78,8 @@ export function useTextChatSession({
setSession(toTextChatSession(response.data));
setDraft("");
} catch (error) {
setSession(null);
setStarted(false);
toast.error(getErrorMessage(error));
} finally {
setCreatingSession(false);

View file

@ -1,186 +0,0 @@
import { Loader2 } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";
import { getWorkflowRunApiV1WorkflowWorkflowIdRunsRunIdGet } from "@/client/sdk.gen";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { ConversationRailFrame, RealtimeFeedback } from "@/components/workflow/conversation";
import { useAuth } from "@/lib/auth";
import {
ApiKeyErrorDialog,
AudioControls,
ConnectionStatus,
WorkflowConfigErrorDialog
} from "./components";
import { useWebSocketRTC } from "./hooks";
const RUN_SHELL_HEIGHT_CLASS = "h-[calc(100svh-49px)] min-h-[calc(100svh-49px)] max-h-[calc(100svh-49px)]";
const BrowserCall = ({ workflowId, workflowRunId, initialContextVariables }: {
workflowId: number,
workflowRunId: number,
initialContextVariables?: Record<string, string> | null
}) => {
const router = useRouter();
const auth = useAuth();
const [accessToken, setAccessToken] = useState<string | null>(null);
const [checkingForRecording, setCheckingForRecording] = useState(false);
// Get access token for WebSocket connection (non-SDK usage)
useEffect(() => {
if (auth.isAuthenticated && !auth.loading) {
auth.getAccessToken().then(setAccessToken);
}
}, [auth]);
const {
audioRef,
audioInputs,
selectedAudioInput,
setSelectedAudioInput,
connectionActive,
permissionError,
isCompleted,
apiKeyModalOpen,
setApiKeyModalOpen,
apiKeyError,
apiKeyErrorCode,
workflowConfigError,
workflowConfigModalOpen,
setWorkflowConfigModalOpen,
connectionStatus,
start,
stop,
isStarting,
getAudioInputDevices,
feedbackMessages,
} = useWebSocketRTC({ workflowId, workflowRunId, accessToken, initialContextVariables });
// Poll for recording availability after call ends
useEffect(() => {
if (!isCompleted || !auth.isAuthenticated) return;
setCheckingForRecording(true);
const intervalId = setInterval(async () => {
try {
const response = await getWorkflowRunApiV1WorkflowWorkflowIdRunsRunIdGet({
path: {
workflow_id: workflowId,
run_id: workflowRunId,
},
});
if (response.data?.transcript_url || response.data?.recording_url) {
setCheckingForRecording(false);
clearInterval(intervalId);
// Refresh the page to show the recording
window.location.reload();
}
} catch (error) {
console.error('Error checking for recording:', error);
}
}, 5000); // Check every 5 seconds
// Clean up after 2 minutes
const timeoutId = setTimeout(() => {
clearInterval(intervalId);
setCheckingForRecording(false);
}, 120000);
return () => {
clearInterval(intervalId);
clearTimeout(timeoutId);
};
}, [isCompleted, auth.isAuthenticated, workflowId, workflowRunId]);
const navigateToCredits = () => {
router.push('/api-keys');
};
const navigateToModelConfig = () => {
router.push('/model-configurations');
};
const navigateToWorkflow = () => {
router.push(`/workflow/${workflowId}`)
}
return (
<>
<div className={`flex ${RUN_SHELL_HEIGHT_CLASS} min-h-0 w-full overflow-hidden bg-background`}>
<div className="min-w-0 flex-1 overflow-y-auto">
<div className="flex min-h-full items-center justify-center px-8 py-8">
<Card className="w-full max-w-xl">
<CardHeader>
<CardTitle>Call Voice Agent</CardTitle>
</CardHeader>
<CardContent>
{isCompleted && checkingForRecording ? (
<div className="flex flex-col items-center justify-center space-y-4 p-8">
<Loader2 className="h-8 w-8 animate-spin text-primary" />
<div className="text-center space-y-2">
<p className="text-foreground font-medium">Processing your call</p>
<p className="text-sm text-muted-foreground">Fetching transcript and recording...</p>
</div>
</div>
) : (
<>
<AudioControls
audioInputs={audioInputs}
selectedAudioInput={selectedAudioInput}
setSelectedAudioInput={setSelectedAudioInput}
isCompleted={isCompleted}
connectionActive={connectionActive}
permissionError={permissionError}
start={start}
stop={stop}
isStarting={isStarting}
getAudioInputDevices={getAudioInputDevices}
/>
<ConnectionStatus
connectionStatus={connectionStatus}
/>
</>
)}
</CardContent>
<audio ref={audioRef} autoPlay playsInline className="hidden" />
</Card>
</div>
</div>
<div className="h-full min-h-0 w-[420px] shrink-0 border-l border-border bg-background p-5">
<ConversationRailFrame className="h-full">
<RealtimeFeedback
mode="live"
messages={feedbackMessages}
isCallActive={connectionActive}
isCallCompleted={isCompleted}
/>
</ConversationRailFrame>
</div>
</div>
<ApiKeyErrorDialog
open={apiKeyModalOpen}
onOpenChange={setApiKeyModalOpen}
error={apiKeyError}
errorCode={apiKeyErrorCode}
onNavigateToCredits={navigateToCredits}
onNavigateToModelConfig={navigateToModelConfig}
/>
<WorkflowConfigErrorDialog
open={workflowConfigModalOpen}
onOpenChange={setWorkflowConfigModalOpen}
error={workflowConfigError}
onNavigateToWorkflow={navigateToWorkflow}
/>
</>
);
};
export default BrowserCall;

View file

@ -6,7 +6,6 @@ import { useParams } from 'next/navigation';
import posthog from 'posthog-js';
import { useEffect, useRef, useState } from 'react';
import BrowserCall from '@/app/workflow/[workflowId]/run/[runId]/BrowserCall';
import WorkflowLayout from '@/app/workflow/WorkflowLayout';
import { getWorkflowRunApiV1WorkflowWorkflowIdRunsRunIdGet } from '@/client/sdk.gen';
import { MediaPreviewButton, MediaPreviewDialog } from '@/components/MediaPreviewDialog';
@ -201,7 +200,7 @@ export default function WorkflowRunPage() {
let returnValue = null;
const isTextChatRun = workflowRun?.mode === WORKFLOW_RUN_MODES.TEXTCHAT;
const showHistoricalRunView = Boolean(workflowRun?.is_completed || isTextChatRun);
const showRunDetailsView = Boolean(workflowRun?.is_completed || isTextChatRun);
if (isLoading) {
returnValue = (
@ -225,7 +224,7 @@ export default function WorkflowRunPage() {
</div>
);
}
else if (showHistoricalRunView) {
else if (showRunDetailsView) {
returnValue = (
<div className={`flex ${RUN_SHELL_HEIGHT_CLASS} min-h-0 w-full overflow-hidden bg-background`}>
<div className="min-w-0 flex-1 overflow-y-auto">
@ -366,23 +365,25 @@ export default function WorkflowRunPage() {
);
}
else {
returnValue =
<BrowserCall
workflowId={Number(params.workflowId)}
workflowRunId={Number(params.runId)}
initialContextVariables={
workflowRun?.initial_context
? Object.fromEntries(
Object.entries(workflowRun.initial_context).map(([key, value]) => [
key,
typeof value === 'object' && value !== null
? JSON.stringify(value)
: String(value)
])
)
: null
}
/>
returnValue = (
<div className="flex h-full items-center justify-center p-6">
<Card className="w-full max-w-xl border-border">
<CardHeader className="space-y-2">
<CardTitle className="text-2xl">Run Details Unavailable</CardTitle>
<p className="text-sm text-muted-foreground">
This run does not have a details view yet. Go back to the workflow to continue testing or make changes.
</p>
</CardHeader>
<CardFooter>
<Button asChild className="gap-2">
<Link href={`/workflow/${params.workflowId}`}>
Customize Agent
</Link>
</Button>
</CardFooter>
</Card>
</div>
);
}
return (
@ -391,7 +392,7 @@ export default function WorkflowRunPage() {
{dialog}
{/* Onboarding Tooltip for Customize Workflow */}
{showHistoricalRunView && (
{showRunDetailsView && (
<OnboardingTooltip
title='Customize Your Workflow'
targetRef={customizeButtonRef}