Files
Atomizer/atomizer-dashboard/frontend/src/hooks/useWebSocket.ts
Antoine 8cbdbcad78 feat: Add Protocol 13 adaptive optimization, Plotly charts, and dashboard improvements
## Protocol 13: Adaptive Multi-Objective Optimization
- Iterative FEA + Neural Network surrogate workflow
- Initial FEA sampling, NN training, NN-accelerated search
- FEA validation of top NN predictions, retraining loop
- adaptive_state.json tracks iteration history and best values
- M1 mirror study (V11) with 103 FEA, 3000 NN trials

## Dashboard Visualization Enhancements
- Added Plotly.js interactive charts (parallel coords, Pareto, convergence)
- Lazy loading with React.lazy() for performance
- Code splitting: plotly.js-basic-dist (~1MB vs 3.5MB)
- Chart library toggle (Recharts default, Plotly on-demand)
- ExpandableChart component for full-screen modal views
- ConsoleOutput component for real-time log viewing

## Documentation
- Protocol 13 detailed documentation
- Dashboard visualization guide
- Plotly components README
- Updated run-optimization skill with Mode 5 (adaptive)

## Bug Fixes
- Fixed TypeScript errors in dashboard components
- Fixed Card component to accept ReactNode title
- Removed unused imports across components

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 07:41:54 -05:00

66 lines
2.1 KiB
TypeScript

import { useState, useEffect } from 'react';
import useWebSocket, { ReadyState } from 'react-use-websocket';
import { WebSocketMessage } from '../types';
interface UseOptimizationWebSocketProps {
studyId: string | null;
onMessage?: (message: WebSocketMessage) => void;
}
export const useOptimizationWebSocket = ({ studyId, onMessage }: UseOptimizationWebSocketProps) => {
const [socketUrl, setSocketUrl] = useState<string | null>(null);
useEffect(() => {
if (studyId) {
// In development, we might need to point to localhost:8000 explicitly if not proxied
// But assuming Vite proxy is set up correctly:
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
const host = window.location.host; // This will be localhost:3000 in dev
// If using proxy in vite.config.ts, this works.
// If not, we might need to hardcode backend URL for dev:
const backendHost = import.meta.env.DEV ? 'localhost:8000' : host;
setSocketUrl(`${protocol}//${backendHost}/api/ws/optimization/${studyId}`);
} else {
setSocketUrl(null);
}
}, [studyId]);
const { sendMessage, lastMessage, readyState } = useWebSocket(socketUrl, {
shouldReconnect: (_closeEvent) => true,
reconnectAttempts: 10,
reconnectInterval: 3000,
onOpen: () => console.log('WebSocket Connected'),
onClose: () => console.log('WebSocket Disconnected'),
onError: (e) => console.error('WebSocket Error:', e),
});
useEffect(() => {
if (lastMessage !== null) {
try {
const data = JSON.parse(lastMessage.data) as WebSocketMessage;
if (onMessage) {
onMessage(data);
}
} catch (e) {
console.error('Failed to parse WebSocket message:', e);
}
}
}, [lastMessage, onMessage]);
const connectionStatus = {
[ReadyState.CONNECTING]: 'Connecting',
[ReadyState.OPEN]: 'Open',
[ReadyState.CLOSING]: 'Closing',
[ReadyState.CLOSED]: 'Closed',
[ReadyState.UNINSTANTIATED]: 'Uninstantiated',
}[readyState];
return {
sendMessage,
lastMessage,
readyState,
connectionStatus,
};
};