| | import { useAgentStore } from '@/stores/agentStore';
|
| | import { uploadTraceToModal } from '@/services/api';
|
| | import { getTraceExportData } from '@/services/jsonExporter';
|
| | import { AgentTrace, AgentTraceMetadata, WebSocketEvent } from '@/types/agent';
|
| | import { useCallback, useEffect } from 'react';
|
| | import { useWebSocket } from './useWebSocket';
|
| |
|
| | interface UseAgentWebSocketOptions {
|
| | url: string;
|
| | }
|
| |
|
| | export const useAgentWebSocket = ({ url }: UseAgentWebSocketOptions) => {
|
| | const {
|
| | setTrace,
|
| | traceId,
|
| | setTraceId,
|
| | updateTraceWithStep,
|
| | completeTrace,
|
| | setIsAgentProcessing,
|
| | setIsConnectingToE2B,
|
| | setVncUrl,
|
| | setError,
|
| | setIsConnected,
|
| | selectedModelId,
|
| | resetAgent,
|
| | } = useAgentStore();
|
| |
|
| |
|
| | const handleWebSocketMessage = useCallback(
|
| | (event: WebSocketEvent) => {
|
| | console.log('WebSocket event received:', event);
|
| |
|
| | switch (event.type) {
|
| | case 'agent_start': {
|
| |
|
| | resetAgent();
|
| |
|
| | setIsAgentProcessing(true);
|
| | setIsConnectingToE2B(true);
|
| | setError(undefined);
|
| |
|
| |
|
| | const traceWithMetadata = {
|
| | ...event.agentTrace,
|
| | traceMetadata: event.agentTrace.traceMetadata ? {
|
| | ...event.agentTrace.traceMetadata,
|
| | maxSteps: event.agentTrace.traceMetadata.maxSteps > 0
|
| | ? event.agentTrace.traceMetadata.maxSteps
|
| | : 200,
|
| | } : {
|
| | traceId: event.agentTrace.id,
|
| | inputTokensUsed: 0,
|
| | outputTokensUsed: 0,
|
| | duration: 0,
|
| | numberOfSteps: 0,
|
| | maxSteps: 200,
|
| | completed: false,
|
| | final_state: null,
|
| | },
|
| | };
|
| |
|
| | setTrace(traceWithMetadata);
|
| | console.log('Agent start received:', traceWithMetadata);
|
| | break;
|
| | }
|
| |
|
| | case 'agent_progress':
|
| |
|
| | setIsConnectingToE2B(false);
|
| | updateTraceWithStep(event.agentStep, event.traceMetadata);
|
| | console.log('Agent progress received:', event.agentStep);
|
| | break;
|
| |
|
| | case 'agent_complete':
|
| | setIsAgentProcessing(false);
|
| | setIsConnectingToE2B(false);
|
| | completeTrace(event.traceMetadata, event.final_state);
|
| | console.log('Agent complete received:', event.traceMetadata, 'Final state:', event.final_state);
|
| |
|
| |
|
| |
|
| | setTimeout(() => {
|
| | const state = useAgentStore.getState();
|
| | const trace = state.trace;
|
| | const steps = state.trace?.steps || [];
|
| | const finalStep = state.finalStep;
|
| | const metadata = state.trace?.traceMetadata;
|
| |
|
| | if (trace && !trace.isRunning) {
|
| | console.log('🚀 Auto-uploading trace after task completion...');
|
| | const traceData = getTraceExportData(trace, steps, metadata, finalStep);
|
| | uploadTraceToModal(traceData)
|
| | .then((result) => {
|
| | if (result.success) {
|
| | console.log('✅ Trace auto-uploaded successfully:', result);
|
| | } else {
|
| | console.warn('⚠️ Trace auto-upload failed:', result.error);
|
| | }
|
| | })
|
| | .catch((error) => {
|
| | console.error('❌ Error auto-uploading trace:', error);
|
| | });
|
| | }
|
| | }, 100);
|
| | break;
|
| |
|
| | case 'agent_error':
|
| | setIsAgentProcessing(false);
|
| | setIsConnectingToE2B(false);
|
| | setError(event.error);
|
| | console.error('Agent error received:', event.error);
|
| | break;
|
| |
|
| | case 'vnc_url_set':
|
| | setIsConnectingToE2B(false);
|
| | setVncUrl(event.vncUrl);
|
| | console.log('VNC URL set received:', event.vncUrl);
|
| | break;
|
| |
|
| | case 'vnc_url_unset':
|
| | setVncUrl('');
|
| | console.log('VNC URL unset received');
|
| | break;
|
| |
|
| | case 'heartbeat':
|
| | console.log('Heartbeat received:', event);
|
| | setTraceId(event.uuid);
|
| | console.log('TraceId set from backend:', event.uuid);
|
| | break;
|
| |
|
| | }
|
| | },
|
| | [setTrace, updateTraceWithStep, completeTrace, setIsAgentProcessing, setIsConnectingToE2B, setVncUrl, setError, resetAgent, setTraceId, traceId]
|
| | );
|
| |
|
| |
|
| | const handleWebSocketError = useCallback(() => {
|
| |
|
| | console.error('WebSocket connection error');
|
| | }, []);
|
| |
|
| |
|
| | const { isConnected, connectionState, sendMessage, manualReconnect } = useWebSocket({
|
| | url,
|
| | onMessage: handleWebSocketMessage,
|
| | onError: handleWebSocketError,
|
| | });
|
| |
|
| |
|
| | useEffect(() => {
|
| | setIsConnected(isConnected);
|
| |
|
| |
|
| | if (!isConnected) {
|
| | setTraceId(null);
|
| | console.log('WebSocket disconnected - traceId cleared');
|
| | }
|
| | }, [isConnected, setIsConnected, setTraceId]);
|
| |
|
| |
|
| | useEffect(() => {
|
| |
|
| | (window as Window & { __sendNewTask?: (instruction: string, modelId: string) => void }).__sendNewTask = (instruction: string, modelId: string) => {
|
| |
|
| | resetAgent();
|
| |
|
| |
|
| | if (!traceId) {
|
| | console.error('Internal error: Cannot send task. TraceId not set. Refreshing page...');
|
| | window.location.reload();
|
| | return;
|
| | }
|
| |
|
| | const trace: AgentTrace = {
|
| | id: traceId,
|
| | instruction,
|
| | modelId: modelId,
|
| | timestamp: new Date(),
|
| | isRunning: true,
|
| | traceMetadata: {
|
| | traceId: traceId,
|
| | inputTokensUsed: 0,
|
| | outputTokensUsed: 0,
|
| | duration: 0,
|
| | numberOfSteps: 0,
|
| | maxSteps: 200,
|
| | completed: false,
|
| | final_state: null,
|
| | } as AgentTraceMetadata,
|
| | };
|
| |
|
| | setTrace(trace);
|
| | setIsAgentProcessing(true);
|
| | setIsConnectingToE2B(true);
|
| |
|
| |
|
| | sendMessage({
|
| | type: 'user_task',
|
| | trace: trace,
|
| | });
|
| |
|
| | console.log('Task sent:', trace);
|
| | };
|
| | }, [setTrace, setIsAgentProcessing, setIsConnectingToE2B, sendMessage, resetAgent, traceId]);
|
| |
|
| |
|
| | const stopCurrentTask = useCallback(() => {
|
| | const trace = useAgentStore.getState().trace;
|
| | if (trace?.id && trace.isRunning) {
|
| | sendMessage({
|
| | type: 'stop_task',
|
| | trace_id: trace.id,
|
| | });
|
| | console.log('Stop task sent for trace:', trace.id);
|
| |
|
| |
|
| | }
|
| | }, [sendMessage]);
|
| |
|
| | return {
|
| | isConnected,
|
| | connectionState,
|
| | manualReconnect,
|
| | stopCurrentTask,
|
| | };
|
| | };
|
| |
|