cleanup
This commit is contained in:
		
							parent
							
								
									5ecbabea90
								
							
						
					
					
						commit
						bcd92af8a0
					
				@ -1185,7 +1185,6 @@ class AIQueryInterface {
 | 
				
			|||||||
      keyInsights.push('Mehrheit der Analyseschritte mit hoher Sicherheit');
 | 
					      keyInsights.push('Mehrheit der Analyseschritte mit hoher Sicherheit');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Calculate meaningful insights based on response quality
 | 
					 | 
				
			||||||
    const responseQualityEntries = auditTrail.filter(e => 
 | 
					    const responseQualityEntries = auditTrail.filter(e => 
 | 
				
			||||||
      e.metadata?.responseConfidence && e.metadata.finalConfidence
 | 
					      e.metadata?.responseConfidence && e.metadata.finalConfidence
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
@ -1204,7 +1203,6 @@ class AIQueryInterface {
 | 
				
			|||||||
      potentialIssues.push(`${lowConfidenceSteps} Analyseschritte mit niedriger Konfidenz`);
 | 
					      potentialIssues.push(`${lowConfidenceSteps} Analyseschritte mit niedriger Konfidenz`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check for truncated responses
 | 
					 | 
				
			||||||
    const truncatedResponses = auditTrail.filter(e => 
 | 
					    const truncatedResponses = auditTrail.filter(e => 
 | 
				
			||||||
      e.output && typeof e.output === 'object' && 
 | 
					      e.output && typeof e.output === 'object' && 
 | 
				
			||||||
      e.output.response && e.output.response.includes('...')
 | 
					      e.output.response && e.output.response.includes('...')
 | 
				
			||||||
@ -1230,7 +1228,6 @@ class AIQueryInterface {
 | 
				
			|||||||
          medium: mediumConfidenceSteps, 
 | 
					          medium: mediumConfidenceSteps, 
 | 
				
			||||||
          low: lowConfidenceSteps 
 | 
					          low: lowConfidenceSteps 
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        // aiTransparency removed entirely
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      analysisQuality,
 | 
					      analysisQuality,
 | 
				
			||||||
      keyInsights,
 | 
					      keyInsights,
 | 
				
			||||||
@ -1339,7 +1336,6 @@ class AIQueryInterface {
 | 
				
			|||||||
    const details = [];
 | 
					    const details = [];
 | 
				
			||||||
    const metadata = entry.metadata || {};
 | 
					    const metadata = entry.metadata || {};
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // The backend now provides meaningful inputSummary and outputSummary
 | 
					 | 
				
			||||||
    if (metadata.inputSummary && metadata.inputSummary !== 'Leer') {
 | 
					    if (metadata.inputSummary && metadata.inputSummary !== 'Leer') {
 | 
				
			||||||
      details.push(`<div class="detail-item"><strong>Eingabe:</strong> ${escapeHtml(metadata.inputSummary)}</div>`);
 | 
					      details.push(`<div class="detail-item"><strong>Eingabe:</strong> ${escapeHtml(metadata.inputSummary)}</div>`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1348,12 +1344,10 @@ class AIQueryInterface {
 | 
				
			|||||||
      details.push(`<div class="detail-item"><strong>Ausgabe:</strong> ${escapeHtml(metadata.outputSummary)}</div>`);
 | 
					      details.push(`<div class="detail-item"><strong>Ausgabe:</strong> ${escapeHtml(metadata.outputSummary)}</div>`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Show meaningful reasoning (backend now avoids generic "completed with X%" messages)
 | 
					 | 
				
			||||||
    if (metadata.reasoning && !metadata.reasoning.includes('completed with')) {
 | 
					    if (metadata.reasoning && !metadata.reasoning.includes('completed with')) {
 | 
				
			||||||
      details.push(`<div class="detail-item"><strong>Begründung:</strong> ${escapeHtml(metadata.reasoning)}</div>`);
 | 
					      details.push(`<div class="detail-item"><strong>Begründung:</strong> ${escapeHtml(metadata.reasoning)}</div>`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Action-specific additional details
 | 
					 | 
				
			||||||
    if (entry.action === 'similarity-search' && metadata.similarityScores) {
 | 
					    if (entry.action === 'similarity-search' && metadata.similarityScores) {
 | 
				
			||||||
      const topScores = Object.entries(metadata.similarityScores)
 | 
					      const topScores = Object.entries(metadata.similarityScores)
 | 
				
			||||||
        .sort(([,a], [,b]) => (b) - (a))
 | 
					        .sort(([,a], [,b]) => (b) - (a))
 | 
				
			||||||
@ -1597,11 +1591,9 @@ class AIQueryInterface {
 | 
				
			|||||||
      embeddingsSimilarities: {}
 | 
					      embeddingsSimilarities: {}
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Enhanced export structure with proper audit trail handling
 | 
					 | 
				
			||||||
    const exportData = {
 | 
					    const exportData = {
 | 
				
			||||||
      metadata: {
 | 
					      metadata: {
 | 
				
			||||||
        timestamp: new Date().toISOString(),
 | 
					        timestamp: new Date().toISOString(),
 | 
				
			||||||
        version: "1.1", // Increment version for improved structure
 | 
					 | 
				
			||||||
        toolsDataHash: toolsDataHash,
 | 
					        toolsDataHash: toolsDataHash,
 | 
				
			||||||
        aiModel: aiModel,
 | 
					        aiModel: aiModel,
 | 
				
			||||||
        aiParameters: aiParameters,
 | 
					        aiParameters: aiParameters,
 | 
				
			||||||
@ -1609,16 +1601,13 @@ class AIQueryInterface {
 | 
				
			|||||||
        mode: this.currentMode,
 | 
					        mode: this.currentMode,
 | 
				
			||||||
        processingStats: processingStats,
 | 
					        processingStats: processingStats,
 | 
				
			||||||
        exportedBy: 'ForensicPathways',
 | 
					        exportedBy: 'ForensicPathways',
 | 
				
			||||||
        auditTrailVersion: '1.1' // Track audit trail format version
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      recommendation: {
 | 
					      recommendation: {
 | 
				
			||||||
        // Export recommendation without auditTrail to avoid duplication
 | 
					 | 
				
			||||||
        ...this.currentRecommendation,
 | 
					        ...this.currentRecommendation,
 | 
				
			||||||
        auditTrail: undefined // Remove from recommendation as it's at top level
 | 
					        auditTrail: undefined
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      auditTrail: this.currentRecommendation.auditTrail || [], // Extract to top level
 | 
					      auditTrail: this.currentRecommendation.auditTrail || [],
 | 
				
			||||||
      rawContext: rawContext,
 | 
					      rawContext: rawContext,
 | 
				
			||||||
      // Add validation checksum for integrity
 | 
					 | 
				
			||||||
      checksum: this.calculateDataChecksum(this.currentRecommendation)
 | 
					      checksum: this.calculateDataChecksum(this.currentRecommendation)
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -1647,7 +1636,6 @@ class AIQueryInterface {
 | 
				
			|||||||
    if (!data) return 'empty';
 | 
					    if (!data) return 'empty';
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      // Simple checksum based on key data properties
 | 
					 | 
				
			||||||
      const keyData = {
 | 
					      const keyData = {
 | 
				
			||||||
        recommendedToolsCount: data.recommended_tools?.length || 0,
 | 
					        recommendedToolsCount: data.recommended_tools?.length || 0,
 | 
				
			||||||
        backgroundKnowledgeCount: data.background_knowledge?.length || 0,
 | 
					        backgroundKnowledgeCount: data.background_knowledge?.length || 0,
 | 
				
			||||||
@ -1661,7 +1649,7 @@ class AIQueryInterface {
 | 
				
			|||||||
      for (let i = 0; i < dataString.length; i++) {
 | 
					      for (let i = 0; i < dataString.length; i++) {
 | 
				
			||||||
        const char = dataString.charCodeAt(i);
 | 
					        const char = dataString.charCodeAt(i);
 | 
				
			||||||
        hash = ((hash << 5) - hash) + char;
 | 
					        hash = ((hash << 5) - hash) + char;
 | 
				
			||||||
        hash = hash & hash; // Convert to 32-bit integer
 | 
					        hash = hash & hash;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return Math.abs(hash).toString(36);
 | 
					      return Math.abs(hash).toString(36);
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
@ -1680,14 +1668,13 @@ class AIQueryInterface {
 | 
				
			|||||||
        typeof data.metadata.timestamp === 'string' &&
 | 
					        typeof data.metadata.timestamp === 'string' &&
 | 
				
			||||||
        data.recommendation &&
 | 
					        data.recommendation &&
 | 
				
			||||||
        typeof data.recommendation === 'object' &&
 | 
					        typeof data.recommendation === 'object' &&
 | 
				
			||||||
        Array.isArray(data.auditTrail) // Audit trail at top level
 | 
					        Array.isArray(data.auditTrail)
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (!isValid) {
 | 
					      if (!isValid) {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Enhanced validation for audit trail structure
 | 
					 | 
				
			||||||
      if (data.auditTrail.length > 0) {
 | 
					      if (data.auditTrail.length > 0) {
 | 
				
			||||||
        const sampleEntry = data.auditTrail[0];
 | 
					        const sampleEntry = data.auditTrail[0];
 | 
				
			||||||
        const hasRequiredFields = !!(
 | 
					        const hasRequiredFields = !!(
 | 
				
			||||||
@ -1718,10 +1705,9 @@ class AIQueryInterface {
 | 
				
			|||||||
      
 | 
					      
 | 
				
			||||||
      this.showUploadedBanner(data.metadata);
 | 
					      this.showUploadedBanner(data.metadata);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Fix: Ensure audit trail is available in recommendation for restoreAIResults
 | 
					 | 
				
			||||||
      this.currentRecommendation = {
 | 
					      this.currentRecommendation = {
 | 
				
			||||||
        ...data.recommendation,
 | 
					        ...data.recommendation,
 | 
				
			||||||
        auditTrail: data.auditTrail // Restore audit trail to recommendation object
 | 
					        auditTrail: data.auditTrail
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      this.showResults();
 | 
					      this.showResults();
 | 
				
			||||||
@ -1813,7 +1799,6 @@ class AIQueryInterface {
 | 
				
			|||||||
        throw new Error('Ungültiges Analyse-Dateiformat');
 | 
					        throw new Error('Ungültiges Analyse-Dateiformat');
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Store audit trail separately for restore function
 | 
					 | 
				
			||||||
      this.uploadedAuditTrail = data.auditTrail;
 | 
					      this.uploadedAuditTrail = data.auditTrail;
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      console.log('[AI Interface] Valid previous analysis file uploaded:', {
 | 
					      console.log('[AI Interface] Valid previous analysis file uploaded:', {
 | 
				
			||||||
@ -2282,7 +2267,6 @@ class AIQueryInterface {
 | 
				
			|||||||
    if (this.currentRecommendation && this.elements.results) {
 | 
					    if (this.currentRecommendation && this.elements.results) {
 | 
				
			||||||
      this.showResults();
 | 
					      this.showResults();
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Check both locations for audit trail for backward compatibility
 | 
					 | 
				
			||||||
      const auditTrail = this.currentRecommendation.auditTrail || this.uploadedAuditTrail;
 | 
					      const auditTrail = this.currentRecommendation.auditTrail || this.uploadedAuditTrail;
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (auditTrail && Array.isArray(auditTrail) && auditTrail.length > 0) {
 | 
					      if (auditTrail && Array.isArray(auditTrail) && auditTrail.length > 0) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
// src/components/ContributionButton.astro - CLEANED: Removed duplicate auth script
 | 
					// src/components/ContributionButton.astro
 | 
				
			||||||
export interface Props {
 | 
					export interface Props {
 | 
				
			||||||
  type: 'edit' | 'new' | 'write';
 | 
					  type: 'edit' | 'new' | 'write';
 | 
				
			||||||
  toolName?: string;
 | 
					  toolName?: string;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,6 @@ import { getToolsData } from '../utils/dataService.js';
 | 
				
			|||||||
const data = await getToolsData();
 | 
					const data = await getToolsData();
 | 
				
			||||||
const scenarios = data.scenarios || [];
 | 
					const scenarios = data.scenarios || [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Configuration
 | 
					 | 
				
			||||||
const maxDisplayed = 9;
 | 
					const maxDisplayed = 9;
 | 
				
			||||||
const displayedScenarios = scenarios.slice(0, maxDisplayed);
 | 
					const displayedScenarios = scenarios.slice(0, maxDisplayed);
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ const knowledgebaseCollection = defineCollection({
 | 
				
			|||||||
    tags: z.array(z.string()).default([]),
 | 
					    tags: z.array(z.string()).default([]),
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    published: z.boolean().default(true),
 | 
					    published: z.boolean().default(true),
 | 
				
			||||||
    gated_content: z.boolean().default(false), // NEW: Gated content flag
 | 
					    gated_content: z.boolean().default(false),
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
// src/pages/api/ai/embeddings-status.ts - Updated
 | 
					// src/pages/api/ai/embeddings-status.ts
 | 
				
			||||||
import type { APIRoute } from 'astro';
 | 
					import type { APIRoute } from 'astro';
 | 
				
			||||||
import { embeddingsService } from '../../../utils/embeddings.js';
 | 
					import { embeddingsService } from '../../../utils/embeddings.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
// src/pages/api/ai/enhance-input.ts - Updated to use refactored services
 | 
					// src/pages/api/ai/enhance-input.ts
 | 
				
			||||||
import type { APIRoute } from 'astro';
 | 
					import type { APIRoute } from 'astro';
 | 
				
			||||||
import { withAPIAuth } from '../../../utils/auth.js';
 | 
					import { withAPIAuth } from '../../../utils/auth.js';
 | 
				
			||||||
import { apiError, apiServerError, createAuthErrorResponse } from '../../../utils/api.js';
 | 
					import { apiError, apiServerError, createAuthErrorResponse } from '../../../utils/api.js';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
// src/pages/api/ai/query.ts - Updated to use refactored services
 | 
					// src/pages/api/ai/query.ts
 | 
				
			||||||
import type { APIRoute } from 'astro';
 | 
					import type { APIRoute } from 'astro';
 | 
				
			||||||
import { withAPIAuth } from '../../../utils/auth.js';
 | 
					import { withAPIAuth } from '../../../utils/auth.js';
 | 
				
			||||||
import { apiError, apiServerError, createAuthErrorResponse } from '../../../utils/api.js';
 | 
					import { apiError, apiServerError, createAuthErrorResponse } from '../../../utils/api.js';
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
---
 | 
					---
 | 
				
			||||||
// src/pages/contribute/index.astro - Consolidated Auth
 | 
					// src/pages/contribute/index.astro
 | 
				
			||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
 | 
					import BaseLayout from '../../layouts/BaseLayout.astro';
 | 
				
			||||||
import { withAuth } from '../../utils/auth.js'; 
 | 
					import { withAuth } from '../../utils/auth.js'; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
// src/utils/aiPipeline.ts - Fixed to remove hardcoded values and improve dynamics
 | 
					// src/utils/aiPipeline.ts
 | 
				
			||||||
import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
 | 
					import { getCompressedToolsDataForAI, getDataVersion } from './dataService.js';
 | 
				
			||||||
import { aiService } from './aiService.js';
 | 
					import { aiService } from './aiService.js';
 | 
				
			||||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
					import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
				
			||||||
@ -77,7 +77,6 @@ interface PipelineContext {
 | 
				
			|||||||
  }>;
 | 
					  }>;
 | 
				
			||||||
  seenToolNames: Set<string>;
 | 
					  seenToolNames: Set<string>;
 | 
				
			||||||
  embeddingsSimilarities: Map<string, number>;
 | 
					  embeddingsSimilarities: Map<string, number>;
 | 
				
			||||||
  // Add phase metadata for dynamic phase handling
 | 
					 | 
				
			||||||
  phaseMetadata?: {
 | 
					  phaseMetadata?: {
 | 
				
			||||||
    phases: any[];
 | 
					    phases: any[];
 | 
				
			||||||
    criticalPhaseIds: string[];
 | 
					    criticalPhaseIds: string[];
 | 
				
			||||||
@ -128,7 +127,6 @@ class AIPipeline {
 | 
				
			|||||||
        currentContextLength: 0,
 | 
					        currentContextLength: 0,
 | 
				
			||||||
        seenToolNames: new Set<string>(),
 | 
					        seenToolNames: new Set<string>(),
 | 
				
			||||||
        embeddingsSimilarities: new Map<string, number>(),
 | 
					        embeddingsSimilarities: new Map<string, number>(),
 | 
				
			||||||
        // Initialize phase metadata dynamically
 | 
					 | 
				
			||||||
        phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
 | 
					        phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -259,20 +257,17 @@ class AIPipeline {
 | 
				
			|||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Dynamically determine critical phases based on typical_tools or key_activities
 | 
					 | 
				
			||||||
    const criticalPhaseIds = phases
 | 
					    const criticalPhaseIds = phases
 | 
				
			||||||
      .filter(phase => {
 | 
					      .filter(phase => {
 | 
				
			||||||
        const typicalToolsCount = phase.typical_tools?.length || 0;
 | 
					        const typicalToolsCount = phase.typical_tools?.length || 0;
 | 
				
			||||||
        const keyActivitiesCount = phase.key_activities?.length || 0;
 | 
					        const keyActivitiesCount = phase.key_activities?.length || 0;
 | 
				
			||||||
        // Consider phases with many tools or activities as critical
 | 
					 | 
				
			||||||
        return typicalToolsCount >= 3 || keyActivitiesCount >= 2;
 | 
					        return typicalToolsCount >= 3 || keyActivitiesCount >= 2;
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
      .map(phase => phase.id);
 | 
					      .map(phase => phase.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Calculate phase complexity based on metadata
 | 
					 | 
				
			||||||
    const phaseComplexity = new Map<string, number>();
 | 
					    const phaseComplexity = new Map<string, number>();
 | 
				
			||||||
    phases.forEach(phase => {
 | 
					    phases.forEach(phase => {
 | 
				
			||||||
      let complexity = 1; // Base complexity
 | 
					      let complexity = 1;
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (phase.typical_tools?.length > 5) complexity += 1;
 | 
					      if (phase.typical_tools?.length > 5) complexity += 1;
 | 
				
			||||||
      if (phase.key_activities?.length > 3) complexity += 1;
 | 
					      if (phase.key_activities?.length > 3) complexity += 1;
 | 
				
			||||||
@ -389,7 +384,6 @@ class AIPipeline {
 | 
				
			|||||||
          const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
 | 
					          const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
 | 
				
			||||||
          const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
					          const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
          // Generate dynamic limitations based on context
 | 
					 | 
				
			||||||
          const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
 | 
					          const dynamicLimitations = this.generateDynamicLimitations(tool, phase, sel);
 | 
				
			||||||
          
 | 
					          
 | 
				
			||||||
          this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
 | 
					          this.addToolToSelection(context, tool, phase.id, priority, sel.justification, moderatedTaskRelevance, dynamicLimitations);
 | 
				
			||||||
@ -444,18 +438,15 @@ class AIPipeline {
 | 
				
			|||||||
  ): number {
 | 
					  ): number {
 | 
				
			||||||
    let confidence = 60;
 | 
					    let confidence = 60;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Use dynamic phase metadata instead of hardcoded values
 | 
					 | 
				
			||||||
    const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
 | 
					    const isCritical = phaseMetadata?.criticalPhaseIds.includes(phaseId) || false;
 | 
				
			||||||
    const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
 | 
					    const phaseComplexity = phaseMetadata?.phaseComplexity.get(phaseId) || 1;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Selection made
 | 
					 | 
				
			||||||
    if (selectedCount > 0) {
 | 
					    if (selectedCount > 0) {
 | 
				
			||||||
      confidence += 20;
 | 
					      confidence += 20;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      return 30;
 | 
					      return 30;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Selection ratio (for phases, 20-50% is reasonable)
 | 
					 | 
				
			||||||
    const ratio = selectedCount / availableCount;
 | 
					    const ratio = selectedCount / availableCount;
 | 
				
			||||||
    if (ratio >= 0.2 && ratio <= 0.5) {
 | 
					    if (ratio >= 0.2 && ratio <= 0.5) {
 | 
				
			||||||
      confidence += 15;
 | 
					      confidence += 15;
 | 
				
			||||||
@ -463,17 +454,14 @@ class AIPipeline {
 | 
				
			|||||||
      confidence += 10;
 | 
					      confidence += 10;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Dynamic critical phase handling
 | 
					 | 
				
			||||||
    if (isCritical && selectedCount >= 2) {
 | 
					    if (isCritical && selectedCount >= 2) {
 | 
				
			||||||
      confidence += 10;
 | 
					      confidence += 10;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Phase complexity factor
 | 
					 | 
				
			||||||
    if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
 | 
					    if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
 | 
				
			||||||
      confidence += 5;
 | 
					      confidence += 5;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Quality of selections (based on task relevance)
 | 
					 | 
				
			||||||
    const avgRelevance = selections.length > 0 ? 
 | 
					    const avgRelevance = selections.length > 0 ? 
 | 
				
			||||||
      selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
 | 
					      selections.reduce((sum, s) => sum + (s.taskRelevance || 70), 0) / selections.length : 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -489,12 +477,10 @@ class AIPipeline {
 | 
				
			|||||||
  private generateDynamicLimitations(tool: any, phase: any, selection: any): string[] {
 | 
					  private generateDynamicLimitations(tool: any, phase: any, selection: any): string[] {
 | 
				
			||||||
    const limitations: string[] = [];
 | 
					    const limitations: string[] = [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Add existing limitations if provided
 | 
					 | 
				
			||||||
    if (selection.limitations && Array.isArray(selection.limitations)) {
 | 
					    if (selection.limitations && Array.isArray(selection.limitations)) {
 | 
				
			||||||
      limitations.push(...selection.limitations);
 | 
					      limitations.push(...selection.limitations);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Generate context-aware limitations
 | 
					 | 
				
			||||||
    if (tool.type === 'software' && !tool.projectUrl) {
 | 
					    if (tool.type === 'software' && !tool.projectUrl) {
 | 
				
			||||||
      limitations.push('Installation und Konfiguration erforderlich');
 | 
					      limitations.push('Installation und Konfiguration erforderlich');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -507,12 +493,11 @@ class AIPipeline {
 | 
				
			|||||||
      limitations.push('Kommerzielle Lizenz erforderlich');
 | 
					      limitations.push('Kommerzielle Lizenz erforderlich');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Phase-specific limitations
 | 
					 | 
				
			||||||
    if (phase.id === 'acquisition' && tool.type === 'method') {
 | 
					    if (phase.id === 'acquisition' && tool.type === 'method') {
 | 
				
			||||||
      limitations.push('Sorgfältige Dokumentation für Chain of Custody erforderlich');
 | 
					      limitations.push('Sorgfältige Dokumentation für Chain of Custody erforderlich');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return limitations.slice(0, 3); // Limit to 3 most relevant
 | 
					    return limitations.slice(0, 3);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async processToolMode(
 | 
					  private async processToolMode(
 | 
				
			||||||
@ -699,7 +684,6 @@ class AIPipeline {
 | 
				
			|||||||
          moderatedTaskRelevance = this.moderateTaskRelevance(75);
 | 
					          moderatedTaskRelevance = this.moderateTaskRelevance(75);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        // Generate dynamic limitations instead of hardcoded ones
 | 
					 | 
				
			||||||
        const dynamicLimitations = this.generateCompletionLimitations(tool, phase, selection);
 | 
					        const dynamicLimitations = this.generateCompletionLimitations(tool, phase, selection);
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        this.addToolToSelection(
 | 
					        this.addToolToSelection(
 | 
				
			||||||
@ -754,10 +738,8 @@ class AIPipeline {
 | 
				
			|||||||
  private generateCompletionLimitations(tool: any, phase: any, selection: any): string[] {
 | 
					  private generateCompletionLimitations(tool: any, phase: any, selection: any): string[] {
 | 
				
			||||||
    const limitations: string[] = [];
 | 
					    const limitations: string[] = [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Context-specific limitation for completion tools
 | 
					 | 
				
			||||||
    limitations.push('Nachträgliche Ergänzung - ursprünglich nicht als Hauptmethode identifiziert');
 | 
					    limitations.push('Nachträgliche Ergänzung - ursprünglich nicht als Hauptmethode identifiziert');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Tool-specific limitations
 | 
					 | 
				
			||||||
    if (tool.skillLevel === 'expert') {
 | 
					    if (tool.skillLevel === 'expert') {
 | 
				
			||||||
      limitations.push('Erfordert Expertenwissen für optimale Nutzung');
 | 
					      limitations.push('Erfordert Expertenwissen für optimale Nutzung');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -766,7 +748,6 @@ class AIPipeline {
 | 
				
			|||||||
      limitations.push('Zusätzliche Setup-Zeit erforderlich');
 | 
					      limitations.push('Zusätzliche Setup-Zeit erforderlich');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Phase-specific context
 | 
					 | 
				
			||||||
    if (phase.typical_tools && !phase.typical_tools.includes(tool.name)) {
 | 
					    if (phase.typical_tools && !phase.typical_tools.includes(tool.name)) {
 | 
				
			||||||
      limitations.push(`Nicht typisch für ${phase.name}-Phase - alternative Anwendung`);
 | 
					      limitations.push(`Nicht typisch für ${phase.name}-Phase - alternative Anwendung`);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
// src/utils/auditService.ts - Fixed with meaningful confidence and reasoning
 | 
					// src/utils/auditService.ts
 | 
				
			||||||
import 'dotenv/config';
 | 
					import 'dotenv/config';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function env(key: string, fallback: string | undefined = undefined): string | undefined {
 | 
					function env(key: string, fallback: string | undefined = undefined): string | undefined {
 | 
				
			||||||
@ -85,7 +85,6 @@ class AuditService {
 | 
				
			|||||||
  ): void {
 | 
					  ): void {
 | 
				
			||||||
    if (!this.config.enabled) return;
 | 
					    if (!this.config.enabled) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Skip initialization and completion entries as they don't add transparency
 | 
					 | 
				
			||||||
    if (action === 'pipeline-start' || action === 'pipeline-end') {
 | 
					    if (action === 'pipeline-start' || action === 'pipeline-end') {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -152,7 +151,6 @@ class AuditService {
 | 
				
			|||||||
    startTime: number,
 | 
					    startTime: number,
 | 
				
			||||||
    metadata: Record<string, any> = {}
 | 
					    metadata: Record<string, any> = {}
 | 
				
			||||||
  ): void {
 | 
					  ): void {
 | 
				
			||||||
    // Calculate meaningful confidence based on selection quality
 | 
					 | 
				
			||||||
    const calculatedConfidence = this.calculateSelectionConfidence(
 | 
					    const calculatedConfidence = this.calculateSelectionConfidence(
 | 
				
			||||||
      selectedTools, 
 | 
					      selectedTools, 
 | 
				
			||||||
      availableTools, 
 | 
					      availableTools, 
 | 
				
			||||||
@ -164,7 +162,7 @@ class AuditService {
 | 
				
			|||||||
      'tool-selection',
 | 
					      'tool-selection',
 | 
				
			||||||
      'selection-decision',
 | 
					      'selection-decision',
 | 
				
			||||||
      { 
 | 
					      { 
 | 
				
			||||||
        availableTools: availableTools.slice(0, 10), // Show first 10 for context
 | 
					        availableTools: availableTools.slice(0, 10),
 | 
				
			||||||
        totalAvailable: availableTools.length,
 | 
					        totalAvailable: availableTools.length,
 | 
				
			||||||
        selectionMethod: selectionMethod
 | 
					        selectionMethod: selectionMethod
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
@ -191,7 +189,6 @@ class AuditService {
 | 
				
			|||||||
    startTime: number,
 | 
					    startTime: number,
 | 
				
			||||||
    metadata: Record<string, any> = {}
 | 
					    metadata: Record<string, any> = {}
 | 
				
			||||||
  ): void {
 | 
					  ): void {
 | 
				
			||||||
    // Only add if tools were actually added
 | 
					 | 
				
			||||||
    if (!addedTools || addedTools.length === 0) {
 | 
					    if (!addedTools || addedTools.length === 0) {
 | 
				
			||||||
      console.log(`[AUDIT-SERVICE] Skipping phase completion for ${phaseId} - no tools added`);
 | 
					      console.log(`[AUDIT-SERVICE] Skipping phase completion for ${phaseId} - no tools added`);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
@ -292,21 +289,18 @@ class AuditService {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    const selectionRatio = selectedTools.length / availableTools.length;
 | 
					    const selectionRatio = selectedTools.length / availableTools.length;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Good selection ratio (5-20% of available tools)
 | 
					 | 
				
			||||||
    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
					    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
				
			||||||
      confidence += 25;
 | 
					      confidence += 25;
 | 
				
			||||||
    } else if (selectionRatio < 0.05) {
 | 
					    } else if (selectionRatio < 0.05) {
 | 
				
			||||||
      confidence += 15; // Very selective is good
 | 
					      confidence += 15;
 | 
				
			||||||
    } else if (selectionRatio > 0.30) {
 | 
					    } else if (selectionRatio > 0.30) {
 | 
				
			||||||
      confidence -= 20; // Too many tools selected
 | 
					      confidence -= 20;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Embeddings usage bonus
 | 
					 | 
				
			||||||
    if (selectionMethod.includes('embeddings')) {
 | 
					    if (selectionMethod.includes('embeddings')) {
 | 
				
			||||||
      confidence += 15;
 | 
					      confidence += 15;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Reasonable number of tools selected
 | 
					 | 
				
			||||||
    if (selectedTools.length >= 5 && selectedTools.length <= 25) {
 | 
					    if (selectedTools.length >= 5 && selectedTools.length <= 25) {
 | 
				
			||||||
      confidence += 10;
 | 
					      confidence += 10;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -321,22 +315,18 @@ class AuditService {
 | 
				
			|||||||
  ): number {
 | 
					  ): number {
 | 
				
			||||||
    let confidence = 60;
 | 
					    let confidence = 60;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Tools actually added
 | 
					 | 
				
			||||||
    if (addedTools.length > 0) {
 | 
					    if (addedTools.length > 0) {
 | 
				
			||||||
      confidence += 20;
 | 
					      confidence += 20;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Good reasoning provided
 | 
					 | 
				
			||||||
    if (reasoning && reasoning.length > 50) {
 | 
					    if (reasoning && reasoning.length > 50) {
 | 
				
			||||||
      confidence += 15;
 | 
					      confidence += 15;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // AI reasoning was used successfully
 | 
					 | 
				
			||||||
    if (metadata.aiReasoningUsed) {
 | 
					    if (metadata.aiReasoningUsed) {
 | 
				
			||||||
      confidence += 10;
 | 
					      confidence += 10;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Not too many tools added (indicates thoughtful selection)
 | 
					 | 
				
			||||||
    if (addedTools.length <= 2) {
 | 
					    if (addedTools.length <= 2) {
 | 
				
			||||||
      confidence += 5;
 | 
					      confidence += 5;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -347,17 +337,14 @@ class AuditService {
 | 
				
			|||||||
  private calculateEmbeddingsConfidence(similarResults: any[], threshold: number): number {
 | 
					  private calculateEmbeddingsConfidence(similarResults: any[], threshold: number): number {
 | 
				
			||||||
    let confidence = 50;
 | 
					    let confidence = 50;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Found relevant results
 | 
					 | 
				
			||||||
    if (similarResults.length > 0) {
 | 
					    if (similarResults.length > 0) {
 | 
				
			||||||
      confidence += 20;
 | 
					      confidence += 20;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Good number of results (not too few, not too many)
 | 
					 | 
				
			||||||
    if (similarResults.length >= 5 && similarResults.length <= 30) {
 | 
					    if (similarResults.length >= 5 && similarResults.length <= 30) {
 | 
				
			||||||
      confidence += 15;
 | 
					      confidence += 15;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // High similarity scores
 | 
					 | 
				
			||||||
    const avgSimilarity = similarResults.length > 0 ? 
 | 
					    const avgSimilarity = similarResults.length > 0 ? 
 | 
				
			||||||
      similarResults.reduce((sum, r) => sum + r.similarity, 0) / similarResults.length : 0;
 | 
					      similarResults.reduce((sum, r) => sum + r.similarity, 0) / similarResults.length : 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -367,7 +354,6 @@ class AuditService {
 | 
				
			|||||||
      confidence += 10;
 | 
					      confidence += 10;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Reasonable threshold
 | 
					 | 
				
			||||||
    if (threshold >= 0.3 && threshold <= 0.5) {
 | 
					    if (threshold >= 0.3 && threshold <= 0.5) {
 | 
				
			||||||
      confidence += 5;
 | 
					      confidence += 5;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -378,7 +364,6 @@ class AuditService {
 | 
				
			|||||||
  private createSpecificSummary(data: any, action: string, type: 'input' | 'output'): string {
 | 
					  private createSpecificSummary(data: any, action: string, type: 'input' | 'output'): string {
 | 
				
			||||||
    if (!data) return 'Leer';
 | 
					    if (!data) return 'Leer';
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Action-specific summaries that show actual meaningful data
 | 
					 | 
				
			||||||
    switch (action) {
 | 
					    switch (action) {
 | 
				
			||||||
      case 'selection-decision':
 | 
					      case 'selection-decision':
 | 
				
			||||||
        if (type === 'input') {
 | 
					        if (type === 'input') {
 | 
				
			||||||
@ -476,7 +461,6 @@ class AuditService {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Enhanced fallback that shows actual key-value content instead of just "X Eigenschaften"
 | 
					 | 
				
			||||||
    if (typeof data === 'string') {
 | 
					    if (typeof data === 'string') {
 | 
				
			||||||
      return data.length > 100 ? data.slice(0, 100) + '...' : data;
 | 
					      return data.length > 100 ? data.slice(0, 100) + '...' : data;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -491,7 +475,6 @@ class AuditService {
 | 
				
			|||||||
      const keys = Object.keys(data);
 | 
					      const keys = Object.keys(data);
 | 
				
			||||||
      if (keys.length === 0) return 'Leeres Objekt';
 | 
					      if (keys.length === 0) return 'Leeres Objekt';
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      // Show actual key-value pairs for small objects instead of just counting properties
 | 
					 | 
				
			||||||
      if (keys.length <= 2) {
 | 
					      if (keys.length <= 2) {
 | 
				
			||||||
        const pairs = keys.map(key => {
 | 
					        const pairs = keys.map(key => {
 | 
				
			||||||
          const value = data[key];
 | 
					          const value = data[key];
 | 
				
			||||||
@ -505,7 +488,6 @@ class AuditService {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
        return pairs.join(', ');
 | 
					        return pairs.join(', ');
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        // For larger objects, show key names and some sample values
 | 
					 | 
				
			||||||
        const sampleKeys = keys.slice(0, 3);
 | 
					        const sampleKeys = keys.slice(0, 3);
 | 
				
			||||||
        const sampleValues = sampleKeys.map(key => {
 | 
					        const sampleValues = sampleKeys.map(key => {
 | 
				
			||||||
          const value = data[key];
 | 
					          const value = data[key];
 | 
				
			||||||
@ -531,7 +513,6 @@ class AuditService {
 | 
				
			|||||||
    metadata: Record<string, any>, 
 | 
					    metadata: Record<string, any>, 
 | 
				
			||||||
    confidence: number
 | 
					    confidence: number
 | 
				
			||||||
  ): string {
 | 
					  ): string {
 | 
				
			||||||
    // Use provided reasoning if available and meaningful
 | 
					 | 
				
			||||||
    if (metadata.reasoning && metadata.reasoning.length > 20 && !metadata.reasoning.includes('completed with')) {
 | 
					    if (metadata.reasoning && metadata.reasoning.length > 20 && !metadata.reasoning.includes('completed with')) {
 | 
				
			||||||
      return metadata.reasoning;
 | 
					      return metadata.reasoning;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -546,11 +527,9 @@ class AuditService {
 | 
				
			|||||||
        const totalMatches =
 | 
					        const totalMatches =
 | 
				
			||||||
          typeof metadata.totalMatches === 'number' ? metadata.totalMatches : 0;
 | 
					          typeof metadata.totalMatches === 'number' ? metadata.totalMatches : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Safely narrow & cast similarityScores to a number map
 | 
					 | 
				
			||||||
        const scoresObj = (metadata.similarityScores ?? {}) as Record<string, number>;
 | 
					        const scoresObj = (metadata.similarityScores ?? {}) as Record<string, number>;
 | 
				
			||||||
        const scores = Object.values(scoresObj) as number[];
 | 
					        const scores = Object.values(scoresObj) as number[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Use totalMatches if it looks sensible; otherwise fall back to scores.length
 | 
					 | 
				
			||||||
        const denom = totalMatches > 0 ? totalMatches : scores.length;
 | 
					        const denom = totalMatches > 0 ? totalMatches : scores.length;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const sum = scores.reduce((acc, v) => acc + (typeof v === 'number' ? v : 0), 0);
 | 
					        const sum = scores.reduce((acc, v) => acc + (typeof v === 'number' ? v : 0), 0);
 | 
				
			||||||
@ -697,9 +676,7 @@ class AuditService {
 | 
				
			|||||||
    return Math.min(95, Math.max(25, confidence));
 | 
					    return Math.min(95, Math.max(25, confidence));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // Additional utility methods remain the same...
 | 
					 | 
				
			||||||
  getAuditStatistics(auditTrail: AuditEntry[]): any {
 | 
					  getAuditStatistics(auditTrail: AuditEntry[]): any {
 | 
				
			||||||
    // Implementation remains the same as before
 | 
					 | 
				
			||||||
    if (!auditTrail || auditTrail.length === 0) {
 | 
					    if (!auditTrail || auditTrail.length === 0) {
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        totalTime: 0,
 | 
					        totalTime: 0,
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user