confidence metrics
This commit is contained in:
		
							parent
							
								
									8c5dc36788
								
							
						
					
					
						commit
						183e36b86d
					
				@ -672,6 +672,15 @@ class AIQueryInterface {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  displayResults(recommendation, originalQuery) {
 | 
					  displayResults(recommendation, originalQuery) {
 | 
				
			||||||
 | 
					    console.log('[AI DEBUG] Full recommendation object:', recommendation);
 | 
				
			||||||
 | 
					    console.log('[AI DEBUG] Recommended tools:', recommendation.recommended_tools);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (recommendation.recommended_tools) {
 | 
				
			||||||
 | 
					      recommendation.recommended_tools.forEach((tool, index) => {
 | 
				
			||||||
 | 
					        console.log(`[AI DEBUG] Tool ${index}:`, tool.name, 'Confidence:', tool.confidence);
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    if (this.currentMode === 'workflow') {
 | 
					    if (this.currentMode === 'workflow') {
 | 
				
			||||||
      this.displayWorkflowResults(recommendation, originalQuery);
 | 
					      this.displayWorkflowResults(recommendation, originalQuery);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
@ -693,16 +702,24 @@ class AIQueryInterface {
 | 
				
			|||||||
      toolsByPhase[phase] = [];
 | 
					      toolsByPhase[phase] = [];
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // DEBUG: Log recommendation structure
 | 
				
			||||||
 | 
					    console.log('[AI Results] Recommendation structure:', recommendation);
 | 
				
			||||||
 | 
					    console.log('[AI Results] Recommended tools:', recommendation.recommended_tools);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    recommendation.recommended_tools?.forEach(recTool => {
 | 
					    recommendation.recommended_tools?.forEach(recTool => {
 | 
				
			||||||
 | 
					      // DEBUG: Log each tool's confidence data
 | 
				
			||||||
 | 
					      console.log('[AI Results] Tool confidence data:', recTool.name, recTool.confidence);
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
      if (toolsByPhase[recTool.phase]) {
 | 
					      if (toolsByPhase[recTool.phase]) {
 | 
				
			||||||
        const fullTool = tools.find(t => t.name === recTool.name);
 | 
					        const fullTool = tools.find(t => t.name === recTool.name);
 | 
				
			||||||
        if (fullTool) {
 | 
					        if (fullTool) {
 | 
				
			||||||
          toolsByPhase[recTool.phase].push({
 | 
					          toolsByPhase[recTool.phase].push({
 | 
				
			||||||
            ...fullTool,
 | 
					            ...fullTool,
 | 
				
			||||||
            recommendation: recTool,
 | 
					            recommendation: recTool,
 | 
				
			||||||
            confidence: recTool.confidence,
 | 
					            confidence: recTool.confidence, // Ensure confidence is passed
 | 
				
			||||||
            justification: recTool.justification,
 | 
					            justification: recTool.justification,
 | 
				
			||||||
            priority: recTool.priority
 | 
					            priority: recTool.priority,
 | 
				
			||||||
 | 
					            recommendationStrength: recTool.recommendationStrength
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@ -737,6 +754,106 @@ class AIQueryInterface {
 | 
				
			|||||||
    this.elements.results.innerHTML = html;
 | 
					    this.elements.results.innerHTML = html;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  renderConfidenceTooltip(confidence) {
 | 
				
			||||||
 | 
					    if (!confidence || typeof confidence.overall !== 'number') {
 | 
				
			||||||
 | 
					      console.log('[AI DEBUG] No confidence data or invalid format:', confidence);
 | 
				
			||||||
 | 
					      return '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    const confidenceColor = confidence.overall >= 80 ? 'var(--color-accent)' : 
 | 
				
			||||||
 | 
					                           confidence.overall >= 60 ? 'var(--color-warning)' : 'var(--color-error)';
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    const tooltipId = `tooltip-${Math.random().toString(36).substr(2, 9)}`;
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    console.log(`[AI DEBUG] Generating confidence tooltip: ${confidence.overall}% with ID ${tooltipId}`);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return `
 | 
				
			||||||
 | 
					      <span class="confidence-tooltip-trigger" 
 | 
				
			||||||
 | 
					            style="display: inline-flex; align-items: center; gap: 0.125rem; cursor: help; margin-left: 0.25rem;"
 | 
				
			||||||
 | 
					            onmouseenter="document.getElementById('${tooltipId}').style.display = 'block'"
 | 
				
			||||||
 | 
					            onmouseleave="document.getElementById('${tooltipId}').style.display = 'none'"
 | 
				
			||||||
 | 
					            onclick="event.stopPropagation();">
 | 
				
			||||||
 | 
					        <div style="width: 6px; height: 6px; border-radius: 50%; background-color: ${confidenceColor}; flex-shrink: 0;"></div>
 | 
				
			||||||
 | 
					        <span style="font-size: 0.625rem; color: white; font-weight: 600; text-shadow: 0 1px 2px rgba(0,0,0,0.5);">${confidence.overall}%</span>
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        <div id="${tooltipId}" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 1001; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 0.5rem; padding: 1rem; min-width: 320px; max-width: 400px; box-shadow: var(--shadow-lg); font-size: 0.75rem; color: var(--color-text);">
 | 
				
			||||||
 | 
					          <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.75rem;">
 | 
				
			||||||
 | 
					            <strong style="font-size: 0.875rem;">KI-Vertrauenswertung</strong>
 | 
				
			||||||
 | 
					            <span class="badge badge-mini" style="background-color: ${confidenceColor}; color: white; font-weight: 600;">${confidence.overall}%</span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          <div style="display: grid; grid-template-columns: 1fr; gap: 0.625rem; margin-bottom: 0.75rem;">
 | 
				
			||||||
 | 
					            <div style="background: var(--color-bg-secondary); padding: 0.5rem; border-radius: 0.375rem; border-left: 3px solid var(--color-accent);">
 | 
				
			||||||
 | 
					              <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem;">
 | 
				
			||||||
 | 
					                <span style="font-weight: 600; font-size: 0.6875rem;">🔍 Ähnlichkeit zur Anfrage</span>
 | 
				
			||||||
 | 
					                <strong style="color: var(--color-accent);">${confidence.embeddingsQuality}%</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div style="font-size: 0.625rem; color: var(--color-text-secondary); line-height: 1.3;">
 | 
				
			||||||
 | 
					                Wie gut die Tool-Beschreibung zu Ihrer Suchanfrage passt (basierend auf Vektor-Ähnlichkeit)
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            <div style="background: var(--color-bg-secondary); padding: 0.5rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary);">
 | 
				
			||||||
 | 
					              <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem;">
 | 
				
			||||||
 | 
					                <span style="font-weight: 600; font-size: 0.6875rem;">🎯 Domain-Passung</span>
 | 
				
			||||||
 | 
					                <strong style="color: var(--color-primary);">${confidence.domainAlignment}%</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div style="font-size: 0.625rem; color: var(--color-text-secondary); line-height: 1.3;">
 | 
				
			||||||
 | 
					                Wie gut das Tool-Einsatzgebiet zu Ihrem forensischen Szenario passt
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            <div style="background: var(--color-bg-secondary); padding: 0.5rem; border-radius: 0.375rem; border-left: 3px solid var(--color-warning);">
 | 
				
			||||||
 | 
					              <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem;">
 | 
				
			||||||
 | 
					                <span style="font-weight: 600; font-size: 0.6875rem;">🤝 KI-Konsens</span>
 | 
				
			||||||
 | 
					                <strong style="color: var(--color-warning);">${confidence.consensus}%</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div style="font-size: 0.625rem; color: var(--color-text-secondary); line-height: 1.3;">
 | 
				
			||||||
 | 
					                Wie einig sich die verschiedenen KI-Analyseschritte über dieses Tool sind
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            <div style="background: var(--color-bg-secondary); padding: 0.5rem; border-radius: 0.375rem; border-left: 3px solid var(--color-text-secondary);">
 | 
				
			||||||
 | 
					              <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.25rem;">
 | 
				
			||||||
 | 
					                <span style="font-weight: 600; font-size: 0.6875rem;">🔄 Aktualität</span>
 | 
				
			||||||
 | 
					                <strong style="color: var(--color-text);">${confidence.freshness}%</strong>
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					              <div style="font-size: 0.625rem; color: var(--color-text-secondary); line-height: 1.3;">
 | 
				
			||||||
 | 
					                Wie aktuell und gut gepflegt das Tool ist (basierend auf Hosting-Status, Knowledge Base, Open Source)
 | 
				
			||||||
 | 
					              </div>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          ${confidence.strengthIndicators && confidence.strengthIndicators.length > 0 ? `
 | 
				
			||||||
 | 
					            <div style="margin-bottom: 0.75rem; padding: 0.5rem; background: var(--color-oss-bg); border-radius: 0.375rem; border-left: 3px solid var(--color-accent);">
 | 
				
			||||||
 | 
					              <strong style="color: var(--color-accent); font-size: 0.6875rem; display: flex; align-items: center; gap: 0.25rem; margin-bottom: 0.375rem;">
 | 
				
			||||||
 | 
					                <span>✓</span> Was für dieses Tool spricht:
 | 
				
			||||||
 | 
					              </strong>
 | 
				
			||||||
 | 
					              <ul style="margin: 0; padding-left: 1rem; font-size: 0.625rem; line-height: 1.4;">
 | 
				
			||||||
 | 
					                ${confidence.strengthIndicators.slice(0, 3).map(s => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(s)}</li>`).join('')}
 | 
				
			||||||
 | 
					              </ul>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          ` : ''}
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          ${confidence.uncertaintyFactors && confidence.uncertaintyFactors.length > 0 ? `
 | 
				
			||||||
 | 
					            <div style="padding: 0.5rem; background: var(--color-hosted-bg); border-radius: 0.375rem; border-left: 3px solid var(--color-warning);">
 | 
				
			||||||
 | 
					              <strong style="color: var(--color-warning); font-size: 0.6875rem; display: flex; align-items: center; gap: 0.25rem; margin-bottom: 0.375rem;">
 | 
				
			||||||
 | 
					                <span>⚠</span> Unsicherheitsfaktoren:
 | 
				
			||||||
 | 
					              </strong>
 | 
				
			||||||
 | 
					              <ul style="margin: 0; padding-left: 1rem; font-size: 0.625rem; line-height: 1.4;">
 | 
				
			||||||
 | 
					                ${confidence.uncertaintyFactors.slice(0, 3).map(f => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(f)}</li>`).join('')}
 | 
				
			||||||
 | 
					              </ul>
 | 
				
			||||||
 | 
					            </div>
 | 
				
			||||||
 | 
					          ` : ''}
 | 
				
			||||||
 | 
					          
 | 
				
			||||||
 | 
					          <div style="margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--color-border); font-size: 0.625rem; color: var(--color-text-secondary); text-align: center;">
 | 
				
			||||||
 | 
					            Vertrauensscore basiert auf KI-Analyse • Forensisch validiert
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
 | 
					      </span>
 | 
				
			||||||
 | 
					    `;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  renderAuditTrail(auditTrail) {
 | 
					  renderAuditTrail(auditTrail) {
 | 
				
			||||||
    if (!auditTrail || !Array.isArray(auditTrail) || auditTrail.length === 0) {
 | 
					    if (!auditTrail || !Array.isArray(auditTrail) || auditTrail.length === 0) {
 | 
				
			||||||
      return '';
 | 
					      return '';
 | 
				
			||||||
@ -1003,74 +1120,6 @@ class AIQueryInterface {
 | 
				
			|||||||
    return String(data);
 | 
					    return String(data);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  renderConfidenceIndicator(confidence) {
 | 
					 | 
				
			||||||
    if (!confidence || typeof confidence.overall !== 'number') return '';
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    const confidenceColor = confidence.overall >= 80 ? 'var(--color-accent)' : 
 | 
					 | 
				
			||||||
                           confidence.overall >= 60 ? 'var(--color-warning)' : 'var(--color-error)';
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    const strengthText = confidence.overall >= 80 ? 'HOCH' : 
 | 
					 | 
				
			||||||
                        confidence.overall >= 60 ? 'MITTEL' : 'NIEDRIG';
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    return `
 | 
					 | 
				
			||||||
      <div class="confidence-indicator-integrated" style="display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.75rem;">
 | 
					 | 
				
			||||||
        <div class="confidence-bar-wrapper" style="flex: 1; height: 4px; background-color: var(--color-bg-tertiary); border-radius: 2px; overflow: hidden;">
 | 
					 | 
				
			||||||
          <div class="confidence-bar-fill" style="width: ${confidence.overall}%; height: 100%; background-color: ${confidenceColor}; transition: var(--transition-fast);"></div>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div class="confidence-badge-compact" style="display: flex; align-items: center; gap: 0.375rem;">
 | 
					 | 
				
			||||||
          <span class="badge badge-mini" style="background-color: ${confidenceColor}; color: white; font-weight: 600; font-size: 0.625rem;">
 | 
					 | 
				
			||||||
            ${confidence.overall}%
 | 
					 | 
				
			||||||
          </span>
 | 
					 | 
				
			||||||
          <button class="btn-icon" style="width: 16px; height: 16px; padding: 0.125rem; font-size: 0.625rem;" onclick="this.parentElement.nextElementSibling.style.display = this.parentElement.nextElementSibling.style.display === 'none' ? 'block' : 'none'; this.textContent = this.textContent === 'ℹ️' ? '✕' : 'ℹ️';" title="Vertrauens-Details">ℹ️</button>
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
        <div style="display: none; position: absolute; z-index: 20; background: var(--color-bg); border: 1px solid var(--color-border); border-radius: 0.5rem; padding: 1rem; margin-top: 6rem; right: 0; min-width: 320px; box-shadow: var(--shadow-lg);" class="confidence-details-popup">
 | 
					 | 
				
			||||||
          <div style="margin-bottom: 0.75rem;">
 | 
					 | 
				
			||||||
            <div style="display: flex; justify-content: between; align-items: center; margin-bottom: 0.5rem;">
 | 
					 | 
				
			||||||
              <strong class="text-sm">Vertrauens-Komponenten</strong>
 | 
					 | 
				
			||||||
              <span class="badge badge-mini" style="background-color: ${confidenceColor}; color: white;">${strengthText}</span>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
            <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; font-size: 0.75rem;">
 | 
					 | 
				
			||||||
              <div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
 | 
					 | 
				
			||||||
                <span>Ähnlichkeit:</span>
 | 
					 | 
				
			||||||
                <span class="font-semibold">${confidence.embeddingsQuality}%</span>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
              <div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
 | 
					 | 
				
			||||||
                <span>Domain:</span>
 | 
					 | 
				
			||||||
                <span class="font-semibold">${confidence.domainAlignment}%</span>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
              <div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
 | 
					 | 
				
			||||||
                <span>Konsens:</span>
 | 
					 | 
				
			||||||
                <span class="font-semibold">${confidence.consensus}%</span>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
              <div style="display: flex; justify-content: space-between; padding: 0.25rem; background: var(--color-bg-secondary); border-radius: 0.25rem;">
 | 
					 | 
				
			||||||
                <span>Aktualität:</span>
 | 
					 | 
				
			||||||
                <span class="font-semibold">${confidence.freshness}%</span>
 | 
					 | 
				
			||||||
              </div>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          </div>
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          ${confidence.strengthIndicators && confidence.strengthIndicators.length > 0 ? `
 | 
					 | 
				
			||||||
            <div style="margin-bottom: 0.75rem;">
 | 
					 | 
				
			||||||
              <strong class="text-accent" style="font-size: 0.75rem;">✓ Stärken:</strong>
 | 
					 | 
				
			||||||
              <ul style="font-size: 0.6875rem; margin-top: 0.25rem; padding-left: 1rem; line-height: 1.3;">
 | 
					 | 
				
			||||||
                ${confidence.strengthIndicators.slice(0, 2).map(strength => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(strength)}</li>`).join('')}
 | 
					 | 
				
			||||||
              </ul>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          ` : ''}
 | 
					 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          ${confidence.uncertaintyFactors && confidence.uncertaintyFactors.length > 0 ? `
 | 
					 | 
				
			||||||
            <div style="padding-top: 0.75rem; border-top: 1px solid var(--color-border);">
 | 
					 | 
				
			||||||
              <strong class="text-warning" style="font-size: 0.75rem;">⚠ Unsicherheiten:</strong>
 | 
					 | 
				
			||||||
              <ul style="font-size: 0.6875rem; margin-top: 0.25rem; padding-left: 1rem; line-height: 1.3;">
 | 
					 | 
				
			||||||
                ${confidence.uncertaintyFactors.slice(0, 2).map(factor => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(factor)}</li>`).join('')}
 | 
					 | 
				
			||||||
              </ul>
 | 
					 | 
				
			||||||
            </div>
 | 
					 | 
				
			||||||
          ` : ''}
 | 
					 | 
				
			||||||
        </div>
 | 
					 | 
				
			||||||
      </div>
 | 
					 | 
				
			||||||
    `;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  renderWorkflowTool(tool) {
 | 
					  renderWorkflowTool(tool) {
 | 
				
			||||||
    const hasValidProjectUrl = isToolHosted(tool);
 | 
					    const hasValidProjectUrl = isToolHosted(tool);
 | 
				
			||||||
    const priorityColors = {
 | 
					    const priorityColors = {
 | 
				
			||||||
@ -1088,14 +1137,13 @@ class AIQueryInterface {
 | 
				
			|||||||
          </h4>
 | 
					          </h4>
 | 
				
			||||||
          <div class="flex items-center gap-2">
 | 
					          <div class="flex items-center gap-2">
 | 
				
			||||||
            <span class="tool-rec-priority ${tool.recommendation ? tool.recommendation.priority : tool.priority}" 
 | 
					            <span class="tool-rec-priority ${tool.recommendation ? tool.recommendation.priority : tool.priority}" 
 | 
				
			||||||
                  style="background-color: ${priorityColors[tool.recommendation ? tool.recommendation.priority : tool.priority]}; color: white; padding: 0.25rem 0.5rem; border-radius: 1rem; font-size: 0.75rem;">
 | 
					                  style="background-color: ${priorityColors[tool.recommendation ? tool.recommendation.priority : tool.priority]}; color: white; padding: 0.25rem 0.5rem; border-radius: 1rem; font-size: 0.75rem; position: relative;">
 | 
				
			||||||
              ${tool.recommendation ? tool.recommendation.priority : tool.priority}
 | 
					              ${tool.recommendation ? tool.recommendation.priority : tool.priority}
 | 
				
			||||||
 | 
					              ${tool.confidence ? this.renderConfidenceTooltip(tool.confidence, 'priority') : ''}
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        ${tool.confidence ? this.renderConfidenceIndicator(tool.confidence) : ''}
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        <div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
 | 
					        <div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
 | 
				
			||||||
          "${this.sanitizeText(tool.justification || (tool.recommendation && tool.recommendation.justification) || `Empfohlen für ${tool.phase}`)}"
 | 
					          "${this.sanitizeText(tool.justification || (tool.recommendation && tool.recommendation.justification) || `Empfohlen für ${tool.phase}`)}"
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
@ -1123,12 +1171,11 @@ class AIQueryInterface {
 | 
				
			|||||||
        <div style="margin-bottom: 1rem;">
 | 
					        <div style="margin-bottom: 1rem;">
 | 
				
			||||||
          <h3 style="margin: 0 0 0.5rem 0;">${tool.name}</h3>
 | 
					          <h3 style="margin: 0 0 0.5rem 0;">${tool.name}</h3>
 | 
				
			||||||
          <div style="display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.75rem;">
 | 
					          <div style="display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.75rem;">
 | 
				
			||||||
            <span class="badge" style="background-color: ${suitabilityColors[recommendation.suitability_score]}; color: white;">
 | 
					            <span class="badge" style="background-color: ${suitabilityColors[recommendation.suitability_score]}; color: white; position: relative;">
 | 
				
			||||||
              ${this.getSuitabilityText(recommendation.suitability_score)}
 | 
					              ${this.getSuitabilityText(recommendation.suitability_score, recommendation.confidence)}
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
            ${this.renderToolBadges(tool)}
 | 
					            ${this.renderToolBadges(tool)}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
          ${recommendation.confidence ? this.renderConfidenceIndicator(recommendation.confidence) : ''}
 | 
					 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div style="margin-bottom: 1.5rem;">
 | 
					        <div style="margin-bottom: 1.5rem;">
 | 
				
			||||||
@ -1230,6 +1277,8 @@ class AIQueryInterface {
 | 
				
			|||||||
      const phaseTools = toolsByPhase[phase];
 | 
					      const phaseTools = toolsByPhase[phase];
 | 
				
			||||||
      if (phaseTools.length === 0) return '';
 | 
					      if (phaseTools.length === 0) return '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      console.log(`[AI DEBUG] Phase ${phase} tools:`, phaseTools.map(t => ({name: t.name, hasConfidence: !!t.confidence})));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return `
 | 
					      return `
 | 
				
			||||||
        <div class="workflow-phase">
 | 
					        <div class="workflow-phase">
 | 
				
			||||||
          <div class="phase-header">
 | 
					          <div class="phase-header">
 | 
				
			||||||
@ -1237,7 +1286,10 @@ class AIQueryInterface {
 | 
				
			|||||||
            <div class="phase-info">
 | 
					            <div class="phase-info">
 | 
				
			||||||
              <h3 class="phase-title">${phaseNames[phase]}</h3>
 | 
					              <h3 class="phase-title">${phaseNames[phase]}</h3>
 | 
				
			||||||
              <div class="phase-tools">
 | 
					              <div class="phase-tools">
 | 
				
			||||||
                ${phaseTools.map(tool => this.renderWorkflowTool(tool)).join('')}
 | 
					                ${phaseTools.map(tool => {
 | 
				
			||||||
 | 
					                  console.log(`[AI DEBUG] Rendering tool ${tool.name} with confidence:`, tool.confidence);
 | 
				
			||||||
 | 
					                  return this.renderWorkflowTool(tool);
 | 
				
			||||||
 | 
					                }).join('')}
 | 
				
			||||||
              </div>
 | 
					              </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
@ -1248,6 +1300,8 @@ class AIQueryInterface {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  renderWorkflowTool(tool) {
 | 
					  renderWorkflowTool(tool) {
 | 
				
			||||||
 | 
					    console.log(`[AI DEBUG] renderWorkflowTool called for ${tool.name}, confidence:`, tool.confidence);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    const hasValidProjectUrl = isToolHosted(tool);
 | 
					    const hasValidProjectUrl = isToolHosted(tool);
 | 
				
			||||||
    const priorityColors = {
 | 
					    const priorityColors = {
 | 
				
			||||||
      high: 'var(--color-error)',
 | 
					      high: 'var(--color-error)',
 | 
				
			||||||
@ -1255,21 +1309,29 @@ class AIQueryInterface {
 | 
				
			|||||||
      low: 'var(--color-accent)'
 | 
					      low: 'var(--color-accent)'
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const priority = tool.recommendation ? tool.recommendation.priority : tool.priority;
 | 
				
			||||||
 | 
					    const confidenceTooltip = tool.confidence ? this.renderConfidenceTooltip(tool.confidence) : '';
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    console.log(`[AI DEBUG] Priority: ${priority}, Confidence tooltip:`, confidenceTooltip ? 'generated' : 'empty');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return `
 | 
					    return `
 | 
				
			||||||
      <div class="tool-recommendation ${this.getToolClass(tool, 'recommendation')}" onclick="window.showToolDetails('${tool.name}')">
 | 
					      <div class="tool-recommendation ${this.getToolClass(tool, 'recommendation')}" onclick="window.showToolDetails('${tool.name}')" style="position: relative;">
 | 
				
			||||||
        <div class="tool-rec-header">
 | 
					        <div class="tool-rec-header">
 | 
				
			||||||
          <h4 class="tool-rec-name">
 | 
					          <h4 class="tool-rec-name">
 | 
				
			||||||
            ${tool.icon ? `<span style="margin-right: 0.5rem;">${tool.icon}</span>` : ''}
 | 
					            ${tool.icon ? `<span style="margin-right: 0.5rem;">${tool.icon}</span>` : ''}
 | 
				
			||||||
            ${tool.name}
 | 
					            ${tool.name}
 | 
				
			||||||
          </h4>
 | 
					          </h4>
 | 
				
			||||||
          <span class="tool-rec-priority ${tool.recommendation.priority}" 
 | 
					          <div class="flex items-center gap-2">
 | 
				
			||||||
                style="background-color: ${priorityColors[tool.recommendation.priority]}; color: white; padding: 0.25rem 0.5rem; border-radius: 1rem; font-size: 0.75rem;">
 | 
					            <span class="tool-rec-priority ${priority}" 
 | 
				
			||||||
            ${tool.recommendation.priority}
 | 
					                  style="background-color: ${priorityColors[priority]}; color: white; padding: 0.25rem 0.5rem; border-radius: 1rem; font-size: 0.75rem; position: relative; display: flex; align-items: center; gap: 0.25rem;">
 | 
				
			||||||
          </span>
 | 
					              ${priority}
 | 
				
			||||||
 | 
					              ${confidenceTooltip}
 | 
				
			||||||
 | 
					            </span>
 | 
				
			||||||
 | 
					          </div>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
 | 
					        <div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
 | 
				
			||||||
          "${this.sanitizeText(tool.recommendation.justification)}"
 | 
					          "${this.sanitizeText(tool.justification || (tool.recommendation && tool.recommendation.justification) || `Empfohlen für ${tool.phase}`)}"
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        <div style="font-size: 0.75rem; color: var(--color-text-secondary);">
 | 
					        <div style="font-size: 0.75rem; color: var(--color-text-secondary);">
 | 
				
			||||||
@ -1301,9 +1363,13 @@ class AIQueryInterface {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  renderDetailedTool(tool, recommendation, rank) {
 | 
					  renderDetailedTool(tool, recommendation, rank) {
 | 
				
			||||||
 | 
					    console.log(`[AI DEBUG] renderDetailedTool called for ${tool.name}, recommendation confidence:`, recommendation.confidence);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    const rankColors = { 1: 'var(--color-accent)', 2: 'var(--color-primary)', 3: 'var(--color-warning)' };
 | 
					    const rankColors = { 1: 'var(--color-accent)', 2: 'var(--color-primary)', 3: 'var(--color-warning)' };
 | 
				
			||||||
    const suitabilityColors = { high: 'var(--color-accent)', medium: 'var(--color-warning)', low: 'var(--color-text-secondary)' };
 | 
					    const suitabilityColors = { high: 'var(--color-accent)', medium: 'var(--color-warning)', low: 'var(--color-text-secondary)' };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    const confidenceTooltip = recommendation.confidence ? this.renderConfidenceTooltip(recommendation.confidence) : '';
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    return `
 | 
					    return `
 | 
				
			||||||
      <div class="card ${this.getToolClass(tool, 'card')}" style="cursor: pointer; position: relative;" onclick="window.showToolDetails('${tool.name}')">
 | 
					      <div class="card ${this.getToolClass(tool, 'card')}" style="cursor: pointer; position: relative;" onclick="window.showToolDetails('${tool.name}')">
 | 
				
			||||||
        <div style="position: absolute; top: -8px; right: -8px; width: 32px; height: 32px; background-color: ${rankColors[rank]}; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 1.125rem;">
 | 
					        <div style="position: absolute; top: -8px; right: -8px; width: 32px; height: 32px; background-color: ${rankColors[rank]}; color: white; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-weight: bold; font-size: 1.125rem;">
 | 
				
			||||||
@ -1312,9 +1378,10 @@ class AIQueryInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <div style="margin-bottom: 1rem;">
 | 
					        <div style="margin-bottom: 1rem;">
 | 
				
			||||||
          <h3 style="margin: 0 0 0.5rem 0;">${tool.name}</h3>
 | 
					          <h3 style="margin: 0 0 0.5rem 0;">${tool.name}</h3>
 | 
				
			||||||
          <div style="display: flex; flex-wrap: wrap; gap: 0.5rem;">
 | 
					          <div style="display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; margin-bottom: 0.75rem;">
 | 
				
			||||||
            <span class="badge" style="background-color: ${suitabilityColors[recommendation.suitability_score]}; color: white;">
 | 
					            <span class="badge" style="background-color: ${suitabilityColors[recommendation.suitability_score]}; color: white; position: relative; display: flex; align-items: center; gap: 0.25rem;">
 | 
				
			||||||
              ${this.getSuitabilityText(recommendation.suitability_score)}
 | 
					              ${this.getSuitabilityText(recommendation.suitability_score)}
 | 
				
			||||||
 | 
					              ${confidenceTooltip}
 | 
				
			||||||
            </span>
 | 
					            </span>
 | 
				
			||||||
            ${this.renderToolBadges(tool)}
 | 
					            ${this.renderToolBadges(tool)}
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
@ -1469,13 +1536,18 @@ class AIQueryInterface {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getSuitabilityText(score) {
 | 
					  getSuitabilityText(score, confidence = null) {
 | 
				
			||||||
    const texts = {
 | 
					    const texts = {
 | 
				
			||||||
      high: 'GUT GEEIGNET',
 | 
					      high: 'GUT GEEIGNET',
 | 
				
			||||||
      medium: 'GEEIGNET', 
 | 
					      medium: 'GEEIGNET', 
 | 
				
			||||||
      low: 'VIELLEICHT GEEIGNET'
 | 
					      low: 'VIELLEICHT GEEIGNET'
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    return texts[score] || 'GEEIGNET';
 | 
					    const baseText = texts[score] || 'GEEIGNET';
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    if (confidence) {
 | 
				
			||||||
 | 
					      return `${baseText} ${this.renderConfidenceTooltip(confidence, 'suitability')}`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return baseText;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  escapeHtml(text) {
 | 
					  escapeHtml(text) {
 | 
				
			||||||
 | 
				
			|||||||
@ -2069,7 +2069,7 @@ input[type="checkbox"] {
 | 
				
			|||||||
  border-color: var(--color-method);
 | 
					  border-color: var(--color-method);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tool-recommendation:hover .confidence-bar-fill {
 | 
					.tool-recommendation:hover {
 | 
				
			||||||
  box-shadow: 0 0 8px rgba(0,0,0,0.1);
 | 
					  box-shadow: 0 0 8px rgba(0,0,0,0.1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2111,57 +2111,6 @@ input[type="checkbox"] {
 | 
				
			|||||||
  border-left: 3px solid var(--color-primary);
 | 
					  border-left: 3px solid var(--color-primary);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* ===================================================================
 | 
					 | 
				
			||||||
   CONFIDENCE INTEGRATION STYLES
 | 
					 | 
				
			||||||
   ================================================================= */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-indicator-integrated {
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-bar-wrapper {
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
  background-color: var(--color-bg-tertiary);
 | 
					 | 
				
			||||||
  border-radius: 2px;
 | 
					 | 
				
			||||||
  overflow: hidden;
 | 
					 | 
				
			||||||
  border: 1px solid var(--color-border);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-bar-fill {
 | 
					 | 
				
			||||||
  transition: width 0.6s ease-out;
 | 
					 | 
				
			||||||
  position: relative;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-bar-fill::after {
 | 
					 | 
				
			||||||
  content: '';
 | 
					 | 
				
			||||||
  position: absolute;
 | 
					 | 
				
			||||||
  top: 0;
 | 
					 | 
				
			||||||
  left: 0;
 | 
					 | 
				
			||||||
  right: 0;
 | 
					 | 
				
			||||||
  bottom: 0;
 | 
					 | 
				
			||||||
  background: linear-gradient(45deg, transparent 25%, rgba(255,255,255,0.1) 25%, rgba(255,255,255,0.1) 50%, transparent 50%, transparent 75%, rgba(255,255,255,0.1) 75%);
 | 
					 | 
				
			||||||
  background-size: 8px 8px;
 | 
					 | 
				
			||||||
  animation: confidence-shimmer 2s linear infinite;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-badge-compact .btn-icon {
 | 
					 | 
				
			||||||
  transition: var(--transition-fast);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-badge-compact .btn-icon:hover {
 | 
					 | 
				
			||||||
  background-color: var(--color-bg-secondary);
 | 
					 | 
				
			||||||
  transform: scale(1.1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
.confidence-details-popup {
 | 
					 | 
				
			||||||
  animation: confidence-popup-in 0.2s ease-out;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* Hover effect for confidence bars */
 | 
					 | 
				
			||||||
.confidence-indicator-integrated:hover .confidence-bar-fill {
 | 
					 | 
				
			||||||
  filter: brightness(1.1);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* ===================================================================
 | 
					/* ===================================================================
 | 
				
			||||||
   18. APPROACH SELECTION (CONSOLIDATED)
 | 
					   18. APPROACH SELECTION (CONSOLIDATED)
 | 
				
			||||||
   ================================================================= */
 | 
					   ================================================================= */
 | 
				
			||||||
@ -2563,22 +2512,6 @@ footer {
 | 
				
			|||||||
  animation: ai-spotlight-pulse 0.4s ease-out;
 | 
					  animation: ai-spotlight-pulse 0.4s ease-out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@keyframes confidence-shimmer {
 | 
					 | 
				
			||||||
  0% { transform: translateX(-8px); }
 | 
					 | 
				
			||||||
  100% { transform: translateX(8px); }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@keyframes confidence-popup-in {
 | 
					 | 
				
			||||||
  from {
 | 
					 | 
				
			||||||
    opacity: 0;
 | 
					 | 
				
			||||||
    transform: translateY(-8px);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  to {
 | 
					 | 
				
			||||||
    opacity: 1;
 | 
					 | 
				
			||||||
    transform: translateY(0);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/* ===================================================================
 | 
					/* ===================================================================
 | 
				
			||||||
   21. SMART PROMPTING INTERFACE (MISSING STYLES ADDED BACK)
 | 
					   21. SMART PROMPTING INTERFACE (MISSING STYLES ADDED BACK)
 | 
				
			||||||
   ================================================================= */
 | 
					   ================================================================= */
 | 
				
			||||||
@ -3501,26 +3434,6 @@ footer {
 | 
				
			|||||||
    width: 14px;
 | 
					    width: 14px;
 | 
				
			||||||
    height: 14px;
 | 
					    height: 14px;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  .confidence-details-popup {
 | 
					 | 
				
			||||||
    position: fixed !important;
 | 
					 | 
				
			||||||
    top: 50% !important;
 | 
					 | 
				
			||||||
    left: 50% !important;
 | 
					 | 
				
			||||||
    transform: translate(-50%, -50%) !important;
 | 
					 | 
				
			||||||
    margin: 0 !important;
 | 
					 | 
				
			||||||
    width: 90vw !important;
 | 
					 | 
				
			||||||
    max-width: 300px !important;
 | 
					 | 
				
			||||||
    z-index: 1000 !important;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  .confidence-indicator-integrated {
 | 
					 | 
				
			||||||
    margin-bottom: 0.5rem;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  .confidence-badge-compact .btn-icon {
 | 
					 | 
				
			||||||
    width: 18px;
 | 
					 | 
				
			||||||
    height: 18px;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media (width <= 640px) {
 | 
					@media (width <= 640px) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1101,11 +1101,15 @@ ${JSON.stringify(conceptsToSend, null, 2)}`;
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    const queryLower = userQuery.toLowerCase();
 | 
					    const queryLower = userQuery.toLowerCase();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const domainKeywordsEnv = process.env.CONFIDENCE_DOMAIN_KEYWORDS || '';
 | 
					    // Load domain keywords from environment with fallback
 | 
				
			||||||
 | 
					    const domainKeywordsEnv = process.env.CONFIDENCE_DOMAIN_KEYWORDS || 
 | 
				
			||||||
 | 
					      'incident-response:incident,breach,attack,compromise,response|malware-analysis:malware,virus,trojan,reverse,analysis|network-forensics:network,traffic,packet,pcap,wireshark|mobile-forensics:mobile,android,ios,phone,app|cloud-forensics:cloud,aws,azure,saas,paas';
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const domainKeywords = domainKeywordsEnv.split('|').reduce((acc, pair) => {
 | 
					    const domainKeywords = domainKeywordsEnv.split('|').reduce((acc, pair) => {
 | 
				
			||||||
      const [domain, keywords] = pair.split(':');
 | 
					      const [domain, keywords] = pair.split(':');
 | 
				
			||||||
      acc[domain] = keywords.split(',');
 | 
					      if (domain && keywords) {
 | 
				
			||||||
 | 
					        acc[domain] = keywords.split(',');
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      return acc;
 | 
					      return acc;
 | 
				
			||||||
    }, {});
 | 
					    }, {});
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user