NeerajCodz commited on
Commit
fa81e4d
·
1 Parent(s): 4afa792

feat: add frontend WebSocket integration with episode progress tracking

Browse files
frontend/src/hooks/useEpisodeProgress.ts ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { useEffect, useState } from 'react';
2
+ import { useWebSocket } from '@/hooks/useWebSocket';
3
+ import type { WebSocketMessage } from '@/types';
4
+
5
+ interface EpisodeProgressProps {
6
+ episodeId: string | null;
7
+ onProgressUpdate?: (data: WebSocketMessage) => void;
8
+ onCompletion?: (data: WebSocketMessage) => void;
9
+ onError?: (error: string) => void;
10
+ }
11
+
12
+ export function useEpisodeProgress({
13
+ episodeId,
14
+ onProgressUpdate,
15
+ onCompletion,
16
+ onError,
17
+ }: EpisodeProgressProps) {
18
+ const [currentStep, setCurrentStep] = useState(0);
19
+ const [totalReward, setTotalReward] = useState(0);
20
+ const [progress, setProgress] = useState(0);
21
+ const [lastAction, setLastAction] = useState<string>('');
22
+ const [isCompleted, setIsCompleted] = useState(false);
23
+ const [error, setError] = useState<string | null>(null);
24
+
25
+ const { isConnected, lastMessage } = useWebSocket(
26
+ episodeId ? `/ws/episode/${episodeId}` : '',
27
+ {
28
+ autoConnect: !!episodeId,
29
+ onMessage: (message: WebSocketMessage) => {
30
+ console.log('WebSocket message:', message);
31
+
32
+ switch (message.type) {
33
+ case 'connected':
34
+ console.log('Connected to episode:', message.episode_id);
35
+ break;
36
+
37
+ case 'progress':
38
+ if (message.step !== undefined) setCurrentStep(message.step);
39
+ if (message.reward !== undefined) setTotalReward(prev => prev + message.reward!);
40
+ if (message.progress !== undefined) setProgress(message.progress);
41
+ if (message.action_type) setLastAction(message.action_type);
42
+ onProgressUpdate?.(message);
43
+ break;
44
+
45
+ case 'completion':
46
+ setIsCompleted(true);
47
+ if (message.total_reward !== undefined) setTotalReward(message.total_reward);
48
+ setProgress(100);
49
+ onCompletion?.(message);
50
+ break;
51
+
52
+ case 'error':
53
+ const errorMsg = message.error || 'Unknown error occurred';
54
+ setError(errorMsg);
55
+ onError?.(errorMsg);
56
+ break;
57
+ }
58
+ },
59
+ }
60
+ );
61
+
62
+ // Reset state when episode changes
63
+ useEffect(() => {
64
+ if (episodeId) {
65
+ setCurrentStep(0);
66
+ setTotalReward(0);
67
+ setProgress(0);
68
+ setLastAction('');
69
+ setIsCompleted(false);
70
+ setError(null);
71
+ }
72
+ }, [episodeId]);
73
+
74
+ return {
75
+ isConnected,
76
+ currentStep,
77
+ totalReward,
78
+ progress,
79
+ lastAction,
80
+ isCompleted,
81
+ error,
82
+ lastMessage,
83
+ };
84
+ }
85
+
86
+ export default useEpisodeProgress;
frontend/src/types/index.ts CHANGED
@@ -205,10 +205,24 @@ export interface SystemSettings {
205
  }
206
 
207
  export interface WebSocketMessage {
208
- type: 'observation' | 'action' | 'reward' | 'agent_update' | 'episode_status' | 'error';
209
- payload: unknown;
210
- timestamp: string;
211
- episodeId?: string;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  }
213
 
214
  export interface APIResponse<T> {
 
205
  }
206
 
207
  export interface WebSocketMessage {
208
+ type: 'connected' | 'ping' | 'pong' | 'progress' | 'error' | 'completion';
209
+ episode_id?: string;
210
+ message?: string;
211
+ // Progress update fields
212
+ step?: number;
213
+ action_type?: string;
214
+ reward?: number;
215
+ progress?: number;
216
+ // Error fields
217
+ error?: string;
218
+ details?: Record<string, unknown>;
219
+ // Completion fields
220
+ success?: boolean;
221
+ total_reward?: number;
222
+ extracted_data?: Record<string, unknown>;
223
+ // Metadata
224
+ timestamp?: number;
225
+ payload?: unknown;
226
  }
227
 
228
  export interface APIResponse<T> {