|
|
|
|
|
|
|
|
|
|
|
import { Logger } from '../core/logger.js'; |
|
|
import { appState } from '../core/state.js'; |
|
|
import { domManager } from '../ui/dom-manager.js'; |
|
|
import { messageManager } from '../ui/message-manager.js'; |
|
|
import { settingsManager } from '../ui/settings-manager.js'; |
|
|
import { sessionManager } from '../ui/session-manager.js'; |
|
|
|
|
|
export class SocketEventHandlers { |
|
|
constructor() { |
|
|
this.timeoutHandlers = { |
|
|
solvingTimeoutId: null, |
|
|
connectionTimeoutId: null |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
getEventHandlers() { |
|
|
return { |
|
|
'session_connected': (data) => this.handleSessionConnected(data), |
|
|
'settings_updated': (data) => this.handleSettingsUpdated(data), |
|
|
'solving_started': (data) => this.handleSolvingStarted(data), |
|
|
'step_update': (data) => this.handleStepUpdate(data), |
|
|
'solving_complete': (data) => this.handleSolvingComplete(data), |
|
|
'solving_interrupted': (data) => this.handleSolvingInterrupted(data), |
|
|
'solving_error': (data) => this.handleSolvingError(data), |
|
|
'ai_response': (data) => this.handleAIResponse(data), |
|
|
'error': (data) => this.handleError(data), |
|
|
|
|
|
|
|
|
'llm_streaming_start': (data) => this.handleLLMStreamingStart(data), |
|
|
'llm_streaming_token': (data) => this.handleLLMStreamingToken(data), |
|
|
'llm_streaming_end': (data) => this.handleLLMStreamingEnd(data), |
|
|
'llm_response': (data) => this.handleLLMResponse(data), |
|
|
|
|
|
|
|
|
'code_execution_start': (data) => this.handleCodeExecutionStart(data), |
|
|
'code_execution_end': (data) => this.handleCodeExecutionEnd(data), |
|
|
'code_execution': (data) => this.handleCodeExecution(data), |
|
|
|
|
|
|
|
|
'code_check_streaming_start': (data) => this.handleCodeCheckStreamingStart(data), |
|
|
'code_check_streaming_token': (data) => this.handleCodeCheckStreamingToken(data), |
|
|
'code_check_streaming_end': (data) => this.handleCodeCheckStreamingEnd(data), |
|
|
|
|
|
|
|
|
'awaiting_user_feedback': (data) => this.handleAwaitingUserFeedback(data), |
|
|
'final_artifacts': (data) => this.handleFinalArtifacts(data), |
|
|
|
|
|
|
|
|
'heartbeat_response': (data) => this.handleHeartbeatResponse(data) |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
getConnectionHandlers() { |
|
|
return { |
|
|
'connected': () => this.handleSocketConnected(), |
|
|
'disconnected': ({ reason }) => this.handleSocketDisconnected(reason), |
|
|
'connectionError': ({ error }) => this.handleConnectionError(error), |
|
|
'ioError': ({ error }) => this.handleIOError(error) |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
handleSocketConnected() { |
|
|
console.log('[DEBUG] handleSocketConnected called'); |
|
|
|
|
|
|
|
|
if (!appState.currentSessionId) { |
|
|
console.log('[DEBUG] No session ID yet, showing Connecting...'); |
|
|
domManager.updateSessionInfo('Connecting...'); |
|
|
} else { |
|
|
console.log('[DEBUG] Already have session ID:', appState.currentSessionId); |
|
|
} |
|
|
|
|
|
|
|
|
setTimeout(() => { |
|
|
if (!appState.currentSessionId) { |
|
|
console.log('[DEBUG] Session ID still unknown after 1s, requesting session info'); |
|
|
Logger.debug('Socket Event', 'Session ID still unknown after 1s, requesting session info'); |
|
|
|
|
|
import('../network/socket.js').then(({ socketManager }) => { |
|
|
socketManager.send('request_session_info'); |
|
|
}); |
|
|
} |
|
|
}, 1000); |
|
|
} |
|
|
|
|
|
handleSocketDisconnected(reason) { |
|
|
domManager.updateSessionInfo('Session: Not connected'); |
|
|
domManager.updateStatus('Disconnected from server', 'error'); |
|
|
|
|
|
|
|
|
if (appState.isSolving) { |
|
|
this.resetSolvingState(); |
|
|
messageManager.addMessage('PIPS System', 'Connection lost during solving. Please try again.', null); |
|
|
} |
|
|
} |
|
|
|
|
|
handleConnectionError(error) { |
|
|
domManager.updateStatus('Connection error. Retrying...', 'error'); |
|
|
} |
|
|
|
|
|
handleIOError(error) { |
|
|
domManager.updateStatus('Socket.IO error occurred', 'error'); |
|
|
} |
|
|
|
|
|
|
|
|
handleSessionConnected(data) { |
|
|
console.log('[DEBUG] handleSessionConnected called with data:', data); |
|
|
Logger.debug('Socket Event', 'Session connected:', data); |
|
|
sessionManager.handleSessionConnected(data); |
|
|
|
|
|
|
|
|
settingsManager.initializeServerSettings(); |
|
|
} |
|
|
|
|
|
handleSettingsUpdated(data) { |
|
|
Logger.debug('Socket Event', 'Settings updated:', data); |
|
|
settingsManager.handleSettingsUpdated(data); |
|
|
} |
|
|
|
|
|
handleSolvingStarted(data) { |
|
|
Logger.debug('Socket Event', 'Solving started:', data); |
|
|
appState.setSolving(true); |
|
|
appState.setIteration(0); |
|
|
|
|
|
domManager.setSolvingState(); |
|
|
domManager.updateStatus(data.message, 'info'); |
|
|
this.setSolvingTimeout(); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.removeFeedbackPanel(); |
|
|
window.interactiveFeedback.removeRestoreButton(); |
|
|
} |
|
|
|
|
|
|
|
|
sessionManager.handleSolvingStarted(); |
|
|
} |
|
|
|
|
|
handleStepUpdate(data) { |
|
|
Logger.debug('Socket Event', 'Step update:', data); |
|
|
|
|
|
appState.setIteration(data.iteration || 0); |
|
|
domManager.updateStatus(data.message, 'info'); |
|
|
domManager.updateProgress(data.progress); |
|
|
|
|
|
|
|
|
let displayMessage = data.message; |
|
|
|
|
|
|
|
|
if (data.step === 'code_checking') { |
|
|
displayMessage = `Analyzing code quality (iteration ${data.iteration})...`; |
|
|
} else if (data.step === 'code_refinement') { |
|
|
displayMessage = `Refining solution (iteration ${data.iteration})...`; |
|
|
} else if (data.step === 'interrupted') { |
|
|
displayMessage = '⏹️ PIPS was interrupted by the user.'; |
|
|
} else if (data.step === 'finished') { |
|
|
displayMessage = '🎉 Solution completed successfully!'; |
|
|
} |
|
|
|
|
|
messageManager.addMessage('PIPS', displayMessage, data.iteration, data.prompt_details); |
|
|
this.resetSolvingTimeout(); |
|
|
} |
|
|
|
|
|
handleSolvingComplete(data) { |
|
|
Logger.debug('Socket Event', 'Solving complete:', data); |
|
|
|
|
|
this.clearSolvingTimeout(); |
|
|
this.resetSolvingState(); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.removeFeedbackPanel(); |
|
|
window.interactiveFeedback.removeRestoreButton(); |
|
|
} |
|
|
|
|
|
|
|
|
if (data.final_answer) { |
|
|
messageManager.displayFinalAnswer(data.final_answer); |
|
|
} |
|
|
|
|
|
domManager.updateStatus('Problem solving completed successfully!', 'success'); |
|
|
|
|
|
|
|
|
sessionManager.handleSolvingComplete(); |
|
|
} |
|
|
|
|
|
handleSolvingInterrupted(data) { |
|
|
Logger.debug('Socket Event', 'Solving interrupted:', data); |
|
|
|
|
|
this.clearSolvingTimeout(); |
|
|
this.resetSolvingState(); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.removeFeedbackPanel(); |
|
|
window.interactiveFeedback.removeRestoreButton(); |
|
|
} |
|
|
|
|
|
domManager.updateStatus(data.message || 'Problem solving interrupted', 'warning'); |
|
|
|
|
|
|
|
|
sessionManager.handleSolvingInterrupted(); |
|
|
} |
|
|
|
|
|
handleSolvingError(data) { |
|
|
Logger.error('Socket Event', 'Solving error:', data); |
|
|
domManager.updateStatus(`Error: ${data.error}`, 'error'); |
|
|
|
|
|
this.clearSolvingTimeout(); |
|
|
this.resetSolvingState(); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.removeFeedbackPanel(); |
|
|
window.interactiveFeedback.removeRestoreButton(); |
|
|
} |
|
|
|
|
|
messageManager.addMessage('PIPS System', `Error: ${data.error}`, null); |
|
|
|
|
|
|
|
|
sessionManager.handleSolvingError(); |
|
|
} |
|
|
|
|
|
handleAIResponse(data) { |
|
|
Logger.debug('Socket Event', 'AI response:', data); |
|
|
messageManager.addMessage(data.sender || 'AI Assistant', data.content, data.iteration); |
|
|
domManager.updateProgress(data.progress); |
|
|
} |
|
|
|
|
|
handleError(data) { |
|
|
Logger.error('Socket Event', 'Socket error:', data); |
|
|
domManager.updateStatus(`Error: ${data.message}`, 'error'); |
|
|
|
|
|
if (appState.isSolving) { |
|
|
this.clearSolvingTimeout(); |
|
|
this.resetSolvingState(); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.removeFeedbackPanel(); |
|
|
window.interactiveFeedback.removeRestoreButton(); |
|
|
} |
|
|
|
|
|
|
|
|
sessionManager.handleSolvingError(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
handleLLMStreamingStart(data) { |
|
|
Logger.debug('Socket Event', 'LLM streaming started:', data); |
|
|
messageManager.showAIThinkingIndicator(data.iteration, 'AI Assistant', data.model_name); |
|
|
} |
|
|
|
|
|
handleLLMStreamingToken(data) { |
|
|
Logger.debug('Socket Event', 'LLM streaming token received:', data.token); |
|
|
messageManager.updateStreamingMessage(data.token, data.iteration, 'AI Assistant', data.model_name); |
|
|
} |
|
|
|
|
|
handleLLMStreamingEnd(data) { |
|
|
Logger.debug('Socket Event', 'LLM streaming ended:', data); |
|
|
messageManager.removeAIThinkingIndicator(data.iteration, 'AI Assistant'); |
|
|
messageManager.finalizeStreamingMessage(data.iteration, 'AI Assistant'); |
|
|
} |
|
|
|
|
|
handleLLMResponse(data) { |
|
|
Logger.debug('Socket Event', 'LLM response (fallback):', data); |
|
|
|
|
|
messageManager.removeAIThinkingIndicator(data.iteration); |
|
|
messageManager.addMessage('AI Assistant', data.response, data.iteration); |
|
|
} |
|
|
|
|
|
|
|
|
handleCodeExecutionStart(data) { |
|
|
Logger.debug('Socket Event', 'Code execution started:', data); |
|
|
messageManager.showExecutionSpinner(data.iteration); |
|
|
} |
|
|
|
|
|
handleCodeExecutionEnd(data) { |
|
|
Logger.debug('Socket Event', 'Code execution ended:', data); |
|
|
messageManager.removeExecutionSpinner(data.iteration); |
|
|
} |
|
|
|
|
|
handleCodeExecution(data) { |
|
|
Logger.debug('Socket Event', 'Code execution result:', data); |
|
|
messageManager.removeExecutionSpinner(data.iteration); |
|
|
|
|
|
let resultText = ''; |
|
|
if (data.error && data.error.trim() !== '') { |
|
|
resultText = `Error: ${data.error}`; |
|
|
messageManager.displayExecutionResult(resultText, data.iteration, true); |
|
|
} else { |
|
|
if (data.stdout && data.stdout.trim() !== '') { |
|
|
resultText += `Output: ${data.stdout}\n`; |
|
|
} |
|
|
if (data.output && data.output.trim() !== '' && data.output !== 'None') { |
|
|
resultText += `Result: ${data.output}`; |
|
|
} |
|
|
if (resultText.trim() === '') { |
|
|
resultText = 'Code executed successfully (no output)'; |
|
|
} |
|
|
messageManager.displayExecutionResult(resultText, data.iteration, false); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
handleCodeCheckStreamingStart(data) { |
|
|
Logger.debug('Socket Event', 'Code reviewer streaming started:', data); |
|
|
messageManager.showAIThinkingIndicator(data.iteration, 'AI Code Reviewer', data.model_name); |
|
|
} |
|
|
|
|
|
handleCodeCheckStreamingToken(data) { |
|
|
Logger.debug('Socket Event', 'Code reviewer streaming token received:', data.token); |
|
|
messageManager.updateStreamingMessage(data.token, data.iteration, 'AI Code Reviewer', data.model_name); |
|
|
} |
|
|
|
|
|
handleCodeCheckStreamingEnd(data) { |
|
|
Logger.debug('Socket Event', 'Code reviewer streaming ended:', data); |
|
|
messageManager.removeAIThinkingIndicator(data.iteration, 'AI Code Reviewer'); |
|
|
messageManager.finalizeStreamingMessage(data.iteration, 'AI Code Reviewer'); |
|
|
} |
|
|
|
|
|
|
|
|
handleAwaitingUserFeedback(data) { |
|
|
Logger.debug('Socket Event', 'Awaiting user feedback:', data); |
|
|
|
|
|
|
|
|
appState.setUserFeedback(true); |
|
|
domManager.updateStatus('Waiting for your feedback...', 'info'); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.showFeedbackPanel(data); |
|
|
} else { |
|
|
|
|
|
this.showBasicFeedbackInterface(data); |
|
|
} |
|
|
} |
|
|
|
|
|
handleFinalArtifacts(data) { |
|
|
Logger.debug('Socket Event', 'Final artifacts:', data); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.showFinalArtifacts(data); |
|
|
} else { |
|
|
|
|
|
messageManager.addMessage('PIPS System', 'Final solution artifacts are ready.', null); |
|
|
} |
|
|
} |
|
|
|
|
|
showBasicFeedbackInterface(data) { |
|
|
|
|
|
const feedbackHtml = ` |
|
|
<div class="basic-feedback-panel"> |
|
|
<h4>Interactive Feedback Required</h4> |
|
|
<p>AI Critic: ${data.critic_text || 'No critic feedback available'}</p> |
|
|
<div class="feedback-buttons"> |
|
|
<button onclick="window.provideFeedback(true, '')">Accept & Continue</button> |
|
|
<button onclick="window.provideFeedback(false, '')">Reject & Continue</button> |
|
|
<button onclick="window.terminateSession()">Finish Here</button> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
|
|
|
|
|
|
messageManager.addMessage('PIPS Interactive', feedbackHtml, data.iteration || null); |
|
|
|
|
|
|
|
|
window.provideFeedback = (acceptCritic, comments) => { |
|
|
import('../network/socket.js').then(({ socketManager }) => { |
|
|
socketManager.send('provide_feedback', { |
|
|
accept_critic: acceptCritic, |
|
|
extra_comments: comments, |
|
|
quoted_ranges: [], |
|
|
terminate: false |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
|
|
|
window.terminateSession = () => { |
|
|
import('../network/socket.js').then(({ socketManager }) => { |
|
|
socketManager.send('provide_feedback', { |
|
|
accept_critic: true, |
|
|
extra_comments: '', |
|
|
quoted_ranges: [], |
|
|
terminate: true |
|
|
}); |
|
|
}); |
|
|
}; |
|
|
} |
|
|
|
|
|
|
|
|
handleHeartbeatResponse(data) { |
|
|
Logger.debug('Socket Event', 'Heartbeat response received'); |
|
|
appState.updateLastHeartbeat(); |
|
|
} |
|
|
|
|
|
|
|
|
setSolvingTimeout() { |
|
|
appState.setSolvingTimeout(setTimeout(() => { |
|
|
Logger.error('SocketHandlers', 'Solving timeout detected - server may be unresponsive'); |
|
|
domManager.updateStatus('Server timeout detected. The server may be unresponsive. Try refreshing the page.', 'error'); |
|
|
this.resetSolvingState(); |
|
|
|
|
|
|
|
|
if (window.interactiveFeedback) { |
|
|
window.interactiveFeedback.removeFeedbackPanel(); |
|
|
window.interactiveFeedback.removeRestoreButton(); |
|
|
} |
|
|
|
|
|
messageManager.addMessage('PIPS System', 'Operation timed out. The server may be experiencing issues. Please try again or contact support if the problem persists.', null); |
|
|
|
|
|
|
|
|
sessionManager.handleSolvingError(); |
|
|
}, appState.SOLVING_TIMEOUT_MS)); |
|
|
} |
|
|
|
|
|
clearSolvingTimeout() { |
|
|
appState.clearSolvingTimeout(); |
|
|
} |
|
|
|
|
|
resetSolvingTimeout() { |
|
|
this.clearSolvingTimeout(); |
|
|
this.setSolvingTimeout(); |
|
|
} |
|
|
|
|
|
resetSolvingState() { |
|
|
appState.setSolving(false); |
|
|
appState.setIteration(0); |
|
|
domManager.resetSolvingState(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
export const socketEventHandlers = new SocketEventHandlers(); |