some cleanup
This commit is contained in:
		
							parent
							
								
									07c8f707df
								
							
						
					
					
						commit
						5ecbabea90
					
				@ -423,8 +423,6 @@ class AIQueryInterface {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setupEventListeners() {   
 | 
			
		||||
    console.log('[AI Interface] Setting up event listeners...');
 | 
			
		||||
    
 | 
			
		||||
    this.elements.toggleSwitch?.addEventListener('click', () => this.toggleMode());
 | 
			
		||||
    this.elements.workflowLabel?.addEventListener('click', () => this.setMode('workflow'));
 | 
			
		||||
    this.elements.toolLabel?.addEventListener('click', () => this.setMode('tool'));
 | 
			
		||||
@ -438,13 +436,10 @@ class AIQueryInterface {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (this.elements.submitBtn) {
 | 
			
		||||
      console.log('[AI Interface] Attaching click handler to submit button');
 | 
			
		||||
      this.elements.submitBtn.addEventListener('click', () => {
 | 
			
		||||
        console.log('[AI Interface] Submit button clicked!');
 | 
			
		||||
        this.handleSubmit();
 | 
			
		||||
      });
 | 
			
		||||
    } else {
 | 
			
		||||
      console.error('[AI Interface] Submit button not found!');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.elements.dismissSuggestions?.addEventListener('click', () => this.hideSmartPrompting());
 | 
			
		||||
@ -655,8 +650,6 @@ class AIQueryInterface {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async handleSubmit() {   
 | 
			
		||||
    console.log('[AI Interface] handleSubmit called');
 | 
			
		||||
    
 | 
			
		||||
    const query = this.elements.input.value.trim();
 | 
			
		||||
    
 | 
			
		||||
    if (!query) {
 | 
			
		||||
@ -1084,7 +1077,6 @@ class AIQueryInterface {
 | 
			
		||||
      if (downloadBtn && !downloadBtn.hasAttribute('data-setup')) {
 | 
			
		||||
        downloadBtn.setAttribute('data-setup', 'true');
 | 
			
		||||
        downloadBtn.addEventListener('click', () => this.downloadResults());
 | 
			
		||||
        console.log('[AI Interface] Download button setup complete');
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -1119,7 +1111,6 @@ class AIQueryInterface {
 | 
			
		||||
        qualityMetrics: {
 | 
			
		||||
          avgProcessingTime: 0,
 | 
			
		||||
          confidenceDistribution: { high: 0, medium: 0, low: 0 }
 | 
			
		||||
          // Removed aiTransparency
 | 
			
		||||
        },
 | 
			
		||||
        analysisQuality: 'excellent',
 | 
			
		||||
        keyInsights: [
 | 
			
		||||
@ -1602,25 +1593,33 @@ class AIQueryInterface {
 | 
			
		||||
        concept_name: bg.concept_name,
 | 
			
		||||
        relevance: bg.relevance
 | 
			
		||||
      })) || [],
 | 
			
		||||
      contextHistory: [], // This would need to be passed from server if needed
 | 
			
		||||
      embeddingsSimilarities: {} // This would need to be passed from server if needed
 | 
			
		||||
      contextHistory: [],
 | 
			
		||||
      embeddingsSimilarities: {}
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    // Enhanced export structure with proper audit trail handling
 | 
			
		||||
    const exportData = {
 | 
			
		||||
      metadata: {
 | 
			
		||||
        timestamp: new Date().toISOString(),
 | 
			
		||||
        version: "1.0",
 | 
			
		||||
        version: "1.1", // Increment version for improved structure
 | 
			
		||||
        toolsDataHash: toolsDataHash,
 | 
			
		||||
        aiModel: aiModel,
 | 
			
		||||
        aiParameters: aiParameters,
 | 
			
		||||
        userQuery: inputValue,
 | 
			
		||||
        mode: this.currentMode,
 | 
			
		||||
        processingStats: processingStats,
 | 
			
		||||
        exportedBy: 'ForensicPathways'
 | 
			
		||||
        exportedBy: 'ForensicPathways',
 | 
			
		||||
        auditTrailVersion: '1.1' // Track audit trail format version
 | 
			
		||||
      },
 | 
			
		||||
      recommendation: this.currentRecommendation,
 | 
			
		||||
      auditTrail: this.currentRecommendation.auditTrail || [],
 | 
			
		||||
      rawContext: rawContext
 | 
			
		||||
      recommendation: {
 | 
			
		||||
        // Export recommendation without auditTrail to avoid duplication
 | 
			
		||||
        ...this.currentRecommendation,
 | 
			
		||||
        auditTrail: undefined // Remove from recommendation as it's at top level
 | 
			
		||||
      },
 | 
			
		||||
      auditTrail: this.currentRecommendation.auditTrail || [], // Extract to top level
 | 
			
		||||
      rawContext: rawContext,
 | 
			
		||||
      // Add validation checksum for integrity
 | 
			
		||||
      checksum: this.calculateDataChecksum(this.currentRecommendation)
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    const blob = new Blob([JSON.stringify(exportData, null, 2)], {
 | 
			
		||||
@ -1634,17 +1633,46 @@ class AIQueryInterface {
 | 
			
		||||
    a.click();
 | 
			
		||||
    URL.revokeObjectURL(url);
 | 
			
		||||
    
 | 
			
		||||
    console.log('[AI Interface] Analysis downloaded with real metadata:', {
 | 
			
		||||
    console.log('[AI Interface] Analysis downloaded with enhanced structure:', {
 | 
			
		||||
      version: '1.1',
 | 
			
		||||
      aiModel,
 | 
			
		||||
      toolsDataHash: toolsDataHash.slice(0, 8) + '...',
 | 
			
		||||
      tokensUsed: aiParameters.totalTokensUsed,
 | 
			
		||||
      auditEntries: exportData.auditTrail.length
 | 
			
		||||
      auditEntries: exportData.auditTrail.length,
 | 
			
		||||
      checksum: exportData.checksum.slice(0, 8) + '...'
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculateDataChecksum(data) {
 | 
			
		||||
    if (!data) return 'empty';
 | 
			
		||||
    
 | 
			
		||||
    try {
 | 
			
		||||
      // Simple checksum based on key data properties
 | 
			
		||||
      const keyData = {
 | 
			
		||||
        recommendedToolsCount: data.recommended_tools?.length || 0,
 | 
			
		||||
        backgroundKnowledgeCount: data.background_knowledge?.length || 0,
 | 
			
		||||
        hasScenarioAnalysis: !!(data.scenario_analysis || data.problem_analysis),
 | 
			
		||||
        hasApproach: !!data.investigation_approach,
 | 
			
		||||
        processingTimeMs: data.processingStats?.processingTimeMs || 0
 | 
			
		||||
      };
 | 
			
		||||
      
 | 
			
		||||
      const dataString = JSON.stringify(keyData);
 | 
			
		||||
      let hash = 0;
 | 
			
		||||
      for (let i = 0; i < dataString.length; i++) {
 | 
			
		||||
        const char = dataString.charCodeAt(i);
 | 
			
		||||
        hash = ((hash << 5) - hash) + char;
 | 
			
		||||
        hash = hash & hash; // Convert to 32-bit integer
 | 
			
		||||
      }
 | 
			
		||||
      return Math.abs(hash).toString(36);
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.error('[AI Interface] Checksum calculation failed:', error);
 | 
			
		||||
      return 'error';
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  validateUploadStructure(data) {
 | 
			
		||||
    try {
 | 
			
		||||
      return !!(
 | 
			
		||||
      const isValid = !!(
 | 
			
		||||
        data &&
 | 
			
		||||
        typeof data === 'object' &&
 | 
			
		||||
        data.metadata &&
 | 
			
		||||
@ -1652,8 +1680,32 @@ class AIQueryInterface {
 | 
			
		||||
        typeof data.metadata.timestamp === 'string' &&
 | 
			
		||||
        data.recommendation &&
 | 
			
		||||
        typeof data.recommendation === 'object' &&
 | 
			
		||||
        Array.isArray(data.auditTrail)
 | 
			
		||||
        Array.isArray(data.auditTrail) // Audit trail at top level
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      if (!isValid) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Enhanced validation for audit trail structure
 | 
			
		||||
      if (data.auditTrail.length > 0) {
 | 
			
		||||
        const sampleEntry = data.auditTrail[0];
 | 
			
		||||
        const hasRequiredFields = !!(
 | 
			
		||||
          sampleEntry &&
 | 
			
		||||
          typeof sampleEntry === 'object' &&
 | 
			
		||||
          typeof sampleEntry.timestamp === 'number' &&
 | 
			
		||||
          typeof sampleEntry.phase === 'string' &&
 | 
			
		||||
          typeof sampleEntry.action === 'string' &&
 | 
			
		||||
          typeof sampleEntry.confidence === 'number'
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        if (!hasRequiredFields) {
 | 
			
		||||
          console.warn('[AI Interface] Audit trail entries missing required fields');
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      return true;
 | 
			
		||||
    } catch (error) {
 | 
			
		||||
      console.error('[AI Interface] Structure validation error:', error);
 | 
			
		||||
      return false;
 | 
			
		||||
@ -1666,7 +1718,11 @@ class AIQueryInterface {
 | 
			
		||||
      
 | 
			
		||||
      this.showUploadedBanner(data.metadata);
 | 
			
		||||
      
 | 
			
		||||
      this.currentRecommendation = data.recommendation;
 | 
			
		||||
      // Fix: Ensure audit trail is available in recommendation for restoreAIResults
 | 
			
		||||
      this.currentRecommendation = {
 | 
			
		||||
        ...data.recommendation,
 | 
			
		||||
        auditTrail: data.auditTrail // Restore audit trail to recommendation object
 | 
			
		||||
      };
 | 
			
		||||
      
 | 
			
		||||
      this.showResults();
 | 
			
		||||
      
 | 
			
		||||
@ -1757,7 +1813,15 @@ class AIQueryInterface {
 | 
			
		||||
        throw new Error('Ungültiges Analyse-Dateiformat');
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      console.log('[AI Interface] Valid previous analysis file uploaded');
 | 
			
		||||
      // Store audit trail separately for restore function
 | 
			
		||||
      this.uploadedAuditTrail = data.auditTrail;
 | 
			
		||||
      
 | 
			
		||||
      console.log('[AI Interface] Valid previous analysis file uploaded:', {
 | 
			
		||||
        version: data.metadata.version || '1.0',
 | 
			
		||||
        auditEntries: data.auditTrail?.length || 0,
 | 
			
		||||
        toolsCount: data.recommendation.recommended_tools?.length || 0,
 | 
			
		||||
        checksum: data.checksum?.slice(0, 8) + '...' || 'none'
 | 
			
		||||
      });
 | 
			
		||||
      
 | 
			
		||||
      this.hideResults();
 | 
			
		||||
      this.hideError();
 | 
			
		||||
@ -2218,15 +2282,20 @@ class AIQueryInterface {
 | 
			
		||||
    if (this.currentRecommendation && this.elements.results) {
 | 
			
		||||
      this.showResults();
 | 
			
		||||
      
 | 
			
		||||
      if (this.currentRecommendation.auditTrail) {
 | 
			
		||||
      // Check both locations for audit trail for backward compatibility
 | 
			
		||||
      const auditTrail = this.currentRecommendation.auditTrail || this.uploadedAuditTrail;
 | 
			
		||||
      
 | 
			
		||||
      if (auditTrail && Array.isArray(auditTrail) && auditTrail.length > 0) {
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          try {
 | 
			
		||||
            this.renderAuditTrail(this.currentRecommendation.auditTrail);
 | 
			
		||||
            console.log('[AI Interface] Audit trail restored successfully');
 | 
			
		||||
            this.renderAuditTrail(auditTrail);
 | 
			
		||||
            console.log('[AI Interface] Audit trail restored successfully:', auditTrail.length, 'entries');
 | 
			
		||||
          } catch (error) {
 | 
			
		||||
            console.error('[AI Interface] Audit trail restore failed:', error);
 | 
			
		||||
          }
 | 
			
		||||
        }, 100);
 | 
			
		||||
      } else {
 | 
			
		||||
        console.warn('[AI Interface] No audit trail available for restore');
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      this.hideLoading();
 | 
			
		||||
 | 
			
		||||
@ -511,8 +511,6 @@ if (aiAuthRequired) {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    function handleSharedURL() {     
 | 
			
		||||
      console.log('[SHARE] Handling shared URL:', window.location.search);
 | 
			
		||||
      
 | 
			
		||||
      const urlParams = new URLSearchParams(window.location.search);
 | 
			
		||||
      const toolParam = urlParams.get('tool');
 | 
			
		||||
      const viewParam = urlParams.get('view');
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,4 @@
 | 
			
		||||
// src/utils/aiPipeline.ts - Fixed with accurate audit data and meaningful confidence
 | 
			
		||||
// src/utils/aiPipeline.ts - Fixed to remove hardcoded values and improve dynamics
 | 
			
		||||
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
 | 
			
		||||
import { aiService } from './aiService.js';
 | 
			
		||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
			
		||||
@ -77,6 +77,12 @@ interface PipelineContext {
 | 
			
		||||
  }>;
 | 
			
		||||
  seenToolNames: Set<string>;
 | 
			
		||||
  embeddingsSimilarities: Map<string, number>;
 | 
			
		||||
  // Add phase metadata for dynamic phase handling
 | 
			
		||||
  phaseMetadata?: {
 | 
			
		||||
    phases: any[];
 | 
			
		||||
    criticalPhaseIds: string[];
 | 
			
		||||
    phaseComplexity: Map<string, number>;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class AIPipeline {
 | 
			
		||||
@ -95,7 +101,7 @@ class AIPipeline {
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    console.log('[AI-PIPELINE] Initialized with improved audit accuracy');
 | 
			
		||||
    console.log('[AI-PIPELINE] Initialized with dynamic phase handling');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
 | 
			
		||||
@ -121,17 +127,16 @@ class AIPipeline {
 | 
			
		||||
        maxContextLength: this.config.maxContextTokens,
 | 
			
		||||
        currentContextLength: 0,
 | 
			
		||||
        seenToolNames: new Set<string>(),
 | 
			
		||||
        embeddingsSimilarities: new Map<string, number>()
 | 
			
		||||
        embeddingsSimilarities: new Map<string, number>(),
 | 
			
		||||
        // Initialize phase metadata dynamically
 | 
			
		||||
        phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      // Skip initialization audit entry - it doesn't add transparency value
 | 
			
		||||
 | 
			
		||||
      console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
 | 
			
		||||
      const candidateSelectionStart = Date.now();
 | 
			
		||||
      
 | 
			
		||||
      const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
 | 
			
		||||
      
 | 
			
		||||
      // Calculate meaningful confidence for tool selection
 | 
			
		||||
      const selectionConfidence = this.calculateToolSelectionConfidence(
 | 
			
		||||
        candidateData.tools.length,
 | 
			
		||||
        toolsData.tools.length,
 | 
			
		||||
@ -197,8 +202,6 @@ class AIPipeline {
 | 
			
		||||
 | 
			
		||||
      const recommendation = this.buildRecommendation(context, mode, finalResult.content);
 | 
			
		||||
 | 
			
		||||
      // Skip completion audit entry - it doesn't add transparency value
 | 
			
		||||
 | 
			
		||||
      const processingStats = {
 | 
			
		||||
        embeddingsUsed: embeddingsService.isEnabled(),
 | 
			
		||||
        candidatesFromEmbeddings: candidateData.tools.length,
 | 
			
		||||
@ -242,6 +245,55 @@ class AIPipeline {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private initializePhaseMetadata(phases: any[]): {
 | 
			
		||||
    phases: any[];
 | 
			
		||||
    criticalPhaseIds: string[];
 | 
			
		||||
    phaseComplexity: Map<string, number>;
 | 
			
		||||
  } {
 | 
			
		||||
    if (!phases || !Array.isArray(phases)) {
 | 
			
		||||
      console.warn('[AI-PIPELINE] No phases data available, using fallback');
 | 
			
		||||
      return {
 | 
			
		||||
        phases: [],
 | 
			
		||||
        criticalPhaseIds: [],
 | 
			
		||||
        phaseComplexity: new Map()
 | 
			
		||||
      };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Dynamically determine critical phases based on typical_tools or key_activities
 | 
			
		||||
    const criticalPhaseIds = phases
 | 
			
		||||
      .filter(phase => {
 | 
			
		||||
        const typicalToolsCount = phase.typical_tools?.length || 0;
 | 
			
		||||
        const keyActivitiesCount = phase.key_activities?.length || 0;
 | 
			
		||||
        // Consider phases with many tools or activities as critical
 | 
			
		||||
        return typicalToolsCount >= 3 || keyActivitiesCount >= 2;
 | 
			
		||||
      })
 | 
			
		||||
      .map(phase => phase.id);
 | 
			
		||||
 | 
			
		||||
    // Calculate phase complexity based on metadata
 | 
			
		||||
    const phaseComplexity = new Map<string, number>();
 | 
			
		||||
    phases.forEach(phase => {
 | 
			
		||||
      let complexity = 1; // Base complexity
 | 
			
		||||
      
 | 
			
		||||
      if (phase.typical_tools?.length > 5) complexity += 1;
 | 
			
		||||
      if (phase.key_activities?.length > 3) complexity += 1;
 | 
			
		||||
      if (phase.description?.length > 100) complexity += 1;
 | 
			
		||||
      
 | 
			
		||||
      phaseComplexity.set(phase.id, complexity);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    console.log('[AI-PIPELINE] Initialized phase metadata:', {
 | 
			
		||||
      totalPhases: phases.length,
 | 
			
		||||
      criticalPhases: criticalPhaseIds.length,
 | 
			
		||||
      avgComplexity: Array.from(phaseComplexity.values()).reduce((sum, c) => sum + c, 0) / phases.length
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      phases,
 | 
			
		||||
      criticalPhaseIds,
 | 
			
		||||
      phaseComplexity
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private calculateToolSelectionConfidence(
 | 
			
		||||
    selectedCount: number,
 | 
			
		||||
    totalCount: number,
 | 
			
		||||
@ -252,26 +304,22 @@ class AIPipeline {
 | 
			
		||||
    
 | 
			
		||||
    const selectionRatio = selectedCount / totalCount;
 | 
			
		||||
    
 | 
			
		||||
    // Good selection ratio (5-20% is optimal)
 | 
			
		||||
    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
			
		||||
      confidence += 25;
 | 
			
		||||
    } else if (selectionRatio < 0.05) {
 | 
			
		||||
      confidence += 15; // Very selective
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    } else if (selectionRatio > 0.30) {
 | 
			
		||||
      confidence -= 15; // Too inclusive
 | 
			
		||||
      confidence -= 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Embeddings method bonus
 | 
			
		||||
    if (method.includes('embeddings')) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Concepts also selected
 | 
			
		||||
    if (conceptsCount > 0) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Reasonable absolute numbers
 | 
			
		||||
    if (selectedCount >= 8 && selectedCount <= 25) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
@ -301,12 +349,12 @@ class AIPipeline {
 | 
			
		||||
      
 | 
			
		||||
      const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
 | 
			
		||||
      
 | 
			
		||||
      // Calculate meaningful confidence based on phase selection quality
 | 
			
		||||
      const phaseConfidence = this.calculatePhaseSelectionConfidence(
 | 
			
		||||
        selections.length,
 | 
			
		||||
        phaseTools.length,
 | 
			
		||||
        phase.id,
 | 
			
		||||
        selections
 | 
			
		||||
        selections,
 | 
			
		||||
        context.phaseMetadata
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      auditService.addEntry(
 | 
			
		||||
@ -341,7 +389,10 @@ class AIPipeline {
 | 
			
		||||
          const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
 | 
			
		||||
          const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
			
		||||
          
 | 
			
		||||
          this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, sel.limitations);
 | 
			
		||||
          // Generate dynamic limitations based on context
 | 
			
		||||
          const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
 | 
			
		||||
          
 | 
			
		||||
          this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
 | 
			
		||||
          
 | 
			
		||||
          auditService.addEntry(
 | 
			
		||||
            'tool-reasoning',
 | 
			
		||||
@ -354,7 +405,7 @@ class AIPipeline {
 | 
			
		||||
            },
 | 
			
		||||
            { 
 | 
			
		||||
              justification: sel.justification, 
 | 
			
		||||
              limitations: sel.limitations,
 | 
			
		||||
              limitations: dynamicLimitations,
 | 
			
		||||
              addedToPhase: phase.name
 | 
			
		||||
            },
 | 
			
		||||
            moderatedTaskRelevance || 70,
 | 
			
		||||
@ -384,19 +435,24 @@ class AIPipeline {
 | 
			
		||||
    selectedCount: number,
 | 
			
		||||
    availableCount: number,
 | 
			
		||||
    phaseId: string,
 | 
			
		||||
    selections: any[]
 | 
			
		||||
    selections: any[],
 | 
			
		||||
    phaseMetadata?: {
 | 
			
		||||
      phases: any[];
 | 
			
		||||
      criticalPhaseIds: string[];
 | 
			
		||||
      phaseComplexity: Map<string, number>;
 | 
			
		||||
    }
 | 
			
		||||
  ): number {
 | 
			
		||||
    let confidence = 60;
 | 
			
		||||
    
 | 
			
		||||
    // Phase-specific expectations
 | 
			
		||||
    const criticalPhases = ['acquisition', 'examination', 'analysis'];
 | 
			
		||||
    const isCritical = criticalPhases.includes(phaseId);
 | 
			
		||||
    // Use dynamic phase metadata instead of hardcoded values
 | 
			
		||||
    const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
 | 
			
		||||
    const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
 | 
			
		||||
    
 | 
			
		||||
    // Selection made
 | 
			
		||||
    if (selectedCount > 0) {
 | 
			
		||||
      confidence += 20;
 | 
			
		||||
    } else {
 | 
			
		||||
      return 30; // No selection is concerning
 | 
			
		||||
      return 30;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Selection ratio (for phases, 20-50% is reasonable)
 | 
			
		||||
@ -404,14 +460,19 @@ class AIPipeline {
 | 
			
		||||
    if (ratio >= 0.2 && ratio <= 0.5) {
 | 
			
		||||
      confidence += 15;
 | 
			
		||||
    } else if (ratio < 0.2 && selectedCount >= 1) {
 | 
			
		||||
      confidence += 10; // Selective is ok
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Critical phases should have adequate tools
 | 
			
		||||
    // Dynamic critical phase handling
 | 
			
		||||
    if (isCritical && selectedCount >= 2) {
 | 
			
		||||
      confidence += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Phase complexity factor
 | 
			
		||||
    if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
 | 
			
		||||
      confidence += 5;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Quality of selections (based on task relevance)
 | 
			
		||||
    const avgRelevance = selections.length > 0 ? 
 | 
			
		||||
      selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
 | 
			
		||||
@ -425,6 +486,35 @@ class AIPipeline {
 | 
			
		||||
    return Math.min(95, Math.max(30, confidence));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private generateDynamicLimitations(tool: any, phase: any, selection: any): string[] {
 | 
			
		||||
    const limitations: string[] = [];
 | 
			
		||||
    
 | 
			
		||||
    // Add existing limitations if provided
 | 
			
		||||
    if (selection.limitations && Array.isArray(selection.limitations)) {
 | 
			
		||||
      limitations.push(...selection.limitations);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Generate context-aware limitations
 | 
			
		||||
    if (tool.type === 'software' && !tool.projectUrl) {
 | 
			
		||||
      limitations.push('Installation und Konfiguration erforderlich');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (tool.skillLevel === 'expert') {
 | 
			
		||||
      limitations.push('Erfordert spezialisierte Kenntnisse');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (tool.license === 'Proprietary') {
 | 
			
		||||
      limitations.push('Kommerzielle Lizenz erforderlich');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Phase-specific limitations
 | 
			
		||||
    if (phase.id === 'acquisition' && tool.type === 'method') {
 | 
			
		||||
      limitations.push('Sorgfältige Dokumentation für Chain of Custody erforderlich');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return limitations.slice(0, 3); // Limit to 3 most relevant
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async processToolMode(
 | 
			
		||||
    context: PipelineContext, 
 | 
			
		||||
    completedTasks: number, 
 | 
			
		||||
@ -582,7 +672,6 @@ class AIPipeline {
 | 
			
		||||
        };
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // This is the fix for "0 tools added" - use the actual valid tools
 | 
			
		||||
      const actualToolsAdded = validTools.map(tool => tool.name);
 | 
			
		||||
      
 | 
			
		||||
      for (const tool of validTools) {
 | 
			
		||||
@ -610,6 +699,9 @@ class AIPipeline {
 | 
			
		||||
          moderatedTaskRelevance = this.moderateTaskRelevance(75);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // Generate dynamic limitations instead of hardcoded ones
 | 
			
		||||
        const dynamicLimitations = this.generateCompletionLimitations(tool, phase, selection);
 | 
			
		||||
        
 | 
			
		||||
        this.addToolToSelection(
 | 
			
		||||
          context,
 | 
			
		||||
          tool,
 | 
			
		||||
@ -617,16 +709,15 @@ class AIPipeline {
 | 
			
		||||
          'medium',
 | 
			
		||||
          detailedJustification,
 | 
			
		||||
          moderatedTaskRelevance,
 | 
			
		||||
          ['Nachträgliche Ergänzung via semantische Phasensuche mit KI-Bewertung']
 | 
			
		||||
          dynamicLimitations
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
 | 
			
		||||
      }
 | 
			
		||||
      
 | 
			
		||||
      // Use the actual tools added for audit
 | 
			
		||||
      auditService.addPhaseCompletion(
 | 
			
		||||
        phase.id,
 | 
			
		||||
        actualToolsAdded, // This ensures correct count
 | 
			
		||||
        actualToolsAdded,
 | 
			
		||||
        selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
 | 
			
		||||
        phaseStart,
 | 
			
		||||
        {
 | 
			
		||||
@ -660,6 +751,29 @@ class AIPipeline {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private generateCompletionLimitations(tool: any, phase: any, selection: any): string[] {
 | 
			
		||||
    const limitations: string[] = [];
 | 
			
		||||
    
 | 
			
		||||
    // Context-specific limitation for completion tools
 | 
			
		||||
    limitations.push('Nachträgliche Ergänzung - ursprünglich nicht als Hauptmethode identifiziert');
 | 
			
		||||
    
 | 
			
		||||
    // Tool-specific limitations
 | 
			
		||||
    if (tool.skillLevel === 'expert') {
 | 
			
		||||
      limitations.push('Erfordert Expertenwissen für optimale Nutzung');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (tool.type === 'software' && !tool.projectUrl) {
 | 
			
		||||
      limitations.push('Zusätzliche Setup-Zeit erforderlich');
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Phase-specific context
 | 
			
		||||
    if (phase.typical_tools && !phase.typical_tools.includes(tool.name)) {
 | 
			
		||||
      limitations.push(`Nicht typisch für ${phase.name}-Phase - alternative Anwendung`);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    return limitations.slice(0, 3);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private moderateTaskRelevance(taskRelevance: number): number {
 | 
			
		||||
    if (typeof taskRelevance !== 'number') {
 | 
			
		||||
      return 70;
 | 
			
		||||
@ -904,7 +1018,6 @@ class AIPipeline {
 | 
			
		||||
          'background-knowledge'
 | 
			
		||||
        );
 | 
			
		||||
        
 | 
			
		||||
        // Calculate confidence based on quality of selections
 | 
			
		||||
        const selectionQualityBonus = this.calculateKnowledgeSelectionBonus(context.backgroundKnowledge, availableConcepts);
 | 
			
		||||
        const finalConfidence = Math.min(95, responseConfidence + selectionQualityBonus);
 | 
			
		||||
        
 | 
			
		||||
@ -951,13 +1064,11 @@ class AIPipeline {
 | 
			
		||||
      bonus += 10;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Good selection ratio (10-30% of available concepts)
 | 
			
		||||
    const ratio = selectedKnowledge.length / availableConcepts.length;
 | 
			
		||||
    if (ratio >= 0.1 && ratio <= 0.3) {
 | 
			
		||||
      bonus += 15;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // Quality reasoning provided
 | 
			
		||||
    const hasGoodReasonings = selectedKnowledge.some(bk => 
 | 
			
		||||
      bk.relevance && bk.relevance.length > 30
 | 
			
		||||
    );
 | 
			
		||||
@ -983,7 +1094,6 @@ class AIPipeline {
 | 
			
		||||
        'final-recommendations'
 | 
			
		||||
      );
 | 
			
		||||
      
 | 
			
		||||
      // Calculate bonus based on context quality
 | 
			
		||||
      const contextBonus = this.calculateSynthesisBonus(selectedToolNames, context);
 | 
			
		||||
      const finalConfidence = Math.min(95, confidence + contextBonus);
 | 
			
		||||
      
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user