WebSocket API
The WebSocket API provides real-time communication capabilities for the Daisy system. It handles various events including message streaming, research updates, and system notifications.
Connection
Establishing Connection
typescript
import { io } from 'socket.io-client';
const socket = io('wss://your-daisy-server.com', {
auth: {
token: 'your_jwt_token',
},
});Events
Message Response Events
typescript
// Listen for message chunks
socket.on(
'daisy.event.message-response',
(data: {
threadId: string;
content: string;
artifact?: string;
messageId: string;
name: string;
type: 'ai' | 'tool';
toolCalls?: string[];
toolName?: string;
}) => {
console.log('Received message chunk:', data);
},
);
// Message completion event
socket.on(
'daisy.event.message-response-finished',
(data: { threadId: string }) => {
console.log('Message stream completed for thread:', data.threadId);
},
);Research Events
typescript
// Research progress updates
socket.on(
'daisy.event.deep-research-response',
(data: { threadId: string; content: string; langgraphNode: string }) => {
console.log('Research update:', data);
},
);
// Research completion
socket.on(
'daisy.event.deep-research-response-finished',
(data: { threadId: string }) => {
console.log('Research completed for thread:', data.threadId);
},
);Thread Events
typescript
// Thread title updates
socket.on(
'daisy.event.thread-title-updated',
(data: { threadId: string; title: string }) => {
console.log('Thread title updated:', data);
},
);Usage Examples
Message Streaming
typescript
// Example component handling message streaming
class ChatComponent {
private messageBuffer = '';
constructor() {
this.setupWebSocket();
}
private setupWebSocket() {
socket.on('daisy.event.message-response', (data) => {
this.handleMessageChunk(data);
});
socket.on('daisy.event.message-response-finished', (data) => {
this.handleMessageComplete(data);
});
}
private handleMessageChunk(data: {
content: string;
type: 'ai' | 'tool';
// ... other properties
}) {
if (data.type === 'ai') {
this.messageBuffer += data.content;
this.updateUI();
} else if (data.type === 'tool') {
this.handleToolResponse(data);
}
}
private handleMessageComplete(data: { threadId: string }) {
this.finalizeMessage(this.messageBuffer);
this.messageBuffer = '';
}
}Research Progress Tracking
typescript
class ResearchComponent {
private researchStates: Record<
string,
{
status: 'in_progress' | 'completed';
content: string;
currentNode: string;
}
> = {};
constructor() {
this.setupResearchEvents();
}
private setupResearchEvents() {
socket.on('daisy.event.deep-research-response', (data) => {
this.updateResearchProgress(data);
});
socket.on('daisy.event.deep-research-response-finished', (data) => {
this.completeResearch(data.threadId);
});
}
private updateResearchProgress(data: {
threadId: string;
content: string;
langgraphNode: string;
}) {
this.researchStates[data.threadId] = {
status: 'in_progress',
content: data.content,
currentNode: data.langgraphNode,
};
this.updateUI();
}
}Error Handling
Connection Errors
typescript
socket.on('connect_error', (error) => {
console.error('WebSocket connection error:', error);
// Implement reconnection logic
});
socket.on('disconnect', (reason) => {
console.log('Disconnected:', reason);
if (reason === 'io server disconnect') {
// Disconnected by server
socket.connect();
}
});Message Handling Errors
typescript
socket.on('error', (error) => {
console.error('WebSocket error:', error);
// Handle error appropriately
});
// Implement timeout handling
const messageTimeout = setTimeout(() => {
console.error('Message response timeout');
// Handle timeout
}, 30000);
socket.on('daisy.event.message-response-finished', () => {
clearTimeout(messageTimeout);
});Best Practices
1. Connection Management
- Implement reconnection strategy
- Handle connection timeouts
- Monitor connection state
- Clean up listeners
2. Message Processing
- Buffer message chunks
- Handle out-of-order messages
- Implement timeout handling
- Clean up resources
3. Error Recovery
- Implement exponential backoff
- Handle partial messages
- Maintain message order
- Cache important states
Performance Considerations
1. Message Handling
typescript
// Batch UI updates
let updateTimeout: NodeJS.Timeout;
function handleMessageChunk(content: string) {
buffer += content;
clearTimeout(updateTimeout);
updateTimeout = setTimeout(() => {
updateUI(buffer);
}, 100);
}2. Resource Management
typescript
// Clean up resources on component unmount
class Component {
cleanup() {
socket.off('daisy.event.message-response');
socket.off('daisy.event.message-response-finished');
clearTimeout(updateTimeout);
buffer = '';
}
}3. Connection Optimization
typescript
const socket = io('wss://your-daisy-server.com', {
reconnection: true,
reconnectionDelay: 1000,
reconnectionDelayMax: 5000,
reconnectionAttempts: 5,
});Security Considerations
1. Authentication
typescript
socket.on('connect', () => {
socket.emit('authenticate', { token: getAuthToken() });
});
socket.on('unauthorized', (error) => {
console.error('Authentication failed:', error);
// Handle authentication failure
});2. Data Validation
typescript
function validateMessageData(data: any): boolean {
return (
data &&
typeof data.threadId === 'string' &&
typeof data.content === 'string'
);
}
socket.on('daisy.event.message-response', (data) => {
if (!validateMessageData(data)) {
console.error('Invalid message data received');
return;
}
// Process message
});3. Connection Security
- Use secure WebSocket (WSS)
- Implement message encryption
- Validate origin
- Monitor connections
Monitoring
Connection Metrics
- Connection status
- Reconnection attempts
- Message latency
- Error rates
Performance Metrics
- Message processing time
- UI update frequency
- Memory usage
- Event queue size
Error Tracking
typescript
let errorCount = 0;
const errorThreshold = 5;
socket.on('error', (error) => {
errorCount++;
logError(error);
if (errorCount >= errorThreshold) {
// Implement circuit breaker
socket.disconnect();
// Notify user/system
}
});