export const ProgressTracker = { name: 'ProgressTracker', props: { taskId: { type: String, required: true }, apiPrefix: { type: String, default: '' } }, emits: ['specialist-complete', 'progress-update', 'specialist-error'], data() { return { isExpanded: false, progressLines: [], eventSource: null, isCompleted: false, lastLine: '', error: null, connecting: true, finalAnswer: null, hasError: false }; }, computed: { progressEndpoint() { return `${this.apiPrefix}/chat/api/task_progress/${this.taskId}`; }, displayLines() { return this.isExpanded ? this.progressLines : [ this.lastLine || 'Verbinden met taak...' ]; } }, mounted() { this.connectToEventSource(); }, beforeUnmount() { this.disconnectEventSource(); }, methods: { connectToEventSource() { try { this.connecting = true; this.error = null; // Sluit eventuele bestaande verbinding this.disconnectEventSource(); // Maak nieuwe SSE verbinding this.eventSource = new EventSource(this.progressEndpoint); // Algemene event handler this.eventSource.onmessage = (event) => { this.handleProgressUpdate(event); }; // Specifieke event handlers per type this.eventSource.addEventListener('progress', (event) => { this.handleProgressUpdate(event, 'progress'); }); this.eventSource.addEventListener('EveAI Specialist Complete', (event) => { console.log('Received EveAI Specialist Complete event'); this.handleProgressUpdate(event, 'EveAI Specialist Complete'); }); this.eventSource.addEventListener('error', (event) => { this.handleError(event); }); // Status handlers this.eventSource.onopen = () => { this.connecting = false; }; this.eventSource.onerror = (error) => { console.error('SSE Connection error:', error); this.error = 'Verbindingsfout. Probeer het later opnieuw.'; this.connecting = false; // Probeer opnieuw te verbinden na 3 seconden setTimeout(() => { if (!this.isCompleted && this.progressLines.length === 0) { this.connectToEventSource(); } }, 3000); }; } catch (err) { console.error('Error setting up event source:', err); this.error = 'Kan geen verbinding maken met de voortgangsupdates.'; this.connecting = false; } }, disconnectEventSource() { if (this.eventSource) { this.eventSource.close(); this.eventSource = null; } }, handleProgressUpdate(event, eventType = null) { try { const update = JSON.parse(event.data); // Controleer op verschillende typen updates const processingType = update.processing_type; const data = update.data || {}; // Process based on processing type let message = this.formatProgressMessage(processingType, data); // Alleen bericht toevoegen als er daadwerkelijk een bericht is if (message) { this.progressLines.push(message); this.lastLine = message; } // Emit progress update voor parent component this.$emit('progress-update', { processingType, data, message }); // Handle completion and errors if (processingType === 'EveAI Specialist Complete') { console.log('Processing EveAI Specialist Complete:', data); this.handleSpecialistComplete(data); } else if (processingType === 'EveAI Specialist Error') { this.handleSpecialistError(data); } else if (processingType === 'Task Complete' || processingType === 'Task Error') { this.isCompleted = true; this.disconnectEventSource(); } // Scroll automatisch naar beneden als uitgevouwen if (this.isExpanded) { this.$nextTick(() => { const container = this.$refs.progressContainer; if (container) { container.scrollTop = container.scrollHeight; } }); } } catch (err) { console.error('Error parsing progress update:', err, event.data); } }, formatProgressMessage(processingType, data) { // Lege data dictionary - toon enkel processing type if (!data || Object.keys(data).length === 0) { return processingType; } // Specifiek bericht als er een message field is if (data.message) { return data.message; } // Processing type met name veld als dat bestaat if (data.name) { return `${processingType}: ${data.name}`; } // Stap informatie if (data.step) { return `Stap ${data.step}: ${data.description || ''}`; } // Voor EveAI Specialist Complete - geen progress message if (processingType === 'EveAI Specialist Complete') { return null; } // Default: processing type + eventueel data als string return processingType; }, handleSpecialistComplete(data) { this.isCompleted = true; this.disconnectEventSource(); // Debug logging console.log('Specialist Complete Data:', data); // Extract answer from data.result.answer if (data.result && data.result.answer) { this.finalAnswer = data.result.answer; console.log('Final Answer:', this.finalAnswer); // Direct update van de parent message als noodoplossing try { if (this.$parent && this.$parent.message) { console.log('Direct update parent message'); this.$parent.message.content = data.result.answer; } } catch(err) { console.error('Error updating parent message:', err); } // Emit event to parent met alle relevante data inclusief form_request this.$emit('specialist-complete', { answer: data.result.answer, form_request: data.result.form_request, // Voeg form_request toe result: data.result, interactionId: data.interaction_id, taskId: this.taskId }); } else { console.error('Missing result.answer in specialist complete data:', data); } }, handleSpecialistError(data) { this.isCompleted = true; this.hasError = true; this.disconnectEventSource(); // Zet gebruiksvriendelijke foutmelding const errorMessage = "We could not process your request. Please try again later."; this.error = errorMessage; // Log de werkelijke fout voor debug doeleinden if (data.Error) { console.error('Specialist Error:', data.Error); } // Emit error event naar parent this.$emit('specialist-error', { message: errorMessage, originalError: data.Error, taskId: this.taskId }); }, handleError(event) { console.error('SSE Error event:', event); this.error = 'Er is een fout opgetreden bij het verwerken van updates.'; // Probeer parse van foutgegevens try { const errorData = JSON.parse(event.data); if (errorData && errorData.message) { this.error = errorData.message; } } catch (err) { // Blijf bij algemene foutmelding als parsing mislukt } }, toggleExpand() { this.isExpanded = !this.isExpanded; if (this.isExpanded) { this.$nextTick(() => { const container = this.$refs.progressContainer; if (container) { container.scrollTop = container.scrollHeight; } }); } } }, template: `
Fout bij verwerking Verwerking voltooid Bezig met redeneren...
{{ isExpanded ? '▲' : '▼' }}
{{ error }}
{{ line }}
` };