import { ChatCompletionRequest } from '@/types/chat';
class DeepWikiWebSocketClient {
private ws: WebSocket | null = null;
private messageBuffer: string = '';
async streamCompletion(
request: ChatCompletionRequest,
onChunk: (chunk: string) => void,
onError: (error: Error) => void,
onComplete: () => void
): Promise<void> {
return new Promise((resolve, reject) => {
try {
// Close existing connection if any
this.close();
// Create new WebSocket connection
this.ws = new WebSocket(this.getWebSocketUrl());
// Set binary type for potential future binary support
this.ws.binaryType = 'arraybuffer';
// Connection opened
this.ws.onopen = () => {
console.log('WebSocket connection established');
this.ws!.send(JSON.stringify(request));
};
// Message received
this.ws.onmessage = (event) => {
try {
const chunk = event.data;
this.messageBuffer += chunk;
onChunk(chunk);
} catch (error) {
console.error('Error processing message:', error);
onError(error as Error);
}
};
// Connection closed
this.ws.onclose = (event) => {
console.log('WebSocket closed:', event.code, event.reason);
onComplete();
resolve();
};
// Connection error
this.ws.onerror = (error) => {
console.error('WebSocket error:', error);
onError(new Error('WebSocket connection failed'));
reject(error);
};
// Set timeout for connection
setTimeout(() => {
if (this.ws?.readyState === WebSocket.CONNECTING) {
this.close();
reject(new Error('WebSocket connection timeout'));
}
}, 5000);
} catch (error) {
reject(error);
}
});
}
private getWebSocketUrl(): string {
const baseUrl = process.env.NEXT_PUBLIC_SERVER_BASE_URL || 'http://localhost:8001';
return baseUrl.replace(/^http/, 'ws') + '/ws/chat';
}
close(): void {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
this.ws.close(1000, 'Client closing connection');
}
this.ws = null;
this.messageBuffer = '';
}
getFullResponse(): string {
return this.messageBuffer;
}
}
// Usage example
const client = new DeepWikiWebSocketClient();
await client.streamCompletion(
{
repo_url: 'https://github.com/user/repo',
messages: [{ role: 'user', content: 'Explain the main functionality' }],
provider: 'google',
model: 'gemini-2.0-flash',
language: 'en'
},
(chunk) => {
// Update UI with streaming chunk
setResponse(prev => prev + chunk);
},
(error) => {
console.error('Streaming error:', error);
// Fall back to HTTP
},
() => {
console.log('Streaming complete');
// Enable UI for next question
}
);