Files
hive/frontend/src/contexts/WebSocketContext.tsx
anthonyrawlins 268214d971 Major WHOOSH system refactoring and feature enhancements
- Migrated from HIVE branding to WHOOSH across all components
- Enhanced backend API with new services: AI models, BZZZ integration, templates, members
- Added comprehensive testing suite with security, performance, and integration tests
- Improved frontend with new components for project setup, AI models, and team management
- Updated MCP server implementation with WHOOSH-specific tools and resources
- Enhanced deployment configurations with production-ready Docker setups
- Added comprehensive documentation and setup guides
- Implemented age encryption service and UCXL integration

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-27 08:34:48 +10:00

147 lines
4.3 KiB
TypeScript

import React, { createContext, useContext, useEffect, useState } from 'react';
import { useWebSocket, WebSocketMessage } from '../hooks/useWebSocket';
interface WebSocketContextType {
isConnected: boolean;
connectionState: 'connecting' | 'connected' | 'disconnected' | 'error';
sendMessage: (type: string, data: any) => void;
lastMessage: WebSocketMessage | null;
subscribe: (messageType: string, handler: (data: any) => void) => () => void;
reconnect: () => void;
}
const WebSocketContext = createContext<WebSocketContextType | null>(null);
interface WebSocketProviderProps {
children: React.ReactNode;
url?: string;
}
export const WebSocketProvider: React.FC<WebSocketProviderProps> = ({
children,
url = import.meta.env.VITE_WS_BASE_URL || 'wss://whoosh.home.deepblack.cloud'
}) => {
const [subscriptions, setSubscriptions] = useState<Map<string, Set<(data: any) => void>>>(new Map());
const {
isConnected,
connectionState,
sendMessage,
lastMessage,
reconnect
} = useWebSocket({
url,
reconnectAttempts: 5,
reconnectDelay: 3000,
onMessage: (message) => {
// Handle incoming messages and notify subscribers
const handlers = subscriptions.get(message.type);
if (handlers) {
handlers.forEach(handler => {
try {
handler(message.data);
} catch (error) {
console.error('Error in WebSocket message handler:', error);
}
});
}
},
onConnect: () => {
console.log('WebSocket connected to WHOOSH backend');
// Subscribe to general system events
sendMessage('subscribe', {
events: ['agent_status_changed', 'execution_started', 'execution_completed', 'metrics_updated']
});
},
onDisconnect: () => {
console.log('WebSocket disconnected from WHOOSH backend');
},
onError: (error) => {
console.error('WebSocket error:', error);
}
});
const subscribe = (messageType: string, handler: (data: any) => void) => {
setSubscriptions(prev => {
const newSubscriptions = new Map(prev);
if (!newSubscriptions.has(messageType)) {
newSubscriptions.set(messageType, new Set());
}
newSubscriptions.get(messageType)!.add(handler);
return newSubscriptions;
});
// Return unsubscribe function
return () => {
setSubscriptions(prev => {
const newSubscriptions = new Map(prev);
const handlers = newSubscriptions.get(messageType);
if (handlers) {
handlers.delete(handler);
if (handlers.size === 0) {
newSubscriptions.delete(messageType);
}
}
return newSubscriptions;
});
};
};
const contextValue: WebSocketContextType = {
isConnected,
connectionState,
sendMessage,
lastMessage,
subscribe,
reconnect
};
return (
<WebSocketContext.Provider value={contextValue}>
{children}
</WebSocketContext.Provider>
);
};
export const useWebSocketContext = (): WebSocketContextType => {
const context = useContext(WebSocketContext);
if (!context) {
throw new Error('useWebSocketContext must be used within a WebSocketProvider');
}
return context;
};
// Convenience hooks for common real-time updates
export const useAgentUpdates = (onAgentUpdate: (agentData: any) => void) => {
const { subscribe } = useWebSocketContext();
useEffect(() => {
const unsubscribe = subscribe('agent_status_changed', onAgentUpdate);
return unsubscribe;
}, [subscribe, onAgentUpdate]);
};
export const useExecutionUpdates = (onExecutionUpdate: (executionData: any) => void) => {
const { subscribe } = useWebSocketContext();
useEffect(() => {
const unsubscribeStart = subscribe('execution_started', onExecutionUpdate);
const unsubscribeComplete = subscribe('execution_completed', onExecutionUpdate);
const unsubscribeFailed = subscribe('execution_failed', onExecutionUpdate);
return () => {
unsubscribeStart();
unsubscribeComplete();
unsubscribeFailed();
};
}, [subscribe, onExecutionUpdate]);
};
export const useMetricsUpdates = (onMetricsUpdate: (metricsData: any) => void) => {
const { subscribe } = useWebSocketContext();
useEffect(() => {
const unsubscribe = subscribe('metrics_updated', onMetricsUpdate);
return unsubscribe;
}, [subscribe, onMetricsUpdate]);
};