|
|
import { useAgentStore } from '@/stores/agentStore'; |
|
|
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); |
|
|
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, |
|
|
}; |
|
|
}; |
|
|
|