import React, { useState } from 'react' import { ChevronDown, ChevronUp } from 'lucide-react' /** * WorkflowDebugPanel - Zeigt Debug-Informationen für jeden Node eines Workflows * * @param {Object} props * @param {Array} props.nodeStates - Array von NodeExecutionState Objekten */ export default function WorkflowDebugPanel({ nodeStates }) { const [expandedNodes, setExpandedNodes] = useState(new Set()) const [showAll, setShowAll] = useState(false) if (!nodeStates || nodeStates.length === 0) { return null } // Filter nodes that have debug information const debugNodes = nodeStates.filter(ns => ns.debug_prompt || ns.debug_raw_response || ns.debug_node_type ) if (debugNodes.length === 0) { return (

Keine Debug-Informationen verfügbar. Führe den Workflow mit debug=true aus.

) } const toggleNode = (nodeId) => { const newExpanded = new Set(expandedNodes) if (newExpanded.has(nodeId)) { newExpanded.delete(nodeId) } else { newExpanded.add(nodeId) } setExpandedNodes(newExpanded) } const toggleAll = () => { if (showAll) { setExpandedNodes(new Set()) } else { setExpandedNodes(new Set(debugNodes.map(n => n.node_id))) } setShowAll(!showAll) } const getStatusColor = (status) => { switch (status) { case 'executed': return '#1D9E75' case 'failed': return '#D85A30' case 'skipped': return '#888' default: return 'var(--text2)' } } const getNodeLabel = (node) => { if (node.debug_prompt_slug) return node.debug_prompt_slug if (node.debug_node_type) return `${node.debug_node_type}-${node.node_id.substring(0, 8)}` return node.node_id } return (

🔍 Debug-Informationen ({debugNodes.length} Nodes)

{debugNodes.map((node, idx) => { const isExpanded = expandedNodes.has(node.node_id) const label = getNodeLabel(node) const statusColor = getStatusColor(node.status) const hasFailed = node.status === 'failed' const hasError = node.error != null return (
{/* Node Header */}
toggleNode(node.node_id)} style={{ padding: '12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center', cursor: 'pointer', background: isExpanded ? 'var(--surface)' : 'transparent', transition: 'background 0.2s' }} >
#{idx + 1} {label} {node.status} {node.debug_node_type && ( {node.debug_node_type} )}
{isExpanded ? : }
{/* Node Debug Content */} {isExpanded && (
{node.error && (
Error:
                        {node.error}
                      
)} {node.debug_prompt && (
Prompt:
                        {node.debug_prompt}
                      
)} {node.debug_raw_response && (
Rohe Antwort:
                        {node.debug_raw_response}
                      
)} {node.analysis_core && (
Geparste Ergebnisse:
                        {node.analysis_core}
                      
)} {node.normalized_signals && node.normalized_signals.length > 0 && (
Signale ({node.normalized_signals.length}):
{node.normalized_signals.map((sig, i) => (
{sig.question_type}:{' '} "{sig.raw_value}" → "{sig.normalized_value}" {' '} {sig.status}
))}
)}
)}
) })}
) }