fulldata
This commit is contained in:
		
							parent
							
								
									2cb25d1dd6
								
							
						
					
					
						commit
						70fb012d63
					
				@ -1594,6 +1594,7 @@ class AIQueryInterface {
 | 
				
			|||||||
    const exportData = {
 | 
					    const exportData = {
 | 
				
			||||||
      metadata: {
 | 
					      metadata: {
 | 
				
			||||||
        timestamp: new Date().toISOString(),
 | 
					        timestamp: new Date().toISOString(),
 | 
				
			||||||
 | 
					        version: '2.0',
 | 
				
			||||||
        toolsDataHash: toolsDataHash,
 | 
					        toolsDataHash: toolsDataHash,
 | 
				
			||||||
        aiModel: aiModel,
 | 
					        aiModel: aiModel,
 | 
				
			||||||
        aiParameters: aiParameters,
 | 
					        aiParameters: aiParameters,
 | 
				
			||||||
@ -1607,8 +1608,7 @@ class AIQueryInterface {
 | 
				
			|||||||
        auditTrail: undefined
 | 
					        auditTrail: undefined
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      auditTrail: this.currentRecommendation.auditTrail || [],
 | 
					      auditTrail: this.currentRecommendation.auditTrail || [],
 | 
				
			||||||
      rawContext: rawContext,
 | 
					      rawContext: rawContext
 | 
				
			||||||
      checksum: this.calculateDataChecksum(this.currentRecommendation)
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const blob = new Blob([JSON.stringify(exportData, null, 2)], {
 | 
					    const blob = new Blob([JSON.stringify(exportData, null, 2)], {
 | 
				
			||||||
@ -1622,42 +1622,16 @@ class AIQueryInterface {
 | 
				
			|||||||
    a.click();
 | 
					    a.click();
 | 
				
			||||||
    URL.revokeObjectURL(url);
 | 
					    URL.revokeObjectURL(url);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    console.log('[AI Interface] Analysis downloaded with enhanced structure:', {
 | 
					    console.log('[AI Interface] Analysis downloaded with verified hash structure:', {
 | 
				
			||||||
      version: '1.1',
 | 
					      version: '2.0',
 | 
				
			||||||
      aiModel,
 | 
					      aiModel,
 | 
				
			||||||
      toolsDataHash: toolsDataHash.slice(0, 8) + '...',
 | 
					      toolsDataHash: toolsDataHash.slice(0, 12) + '...',
 | 
				
			||||||
      tokensUsed: aiParameters.totalTokensUsed,
 | 
					      tokensUsed: aiParameters.totalTokensUsed,
 | 
				
			||||||
      auditEntries: exportData.auditTrail.length,
 | 
					      auditEntries: exportData.auditTrail.length,
 | 
				
			||||||
      checksum: exportData.checksum.slice(0, 8) + '...'
 | 
					      hashVerifiable: toolsDataHash !== 'unknown'
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  calculateDataChecksum(data) {
 | 
					 | 
				
			||||||
    if (!data) return 'empty';
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    try {
 | 
					 | 
				
			||||||
      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;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      return Math.abs(hash).toString(36);
 | 
					 | 
				
			||||||
    } catch (error) {
 | 
					 | 
				
			||||||
      console.error('[AI Interface] Checksum calculation failed:', error);
 | 
					 | 
				
			||||||
      return 'error';
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  validateUploadStructure(data) {
 | 
					  validateUploadStructure(data) {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const isValid = !!(
 | 
					      const isValid = !!(
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,12 @@ import { aiService } from './aiService.js';
 | 
				
			|||||||
import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
					import { toolSelector, type SelectionContext } from './toolSelector.js';
 | 
				
			||||||
import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
 | 
					import { confidenceScoring, type AnalysisContext } from './confidenceScoring.js';
 | 
				
			||||||
import { embeddingsService } from './embeddings.js';
 | 
					import { embeddingsService } from './embeddings.js';
 | 
				
			||||||
import { auditService, type AuditEntry } from './auditService.js';
 | 
					import { auditService } from './auditService.js';
 | 
				
			||||||
import { JSONParser } from './jsonUtils.js';
 | 
					import { JSONParser } from './jsonUtils.js';
 | 
				
			||||||
import { getPrompt } from '../config/prompts.js';
 | 
					import { getPrompt } from '../config/prompts.js';
 | 
				
			||||||
import 'dotenv/config';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface PipelineConfig {
 | 
					interface PipelineConfig {
 | 
				
			||||||
  microTaskDelay: number;
 | 
					  microTaskDelay: number;
 | 
				
			||||||
  //maxContextTokens: number;
 | 
					 | 
				
			||||||
  maxPromptTokens: number;
 | 
					 | 
				
			||||||
  taskRelevanceModeration: {
 | 
					  taskRelevanceModeration: {
 | 
				
			||||||
    maxInitialScore: number;
 | 
					    maxInitialScore: number;
 | 
				
			||||||
    maxWithPhaseBonus: number;
 | 
					    maxWithPhaseBonus: number;
 | 
				
			||||||
@ -36,7 +33,6 @@ interface MicroTaskResult {
 | 
				
			|||||||
interface AnalysisResult {
 | 
					interface AnalysisResult {
 | 
				
			||||||
  recommendation: any;
 | 
					  recommendation: any;
 | 
				
			||||||
  processingStats: {
 | 
					  processingStats: {
 | 
				
			||||||
    //embeddingsUsed: boolean;
 | 
					 | 
				
			||||||
    candidatesFromEmbeddings: number;
 | 
					    candidatesFromEmbeddings: number;
 | 
				
			||||||
    finalSelectedItems: number;
 | 
					    finalSelectedItems: number;
 | 
				
			||||||
    processingTimeMs: number;
 | 
					    processingTimeMs: number;
 | 
				
			||||||
@ -57,7 +53,6 @@ interface PipelineContext {
 | 
				
			|||||||
  mode: string;
 | 
					  mode: string;
 | 
				
			||||||
  filteredData: any;
 | 
					  filteredData: any;
 | 
				
			||||||
  contextHistory: string[];
 | 
					  contextHistory: string[];
 | 
				
			||||||
  //maxContextLength: number;
 | 
					 | 
				
			||||||
  currentContextLength: number;
 | 
					  currentContextLength: number;
 | 
				
			||||||
  scenarioAnalysis?: string;
 | 
					  scenarioAnalysis?: string;
 | 
				
			||||||
  problemAnalysis?: string;
 | 
					  problemAnalysis?: string;
 | 
				
			||||||
@ -91,16 +86,12 @@ class AIPipeline {
 | 
				
			|||||||
  constructor() {
 | 
					  constructor() {
 | 
				
			||||||
    this.config = {
 | 
					    this.config = {
 | 
				
			||||||
      microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
 | 
					      microTaskDelay: parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10),
 | 
				
			||||||
      //maxContextTokens: parseInt(process.env.AI_MAX_CONTEXT_TOKENS || '4000', 10),
 | 
					 | 
				
			||||||
      maxPromptTokens: parseInt(process.env.AI_MAX_PROMPT_TOKENS || '1500', 10),
 | 
					 | 
				
			||||||
      taskRelevanceModeration: {
 | 
					      taskRelevanceModeration: {
 | 
				
			||||||
        maxInitialScore: 85,
 | 
					        maxInitialScore: 85,
 | 
				
			||||||
        maxWithPhaseBonus: 95,
 | 
					        maxWithPhaseBonus: 95,
 | 
				
			||||||
        moderationThreshold: 80
 | 
					        moderationThreshold: 80
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log('[AI-PIPELINE] Initialized with dynamic phase handling');
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
 | 
					  async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
 | 
				
			||||||
@ -109,8 +100,6 @@ class AIPipeline {
 | 
				
			|||||||
    let failedTasks = 0;
 | 
					    let failedTasks = 0;
 | 
				
			||||||
    this.totalTokensUsed = 0;
 | 
					    this.totalTokensUsed = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log('[AI-PIPELINE] Starting', mode, 'analysis pipeline');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    auditService.clearAuditTrail();
 | 
					    auditService.clearAuditTrail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@ -118,90 +107,102 @@ class AIPipeline {
 | 
				
			|||||||
      const aiConfig = aiService.getConfig();
 | 
					      const aiConfig = aiService.getConfig();
 | 
				
			||||||
      const toolsDataHash = getDataVersion?.() || 'unknown';
 | 
					      const toolsDataHash = getDataVersion?.() || 'unknown';
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
 | 
					      // Record the tools.yaml version being used
 | 
				
			||||||
 | 
					      auditService.addEntry(
 | 
				
			||||||
 | 
					        'initialization',
 | 
				
			||||||
 | 
					        'tools-data-loaded',
 | 
				
			||||||
 | 
					        { 
 | 
				
			||||||
 | 
					          toolsFile: 'tools.yaml',
 | 
				
			||||||
 | 
					          hashAlgorithm: 'SHA256'
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        { 
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
 | 
					          toolsCount: toolsData.tools.length,
 | 
				
			||||||
 | 
					          conceptsCount: toolsData.concepts.length,
 | 
				
			||||||
 | 
					          domainsCount: toolsData.domains.length,
 | 
				
			||||||
 | 
					          phasesCount: toolsData.phases.length
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        100,
 | 
				
			||||||
 | 
					        Date.now(),
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
 | 
					          verification: `Users can verify with: sha256sum src/data/tools.yaml`,
 | 
				
			||||||
 | 
					          dataVersion: toolsDataHash.slice(0, 12),
 | 
				
			||||||
 | 
					          reasoning: `Geladen: ${toolsData.tools.length} Tools, ${toolsData.concepts.length} Konzepte aus tools.yaml (Hash: ${toolsDataHash.slice(0, 12)}...)`
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      );
 | 
				
			||||||
 | 
					      
 | 
				
			||||||
      const context: PipelineContext = {
 | 
					      const context: PipelineContext = {
 | 
				
			||||||
        userQuery,
 | 
					        userQuery,
 | 
				
			||||||
        mode,
 | 
					        mode,
 | 
				
			||||||
        filteredData: {},
 | 
					        filteredData: {},
 | 
				
			||||||
        contextHistory: [],
 | 
					        contextHistory: [],
 | 
				
			||||||
        //maxContextLength: this.config.maxContextTokens,
 | 
					 | 
				
			||||||
        currentContextLength: 0,
 | 
					        currentContextLength: 0,
 | 
				
			||||||
        seenToolNames: new Set<string>(),
 | 
					        seenToolNames: new Set<string>(),
 | 
				
			||||||
        embeddingsSimilarities: new Map<string, number>(),
 | 
					        embeddingsSimilarities: new Map<string, number>(),
 | 
				
			||||||
        phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
 | 
					        phaseMetadata: this.initializePhaseMetadata(toolsData.phases)
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 1: Tool candidate selection');
 | 
					 | 
				
			||||||
      const candidateSelectionStart = Date.now();
 | 
					      const candidateSelectionStart = Date.now();
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
 | 
					      const candidateData = await toolSelector.getIntelligentCandidates(userQuery, toolsData, mode, context);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      const selectionConfidence = this.calculateToolSelectionConfidence(
 | 
					      const selectionConfidence = this.calculateToolSelectionConfidence(
 | 
				
			||||||
        candidateData.tools.length,
 | 
					        candidateData.tools.length,
 | 
				
			||||||
        toolsData.tools.length,
 | 
					        toolsData.tools.length,
 | 
				
			||||||
        //candidateData.selectionMethod,
 | 
					 | 
				
			||||||
        candidateData.concepts.length
 | 
					        candidateData.concepts.length
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      auditService.addToolSelection(
 | 
					      auditService.addToolSelection(
 | 
				
			||||||
        candidateData.tools.map(t => t.name),
 | 
					        candidateData.tools.map(t => t.name),
 | 
				
			||||||
        toolsData.tools.map(t => t.name),
 | 
					        toolsData.tools.map(t => t.name),
 | 
				
			||||||
        //candidateData.selectionMethod,
 | 
					 | 
				
			||||||
        selectionConfidence,
 | 
					        selectionConfidence,
 | 
				
			||||||
        candidateSelectionStart,
 | 
					        candidateSelectionStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          //embeddingsUsed: embeddingsService.isEnabled(),
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          totalCandidatesFound: candidateData.tools.length + candidateData.concepts.length,
 | 
					          totalCandidatesFound: candidateData.tools.length + candidateData.concepts.length,
 | 
				
			||||||
          //selectionMethod: candidateData.selectionMethod,
 | 
					 | 
				
			||||||
          reductionRatio: candidateData.tools.length / toolsData.tools.length
 | 
					          reductionRatio: candidateData.tools.length / toolsData.tools.length
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      context.filteredData = candidateData;
 | 
					      context.filteredData = candidateData;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 2: Contextual analysis');
 | 
					      const analysisResult = await this.analyzeScenario(context, startTime, toolsDataHash);
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      const analysisResult = await this.analyzeScenario(context, startTime);
 | 
					 | 
				
			||||||
      if (analysisResult.success) completedTasks++; else failedTasks++;
 | 
					      if (analysisResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(analysisResult.aiUsage);
 | 
					      this.trackTokenUsage(analysisResult.aiUsage);
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const approachResult = await this.generateApproach(context, startTime);
 | 
					      const approachResult = await this.generateApproach(context, startTime, toolsDataHash);
 | 
				
			||||||
      if (approachResult.success) completedTasks++; else failedTasks++;
 | 
					      if (approachResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(approachResult.aiUsage);
 | 
					      this.trackTokenUsage(approachResult.aiUsage);
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const considerationsResult = await this.generateCriticalConsiderations(context, startTime);
 | 
					      const considerationsResult = await this.generateCriticalConsiderations(context, startTime, toolsDataHash);
 | 
				
			||||||
      if (considerationsResult.success) completedTasks++; else failedTasks++;
 | 
					      if (considerationsResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(considerationsResult.aiUsage);
 | 
					      this.trackTokenUsage(considerationsResult.aiUsage);
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 3: Tool-specific analysis');
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      if (mode === 'workflow') {
 | 
					      if (mode === 'workflow') {
 | 
				
			||||||
        const workflowResults = await this.processWorkflowMode(context, toolsData, completedTasks, failedTasks, startTime);
 | 
					        const workflowResults = await this.processWorkflowMode(context, toolsData, completedTasks, failedTasks, startTime, toolsDataHash);
 | 
				
			||||||
        completedTasks = workflowResults.completed;
 | 
					        completedTasks = workflowResults.completed;
 | 
				
			||||||
        failedTasks = workflowResults.failed;
 | 
					        failedTasks = workflowResults.failed;
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        const toolResults = await this.processToolMode(context, completedTasks, failedTasks, startTime);
 | 
					        const toolResults = await this.processToolMode(context, completedTasks, failedTasks, startTime, toolsDataHash);
 | 
				
			||||||
        completedTasks = toolResults.completed;
 | 
					        completedTasks = toolResults.completed;
 | 
				
			||||||
        failedTasks = toolResults.failed;
 | 
					        failedTasks = toolResults.failed;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('[AI-PIPELINE] Phase 4: Knowledge synthesis');
 | 
					      const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime, toolsDataHash);
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      const knowledgeResult = await this.selectBackgroundKnowledge(context, startTime);
 | 
					 | 
				
			||||||
      if (knowledgeResult.success) completedTasks++; else failedTasks++;
 | 
					      if (knowledgeResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(knowledgeResult.aiUsage);
 | 
					      this.trackTokenUsage(knowledgeResult.aiUsage);
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const finalResult = await this.generateFinalRecommendations(context, startTime);
 | 
					      const finalResult = await this.generateFinalRecommendations(context, startTime, toolsDataHash);
 | 
				
			||||||
      if (finalResult.success) completedTasks++; else failedTasks++;
 | 
					      if (finalResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(finalResult.aiUsage);
 | 
					      this.trackTokenUsage(finalResult.aiUsage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const recommendation = this.buildRecommendation(context, mode, finalResult.content);
 | 
					      const recommendation = this.buildRecommendation(context, mode, finalResult.content, toolsDataHash);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const processingStats = {
 | 
					      const processingStats = {
 | 
				
			||||||
        //embeddingsUsed: embeddingsService.isEnabled(),
 | 
					 | 
				
			||||||
        candidatesFromEmbeddings: candidateData.tools.length,
 | 
					        candidatesFromEmbeddings: candidateData.tools.length,
 | 
				
			||||||
        finalSelectedItems: (context.selectedTools?.length || 0) + (context.backgroundKnowledge?.length || 0),
 | 
					        finalSelectedItems: (context.selectedTools?.length || 0) + (context.backgroundKnowledge?.length || 0),
 | 
				
			||||||
        processingTimeMs: Date.now() - startTime,
 | 
					        processingTimeMs: Date.now() - startTime,
 | 
				
			||||||
@ -216,16 +217,6 @@ class AIPipeline {
 | 
				
			|||||||
        maxTokensUsed: 32768
 | 
					        maxTokensUsed: 32768
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      console.log('[AI-PIPELINE] Pipeline completed successfully:', {
 | 
					 | 
				
			||||||
        mode,
 | 
					 | 
				
			||||||
        processingTimeMs: processingStats.processingTimeMs,
 | 
					 | 
				
			||||||
        completedTasks,
 | 
					 | 
				
			||||||
        failedTasks,
 | 
					 | 
				
			||||||
        finalItems: processingStats.finalSelectedItems,
 | 
					 | 
				
			||||||
        totalTokensUsed: this.totalTokensUsed,
 | 
					 | 
				
			||||||
        auditEntries: processingStats.auditEntriesGenerated
 | 
					 | 
				
			||||||
      });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
      const finalAuditTrail = auditService.finalizeAuditTrail();
 | 
					      const finalAuditTrail = auditService.finalizeAuditTrail();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
@ -249,7 +240,6 @@ class AIPipeline {
 | 
				
			|||||||
    phaseComplexity: Map<string, number>;
 | 
					    phaseComplexity: Map<string, number>;
 | 
				
			||||||
  } {
 | 
					  } {
 | 
				
			||||||
    if (!phases || !Array.isArray(phases)) {
 | 
					    if (!phases || !Array.isArray(phases)) {
 | 
				
			||||||
      console.warn('[AI-PIPELINE] No phases data available, using fallback');
 | 
					 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        phases: [],
 | 
					        phases: [],
 | 
				
			||||||
        criticalPhaseIds: [],
 | 
					        criticalPhaseIds: [],
 | 
				
			||||||
@ -268,20 +258,12 @@ class AIPipeline {
 | 
				
			|||||||
    const phaseComplexity = new Map<string, number>();
 | 
					    const phaseComplexity = new Map<string, number>();
 | 
				
			||||||
    phases.forEach(phase => {
 | 
					    phases.forEach(phase => {
 | 
				
			||||||
      let complexity = 1;
 | 
					      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;
 | 
				
			||||||
      if (phase.description?.length > 100) complexity += 1;
 | 
					      if (phase.description?.length > 100) complexity += 1;
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      phaseComplexity.set(phase.id, complexity);
 | 
					      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 {
 | 
					    return {
 | 
				
			||||||
      phases,
 | 
					      phases,
 | 
				
			||||||
      criticalPhaseIds,
 | 
					      criticalPhaseIds,
 | 
				
			||||||
@ -292,11 +274,9 @@ class AIPipeline {
 | 
				
			|||||||
  private calculateToolSelectionConfidence(
 | 
					  private calculateToolSelectionConfidence(
 | 
				
			||||||
    selectedCount: number,
 | 
					    selectedCount: number,
 | 
				
			||||||
    totalCount: number,
 | 
					    totalCount: number,
 | 
				
			||||||
    //method: string,
 | 
					 | 
				
			||||||
    conceptsCount: number
 | 
					    conceptsCount: number
 | 
				
			||||||
  ): number {
 | 
					  ): number {
 | 
				
			||||||
    let confidence = 50;
 | 
					    let confidence = 50;
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    const selectionRatio = selectedCount / totalCount;
 | 
					    const selectionRatio = selectedCount / totalCount;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
					    if (selectionRatio >= 0.05 && selectionRatio <= 0.20) {
 | 
				
			||||||
@ -307,17 +287,8 @@ class AIPipeline {
 | 
				
			|||||||
      confidence -= 15;
 | 
					      confidence -= 15;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    //if (method.includes('embeddings')) {
 | 
					    if (conceptsCount > 0) confidence += 10;
 | 
				
			||||||
    //confidence += 15;
 | 
					    if (selectedCount >= 8 && selectedCount <= 25) confidence += 10;
 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (conceptsCount > 0) {
 | 
					 | 
				
			||||||
      confidence += 10;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (selectedCount >= 8 && selectedCount <= 25) {
 | 
					 | 
				
			||||||
      confidence += 10;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return Math.min(95, Math.max(40, confidence));
 | 
					    return Math.min(95, Math.max(40, confidence));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -327,7 +298,8 @@ class AIPipeline {
 | 
				
			|||||||
    toolsData: any, 
 | 
					    toolsData: any, 
 | 
				
			||||||
    completedTasks: number, 
 | 
					    completedTasks: number, 
 | 
				
			||||||
    failedTasks: number,
 | 
					    failedTasks: number,
 | 
				
			||||||
    pipelineStart: number
 | 
					    pipelineStart: number,
 | 
				
			||||||
 | 
					    toolsDataHash: string
 | 
				
			||||||
  ): Promise<{ completed: number; failed: number }> {
 | 
					  ): Promise<{ completed: number; failed: number }> {
 | 
				
			||||||
    const phases = toolsData.phases || [];
 | 
					    const phases = toolsData.phases || [];
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -337,10 +309,7 @@ class AIPipeline {
 | 
				
			|||||||
        tool && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(phase.id)
 | 
					        tool && tool.phases && Array.isArray(tool.phases) && tool.phases.includes(phase.id)
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (phaseTools.length === 0) {
 | 
					      if (phaseTools.length === 0) continue;
 | 
				
			||||||
        console.log(`[AI-PIPELINE] No tools available for phase: ${phase.id}`);
 | 
					 | 
				
			||||||
        continue;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
 | 
					      const selections = await toolSelector.selectToolsForPhase(context.userQuery, phase, phaseTools, context);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
@ -370,6 +339,7 @@ class AIPipeline {
 | 
				
			|||||||
        phaseConfidence,
 | 
					        phaseConfidence,
 | 
				
			||||||
        phaseStart,
 | 
					        phaseStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          phaseId: phase.id,
 | 
					          phaseId: phase.id,
 | 
				
			||||||
          availableToolsCount: phaseTools.length,
 | 
					          availableToolsCount: phaseTools.length,
 | 
				
			||||||
          selectedToolsCount: selections.length,
 | 
					          selectedToolsCount: selections.length,
 | 
				
			||||||
@ -383,7 +353,6 @@ class AIPipeline {
 | 
				
			|||||||
        if (tool) {
 | 
					        if (tool) {
 | 
				
			||||||
          const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
 | 
					          const moderatedTaskRelevance = this.moderateTaskRelevance(sel.taskRelevance);
 | 
				
			||||||
          const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
					          const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
				
			||||||
          
 | 
					 | 
				
			||||||
          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);
 | 
				
			||||||
@ -405,6 +374,7 @@ class AIPipeline {
 | 
				
			|||||||
            moderatedTaskRelevance || 70,
 | 
					            moderatedTaskRelevance || 70,
 | 
				
			||||||
            phaseStart,
 | 
					            phaseStart,
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
					              toolsDataHash: toolsDataHash,
 | 
				
			||||||
              toolType: tool.type,
 | 
					              toolType: tool.type,
 | 
				
			||||||
              priority,
 | 
					              priority,
 | 
				
			||||||
              moderationApplied: sel.taskRelevance !== moderatedTaskRelevance,
 | 
					              moderationApplied: sel.taskRelevance !== moderatedTaskRelevance,
 | 
				
			||||||
@ -418,7 +388,7 @@ class AIPipeline {
 | 
				
			|||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart);
 | 
					    const completionResult = await this.completeUnderrepresentedPhases(context, toolsData, pipelineStart, toolsDataHash);
 | 
				
			||||||
    completedTasks += completionResult.completed;
 | 
					    completedTasks += completionResult.completed;
 | 
				
			||||||
    failedTasks += completionResult.failed;
 | 
					    failedTasks += completionResult.failed;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -437,7 +407,6 @@ class AIPipeline {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  ): number {
 | 
					  ): number {
 | 
				
			||||||
    let confidence = 60;
 | 
					    let confidence = 60;
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    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;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -454,13 +423,8 @@ class AIPipeline {
 | 
				
			|||||||
      confidence += 10;
 | 
					      confidence += 10;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (isCritical && selectedCount >= 2) {
 | 
					    if (isCritical && selectedCount >= 2) confidence += 10;
 | 
				
			||||||
      confidence += 10;
 | 
					    if (phaseComplexity > 2 && selectedCount >= phaseComplexity) confidence += 5;
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (phaseComplexity > 2 && selectedCount >= phaseComplexity) {
 | 
					 | 
				
			||||||
      confidence += 5;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    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;
 | 
				
			||||||
@ -504,12 +468,13 @@ class AIPipeline {
 | 
				
			|||||||
    context: PipelineContext, 
 | 
					    context: PipelineContext, 
 | 
				
			||||||
    completedTasks: number, 
 | 
					    completedTasks: number, 
 | 
				
			||||||
    failedTasks: number,
 | 
					    failedTasks: number,
 | 
				
			||||||
    pipelineStart: number
 | 
					    pipelineStart: number,
 | 
				
			||||||
 | 
					    toolsDataHash: string
 | 
				
			||||||
  ): Promise<{ completed: number; failed: number }> {
 | 
					  ): Promise<{ completed: number; failed: number }> {
 | 
				
			||||||
    const topTools = context.filteredData.tools.slice(0, 3);
 | 
					    const topTools = context.filteredData.tools.slice(0, 3);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for (let i = 0; i < topTools.length; i++) {
 | 
					    for (let i = 0; i < topTools.length; i++) {
 | 
				
			||||||
      const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1, pipelineStart);
 | 
					      const evaluationResult = await this.evaluateSpecificTool(context, topTools[i], i + 1, pipelineStart, toolsDataHash);
 | 
				
			||||||
      if (evaluationResult.success) completedTasks++; else failedTasks++;
 | 
					      if (evaluationResult.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      this.trackTokenUsage(evaluationResult.aiUsage);
 | 
					      this.trackTokenUsage(evaluationResult.aiUsage);
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
@ -521,7 +486,8 @@ class AIPipeline {
 | 
				
			|||||||
  private async completeUnderrepresentedPhases(
 | 
					  private async completeUnderrepresentedPhases(
 | 
				
			||||||
    context: PipelineContext, 
 | 
					    context: PipelineContext, 
 | 
				
			||||||
    toolsData: any, 
 | 
					    toolsData: any, 
 | 
				
			||||||
    pipelineStart: number
 | 
					    pipelineStart: number,
 | 
				
			||||||
 | 
					    toolsDataHash: string
 | 
				
			||||||
  ): Promise<{ completed: number; failed: number }> {
 | 
					  ): Promise<{ completed: number; failed: number }> {
 | 
				
			||||||
    const phases = toolsData.phases || [];
 | 
					    const phases = toolsData.phases || [];
 | 
				
			||||||
    const selectedPhases = new Map<string, number>();
 | 
					    const selectedPhases = new Map<string, number>();
 | 
				
			||||||
@ -538,15 +504,10 @@ class AIPipeline {
 | 
				
			|||||||
      return count <= 1;
 | 
					      return count <= 1;
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (underrepresentedPhases.length === 0) {
 | 
					    if (underrepresentedPhases.length === 0) return { completed: 0, failed: 0 };
 | 
				
			||||||
      console.log('[AI-PIPELINE] All phases adequately represented');
 | 
					 | 
				
			||||||
      return { completed: 0, failed: 0 };
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    console.log('[AI-PIPELINE] Completing underrepresented phases:', underrepresentedPhases.map((p: any) => p.id).join(', '));
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    for (const phase of underrepresentedPhases) {
 | 
					    for (const phase of underrepresentedPhases) {
 | 
				
			||||||
      const result = await this.completePhaseWithSemanticSearchAndAI(context, phase, toolsData, pipelineStart);
 | 
					      const result = await this.completePhaseWithSemanticSearchAndAI(context, phase, toolsData, pipelineStart, toolsDataHash);
 | 
				
			||||||
      if (result.success) completedTasks++; else failedTasks++;
 | 
					      if (result.success) completedTasks++; else failedTasks++;
 | 
				
			||||||
      await this.delay(this.config.microTaskDelay);
 | 
					      await this.delay(this.config.microTaskDelay);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -558,13 +519,12 @@ class AIPipeline {
 | 
				
			|||||||
    context: PipelineContext, 
 | 
					    context: PipelineContext, 
 | 
				
			||||||
    phase: any, 
 | 
					    phase: any, 
 | 
				
			||||||
    toolsData: any, 
 | 
					    toolsData: any, 
 | 
				
			||||||
    pipelineStart: number
 | 
					    pipelineStart: number,
 | 
				
			||||||
 | 
					    toolsDataHash: string
 | 
				
			||||||
  ): Promise<MicroTaskResult> {
 | 
					  ): Promise<MicroTaskResult> {
 | 
				
			||||||
    const phaseStart = Date.now();
 | 
					    const phaseStart = Date.now();
 | 
				
			||||||
    const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
 | 
					    const phaseQuery = `forensic ${phase.name.toLowerCase()} tools methods`;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    console.log('[AI-PIPELINE] Phase completion for:', phase.id);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
 | 
					      const phaseResults = await embeddingsService.findSimilar(phaseQuery, 20, 0.2);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
@ -574,6 +534,7 @@ class AIPipeline {
 | 
				
			|||||||
        0.2,
 | 
					        0.2,
 | 
				
			||||||
        phaseStart,
 | 
					        phaseStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          phaseId: phase.id,
 | 
					          phaseId: phase.id,
 | 
				
			||||||
          phaseName: phase.name,
 | 
					          phaseName: phase.name,
 | 
				
			||||||
          completionPurpose: 'underrepresented-phase-enhancement'
 | 
					          completionPurpose: 'underrepresented-phase-enhancement'
 | 
				
			||||||
@ -581,7 +542,6 @@ class AIPipeline {
 | 
				
			|||||||
      );
 | 
					      );
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (phaseResults.length === 0) {
 | 
					      if (phaseResults.length === 0) {
 | 
				
			||||||
        console.log('[AI-PIPELINE] No semantic results for phase:', phase.id);
 | 
					 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
          taskType: 'phase-completion',
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
          content: '',
 | 
					          content: '',
 | 
				
			||||||
@ -613,7 +573,6 @@ class AIPipeline {
 | 
				
			|||||||
        .slice(0, 2);
 | 
					        .slice(0, 2);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (phaseTools.length === 0) {
 | 
					      if (phaseTools.length === 0) {
 | 
				
			||||||
        console.log('[AI-PIPELINE] No suitable tools for phase completion:', phase.id);
 | 
					 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
          taskType: 'phase-completion',
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
          content: '',
 | 
					          content: '',
 | 
				
			||||||
@ -623,10 +582,9 @@ class AIPipeline {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      const selectionPrompt = getPrompt('generatePhaseCompletionPrompt', context.userQuery, phase, phaseTools, phaseConcepts);
 | 
					      const selectionPrompt = getPrompt('generatePhaseCompletionPrompt', context.userQuery, phase, phaseTools, phaseConcepts);
 | 
				
			||||||
      const selectionResult = await this.callMicroTaskAI(selectionPrompt, context, 800, 'phase-completion-selection');
 | 
					      const selectionResult = await this.callMicroTaskAI(selectionPrompt, context, 'phase-completion-selection');
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (!selectionResult.success) {
 | 
					      if (!selectionResult.success) {
 | 
				
			||||||
        console.error('[AI-PIPELINE] Phase completion selection failed for:', phase.id);
 | 
					 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
          taskType: 'phase-completion',
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
          content: '',
 | 
					          content: '',
 | 
				
			||||||
@ -648,7 +606,6 @@ class AIPipeline {
 | 
				
			|||||||
        .slice(0, 2);
 | 
					        .slice(0, 2);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (validTools.length === 0) {
 | 
					      if (validTools.length === 0) {
 | 
				
			||||||
        console.log('[AI-PIPELINE] No valid tools selected for phase completion:', phase.id);
 | 
					 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
          taskType: 'phase-completion',
 | 
					          taskType: 'phase-completion',
 | 
				
			||||||
          content: selection.completionReasoning || '',
 | 
					          content: selection.completionReasoning || '',
 | 
				
			||||||
@ -660,8 +617,6 @@ class AIPipeline {
 | 
				
			|||||||
      const actualToolsAdded = validTools.map(tool => tool.name);
 | 
					      const actualToolsAdded = validTools.map(tool => tool.name);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      for (const tool of validTools) {
 | 
					      for (const tool of validTools) {
 | 
				
			||||||
        console.log('[AI-PIPELINE] Generating AI reasoning for phase completion tool:', tool.name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        const reasoningPrompt = getPrompt(
 | 
					        const reasoningPrompt = getPrompt(
 | 
				
			||||||
          'phaseCompletionReasoning',
 | 
					          'phaseCompletionReasoning',
 | 
				
			||||||
          context.userQuery,
 | 
					          context.userQuery,
 | 
				
			||||||
@ -671,7 +626,7 @@ class AIPipeline {
 | 
				
			|||||||
          selection.completionReasoning || 'Nachergänzung zur Vervollständigung der Phasenabdeckung'
 | 
					          selection.completionReasoning || 'Nachergänzung zur Vervollständigung der Phasenabdeckung'
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        const reasoningResult = await this.callMicroTaskAI(reasoningPrompt, context, 400, 'phase-completion-reasoning');
 | 
					        const reasoningResult = await this.callMicroTaskAI(reasoningPrompt, context, 'phase-completion-reasoning');
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        let detailedJustification: string;
 | 
					        let detailedJustification: string;
 | 
				
			||||||
        let moderatedTaskRelevance = 75;
 | 
					        let moderatedTaskRelevance = 75;
 | 
				
			||||||
@ -695,8 +650,6 @@ class AIPipeline {
 | 
				
			|||||||
          moderatedTaskRelevance,
 | 
					          moderatedTaskRelevance,
 | 
				
			||||||
          dynamicLimitations
 | 
					          dynamicLimitations
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        console.log('[AI-PIPELINE] Added phase completion tool with AI reasoning:', tool.name);
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      auditService.addPhaseCompletion(
 | 
					      auditService.addPhaseCompletion(
 | 
				
			||||||
@ -705,6 +658,7 @@ class AIPipeline {
 | 
				
			|||||||
        selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
 | 
					        selection.completionReasoning || `${actualToolsAdded.length} Tools für ${phase.name} hinzugefügt`,
 | 
				
			||||||
        phaseStart,
 | 
					        phaseStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          toolsAdded: actualToolsAdded,
 | 
					          toolsAdded: actualToolsAdded,
 | 
				
			||||||
          toolType: validTools[0]?.type,
 | 
					          toolType: validTools[0]?.type,
 | 
				
			||||||
          semanticSimilarity: phaseResults.find(r => r.name === validTools[0]?.name)?.similarity,
 | 
					          semanticSimilarity: phaseResults.find(r => r.name === validTools[0]?.name)?.similarity,
 | 
				
			||||||
@ -723,8 +677,6 @@ class AIPipeline {
 | 
				
			|||||||
      };
 | 
					      };
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      console.error('[AI-PIPELINE] Phase completion failed for:', phase.id, error);
 | 
					 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        taskType: 'phase-completion',
 | 
					        taskType: 'phase-completion',
 | 
				
			||||||
        content: '',
 | 
					        content: '',
 | 
				
			||||||
@ -756,9 +708,7 @@ class AIPipeline {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private moderateTaskRelevance(taskRelevance: number): number {
 | 
					  private moderateTaskRelevance(taskRelevance: number): number {
 | 
				
			||||||
    if (typeof taskRelevance !== 'number') {
 | 
					    if (typeof taskRelevance !== 'number') return 70;
 | 
				
			||||||
      return 70;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    let moderated = Math.min(taskRelevance, this.config.taskRelevanceModeration.maxInitialScore);
 | 
					    let moderated = Math.min(taskRelevance, this.config.taskRelevanceModeration.maxInitialScore);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -770,13 +720,12 @@ class AIPipeline {
 | 
				
			|||||||
    return Math.round(Math.min(moderated, this.config.taskRelevanceModeration.maxInitialScore));
 | 
					    return Math.round(Math.min(moderated, this.config.taskRelevanceModeration.maxInitialScore));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async analyzeScenario(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
					  private async analyzeScenario(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Scenario analysis');
 | 
					 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const isWorkflow = context.mode === 'workflow';
 | 
					    const isWorkflow = context.mode === 'workflow';
 | 
				
			||||||
    const prompt = getPrompt('scenarioAnalysis', isWorkflow, context.userQuery);
 | 
					    const prompt = getPrompt('scenarioAnalysis', isWorkflow, context.userQuery);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 400, 'scenario-analysis');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 'scenario-analysis');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      if (isWorkflow) {
 | 
					      if (isWorkflow) {
 | 
				
			||||||
@ -801,6 +750,7 @@ class AIPipeline {
 | 
				
			|||||||
        `Analysierte ${isWorkflow ? 'Szenario' : 'Problem'} basierend auf Nutzereingabe: "${context.userQuery.slice(0, 100)}..." - Identifizierte Kernaspekte und Herausforderungen für forensische Untersuchung`,
 | 
					        `Analysierte ${isWorkflow ? 'Szenario' : 'Problem'} basierend auf Nutzereingabe: "${context.userQuery.slice(0, 100)}..." - Identifizierte Kernaspekte und Herausforderungen für forensische Untersuchung`,
 | 
				
			||||||
        taskStart,
 | 
					        taskStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          microTaskType: 'scenario-analysis',
 | 
					          microTaskType: 'scenario-analysis',
 | 
				
			||||||
          analysisType: isWorkflow ? 'scenario' : 'problem',
 | 
					          analysisType: isWorkflow ? 'scenario' : 'problem',
 | 
				
			||||||
          contentLength: result.content.length,
 | 
					          contentLength: result.content.length,
 | 
				
			||||||
@ -814,13 +764,12 @@ class AIPipeline {
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async generateApproach(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
					  private async generateApproach(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Investigation approach');
 | 
					 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const isWorkflow = context.mode === 'workflow';
 | 
					    const isWorkflow = context.mode === 'workflow';
 | 
				
			||||||
    const prompt = getPrompt('investigationApproach', isWorkflow, context.userQuery);
 | 
					    const prompt = getPrompt('investigationApproach', isWorkflow, context.userQuery);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 400, 'investigation-approach');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 'investigation-approach');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      context.investigationApproach = result.content;
 | 
					      context.investigationApproach = result.content;
 | 
				
			||||||
@ -840,6 +789,7 @@ class AIPipeline {
 | 
				
			|||||||
        `Entwickelte ${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz unter Berücksichtigung der Szenario-Analyse - Strukturierte Herangehensweise für forensische Methodik`,
 | 
					        `Entwickelte ${isWorkflow ? 'Untersuchungs' : 'Lösungs'}ansatz unter Berücksichtigung der Szenario-Analyse - Strukturierte Herangehensweise für forensische Methodik`,
 | 
				
			||||||
        taskStart,
 | 
					        taskStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          microTaskType: 'investigation-approach',
 | 
					          microTaskType: 'investigation-approach',
 | 
				
			||||||
          approachType: isWorkflow ? 'investigation' : 'solution',
 | 
					          approachType: isWorkflow ? 'investigation' : 'solution',
 | 
				
			||||||
          contentLength: result.content.length,
 | 
					          contentLength: result.content.length,
 | 
				
			||||||
@ -854,13 +804,12 @@ class AIPipeline {
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async generateCriticalConsiderations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
					  private async generateCriticalConsiderations(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Critical considerations');
 | 
					 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const isWorkflow = context.mode === 'workflow';
 | 
					    const isWorkflow = context.mode === 'workflow';
 | 
				
			||||||
    const prompt = getPrompt('criticalConsiderations', isWorkflow, context.userQuery);
 | 
					    const prompt = getPrompt('criticalConsiderations', isWorkflow, context.userQuery);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 350, 'critical-considerations');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 'critical-considerations');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      context.criticalConsiderations = result.content;
 | 
					      context.criticalConsiderations = result.content;
 | 
				
			||||||
@ -880,6 +829,7 @@ class AIPipeline {
 | 
				
			|||||||
        'Identifizierte kritische Überlegungen für forensische Untersuchung - Berücksichtigung von Beweissicherung, Chain of Custody und methodischen Herausforderungen',
 | 
					        'Identifizierte kritische Überlegungen für forensische Untersuchung - Berücksichtigung von Beweissicherung, Chain of Custody und methodischen Herausforderungen',
 | 
				
			||||||
        taskStart,
 | 
					        taskStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          microTaskType: 'critical-considerations',
 | 
					          microTaskType: 'critical-considerations',
 | 
				
			||||||
          contentLength: result.content.length,
 | 
					          contentLength: result.content.length,
 | 
				
			||||||
          decisionBasis: 'ai-analysis',
 | 
					          decisionBasis: 'ai-analysis',
 | 
				
			||||||
@ -896,9 +846,9 @@ class AIPipeline {
 | 
				
			|||||||
    context: PipelineContext, 
 | 
					    context: PipelineContext, 
 | 
				
			||||||
    tool: any, 
 | 
					    tool: any, 
 | 
				
			||||||
    rank: number,
 | 
					    rank: number,
 | 
				
			||||||
    pipelineStart: number
 | 
					    pipelineStart: number,
 | 
				
			||||||
 | 
					    toolsDataHash: string
 | 
				
			||||||
  ): Promise<MicroTaskResult> {
 | 
					  ): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Tool evaluation for:', tool.name);
 | 
					 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
 | 
					    const existingSelection = context.selectedTools?.find((st: any) => st.tool && st.tool.name === tool.name);
 | 
				
			||||||
    const originalTaskRelevance = existingSelection?.taskRelevance || 70;
 | 
					    const originalTaskRelevance = existingSelection?.taskRelevance || 70;
 | 
				
			||||||
@ -906,7 +856,7 @@ class AIPipeline {
 | 
				
			|||||||
    const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
					    const priority = this.derivePriorityFromScore(moderatedTaskRelevance);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, moderatedTaskRelevance);
 | 
					    const prompt = getPrompt('toolEvaluation', context.userQuery, tool, rank, moderatedTaskRelevance);
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 1000, 'tool-evaluation');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 'tool-evaluation');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      const evaluation = JSONParser.safeParseJSON(result.content, {
 | 
					      const evaluation = JSONParser.safeParseJSON(result.content, {
 | 
				
			||||||
@ -942,6 +892,7 @@ class AIPipeline {
 | 
				
			|||||||
        `Bewertete Tool "${tool.name}" (Rang ${rank}) - Analysierte Eignung für spezifische Aufgabenstellung mit Fokus auf praktische Anwendbarkeit und methodische Integration`,
 | 
					        `Bewertete Tool "${tool.name}" (Rang ${rank}) - Analysierte Eignung für spezifische Aufgabenstellung mit Fokus auf praktische Anwendbarkeit und methodische Integration`,
 | 
				
			||||||
        taskStart,
 | 
					        taskStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          microTaskType: 'tool-evaluation',
 | 
					          microTaskType: 'tool-evaluation',
 | 
				
			||||||
          toolName: tool.name,
 | 
					          toolName: tool.name,
 | 
				
			||||||
          toolType: tool.type,
 | 
					          toolType: tool.type,
 | 
				
			||||||
@ -964,8 +915,7 @@ class AIPipeline {
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async selectBackgroundKnowledge(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
					  private async selectBackgroundKnowledge(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Background knowledge selection');
 | 
					 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const availableConcepts = context.filteredData.concepts;
 | 
					    const availableConcepts = context.filteredData.concepts;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -980,7 +930,7 @@ class AIPipeline {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
 | 
					    const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
 | 
				
			||||||
    const prompt = getPrompt('backgroundKnowledgeSelection', context.userQuery, context.mode, selectedToolNames, availableConcepts);
 | 
					    const prompt = getPrompt('backgroundKnowledgeSelection', context.userQuery, context.mode, selectedToolNames, availableConcepts);
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 700, 'background-knowledge');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 'background-knowledge');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      const selections = JSONParser.safeParseJSON(result.content, []);
 | 
					      const selections = JSONParser.safeParseJSON(result.content, []);
 | 
				
			||||||
@ -1017,6 +967,7 @@ class AIPipeline {
 | 
				
			|||||||
          finalConfidence,
 | 
					          finalConfidence,
 | 
				
			||||||
          taskStart,
 | 
					          taskStart,
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
 | 
					            toolsDataHash: toolsDataHash,
 | 
				
			||||||
            microTaskType: 'background-knowledge',
 | 
					            microTaskType: 'background-knowledge',
 | 
				
			||||||
            availableConceptsCount: availableConcepts.length,
 | 
					            availableConceptsCount: availableConcepts.length,
 | 
				
			||||||
            selectedConceptsCount: context.backgroundKnowledge.length,
 | 
					            selectedConceptsCount: context.backgroundKnowledge.length,
 | 
				
			||||||
@ -1041,32 +992,25 @@ class AIPipeline {
 | 
				
			|||||||
  ): number {
 | 
					  ): number {
 | 
				
			||||||
    let bonus = 0;
 | 
					    let bonus = 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (selectedKnowledge.length > 0) {
 | 
					    if (selectedKnowledge.length > 0) bonus += 10;
 | 
				
			||||||
      bonus += 10;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const ratio = selectedKnowledge.length / availableConcepts.length;
 | 
					    const ratio = selectedKnowledge.length / availableConcepts.length;
 | 
				
			||||||
    if (ratio >= 0.1 && ratio <= 0.3) {
 | 
					    if (ratio >= 0.1 && ratio <= 0.3) bonus += 15;
 | 
				
			||||||
      bonus += 15;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const hasGoodReasonings = selectedKnowledge.some(bk => 
 | 
					    const hasGoodReasonings = selectedKnowledge.some(bk => 
 | 
				
			||||||
      bk.relevance && bk.relevance.length > 30
 | 
					      bk.relevance && bk.relevance.length > 30
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    if (hasGoodReasonings) {
 | 
					    if (hasGoodReasonings) bonus += 10;
 | 
				
			||||||
      bonus += 10;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return bonus;
 | 
					    return bonus;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number): Promise<MicroTaskResult> {
 | 
					  private async generateFinalRecommendations(context: PipelineContext, pipelineStart: number, toolsDataHash: string): Promise<MicroTaskResult> {
 | 
				
			||||||
    console.log('[AI-PIPELINE] Micro-task: Final recommendations');
 | 
					 | 
				
			||||||
    const taskStart = Date.now();
 | 
					    const taskStart = Date.now();
 | 
				
			||||||
    const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
 | 
					    const selectedToolNames = context.selectedTools?.map((st: any) => st.tool && st.tool.name).filter(Boolean) || [];
 | 
				
			||||||
    const prompt = getPrompt('finalRecommendations', context.mode === 'workflow', context.userQuery, selectedToolNames);
 | 
					    const prompt = getPrompt('finalRecommendations', context.mode === 'workflow', context.userQuery, selectedToolNames);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    const result = await this.callMicroTaskAI(prompt, context, 350, 'final-recommendations');
 | 
					    const result = await this.callMicroTaskAI(prompt, context, 'final-recommendations');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (result.success) {
 | 
					    if (result.success) {
 | 
				
			||||||
      const confidence = auditService.calculateAIResponseConfidence(
 | 
					      const confidence = auditService.calculateAIResponseConfidence(
 | 
				
			||||||
@ -1086,6 +1030,7 @@ class AIPipeline {
 | 
				
			|||||||
        `Generierte abschließende ${context.mode}-Empfehlungen basierend auf ausgewählten ${selectedToolNames.length} Tools - Synthese aller Analyseschritte zu kohärenter Handlungsempfehlung`,
 | 
					        `Generierte abschließende ${context.mode}-Empfehlungen basierend auf ausgewählten ${selectedToolNames.length} Tools - Synthese aller Analyseschritte zu kohärenter Handlungsempfehlung`,
 | 
				
			||||||
        taskStart,
 | 
					        taskStart,
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          toolsDataHash: toolsDataHash,
 | 
				
			||||||
          microTaskType: 'final-recommendations',
 | 
					          microTaskType: 'final-recommendations',
 | 
				
			||||||
          mode: context.mode,
 | 
					          mode: context.mode,
 | 
				
			||||||
          selectedToolsCount: selectedToolNames.length,
 | 
					          selectedToolsCount: selectedToolNames.length,
 | 
				
			||||||
@ -1105,30 +1050,17 @@ class AIPipeline {
 | 
				
			|||||||
  private calculateSynthesisBonus(selectedToolNames: string[], context: PipelineContext): number {
 | 
					  private calculateSynthesisBonus(selectedToolNames: string[], context: PipelineContext): number {
 | 
				
			||||||
    let bonus = 0;
 | 
					    let bonus = 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if (selectedToolNames.length >= 3) {
 | 
					    if (selectedToolNames.length >= 3) bonus += 10;
 | 
				
			||||||
      bonus += 10;
 | 
					    if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) bonus += 10;
 | 
				
			||||||
    }
 | 
					    if (context.scenarioAnalysis || context.problemAnalysis) bonus += 5;
 | 
				
			||||||
    
 | 
					    if (context.investigationApproach) bonus += 5;
 | 
				
			||||||
    if (context.backgroundKnowledge && context.backgroundKnowledge.length > 0) {
 | 
					 | 
				
			||||||
      bonus += 10;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (context.scenarioAnalysis || context.problemAnalysis) {
 | 
					 | 
				
			||||||
      bonus += 5;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (context.investigationApproach) {
 | 
					 | 
				
			||||||
      bonus += 5;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return bonus;
 | 
					    return bonus;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private buildRecommendation(context: PipelineContext, mode: string, finalContent: string): any {
 | 
					  private buildRecommendation(context: PipelineContext, mode: string, finalContent: string, toolsDataHash: string): any {
 | 
				
			||||||
    const isWorkflow = mode === 'workflow';
 | 
					    const isWorkflow = mode === 'workflow';
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    console.log('[AI-PIPELINE] Building recommendation for', mode, 'mode with', context.selectedTools?.length || 0, 'tools');
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    const base = {
 | 
					    const base = {
 | 
				
			||||||
      [isWorkflow ? 'scenario_analysis' : 'problem_analysis']: 
 | 
					      [isWorkflow ? 'scenario_analysis' : 'problem_analysis']: 
 | 
				
			||||||
        isWorkflow ? context.scenarioAnalysis : context.problemAnalysis,
 | 
					        isWorkflow ? context.scenarioAnalysis : context.problemAnalysis,
 | 
				
			||||||
@ -1161,6 +1093,7 @@ class AIPipeline {
 | 
				
			|||||||
          confidence,
 | 
					          confidence,
 | 
				
			||||||
          Date.now(),
 | 
					          Date.now(),
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
 | 
					            toolsDataHash: toolsDataHash,
 | 
				
			||||||
            phase: st.phase,
 | 
					            phase: st.phase,
 | 
				
			||||||
            priority: st.priority,
 | 
					            priority: st.priority,
 | 
				
			||||||
            toolType: st.tool.type,
 | 
					            toolType: st.tool.type,
 | 
				
			||||||
@ -1205,6 +1138,7 @@ class AIPipeline {
 | 
				
			|||||||
          confidence,
 | 
					          confidence,
 | 
				
			||||||
          Date.now(),
 | 
					          Date.now(),
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
 | 
					            toolsDataHash: toolsDataHash,
 | 
				
			||||||
            rank: st.tool.evaluation?.rank || 1,
 | 
					            rank: st.tool.evaluation?.rank || 1,
 | 
				
			||||||
            toolType: st.tool.type,
 | 
					            toolType: st.tool.type,
 | 
				
			||||||
            moderatedTaskRelevance: st.taskRelevance
 | 
					            moderatedTaskRelevance: st.taskRelevance
 | 
				
			||||||
@ -1237,7 +1171,6 @@ class AIPipeline {
 | 
				
			|||||||
  private async callMicroTaskAI(
 | 
					  private async callMicroTaskAI(
 | 
				
			||||||
    prompt: string, 
 | 
					    prompt: string, 
 | 
				
			||||||
    context: PipelineContext, 
 | 
					    context: PipelineContext, 
 | 
				
			||||||
    maxTokens: number = 500,
 | 
					 | 
				
			||||||
    taskType: string = 'micro-task'
 | 
					    taskType: string = 'micro-task'
 | 
				
			||||||
  ): Promise<MicroTaskResult> {
 | 
					  ): Promise<MicroTaskResult> {
 | 
				
			||||||
    const startTime = Date.now();
 | 
					    const startTime = Date.now();
 | 
				
			||||||
@ -1245,15 +1178,11 @@ class AIPipeline {
 | 
				
			|||||||
    let contextPrompt = prompt;
 | 
					    let contextPrompt = prompt;
 | 
				
			||||||
    if (context.contextHistory.length > 0) {
 | 
					    if (context.contextHistory.length > 0) {
 | 
				
			||||||
      const contextSection = `BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n`;
 | 
					      const contextSection = `BISHERIGE ANALYSE:\n${context.contextHistory.join('\n\n')}\n\nAKTUELLE AUFGABE:\n`;
 | 
				
			||||||
      const combinedPrompt = contextSection + prompt;
 | 
					      contextPrompt = contextSection + prompt;
 | 
				
			||||||
      
 | 
					 | 
				
			||||||
      if (aiService.estimateTokens(combinedPrompt) <= this.config.maxPromptTokens) {
 | 
					 | 
				
			||||||
        contextPrompt = combinedPrompt;
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const response = await aiService.callMicroTaskAI(contextPrompt, maxTokens);
 | 
					      const response = await aiService.callMicroTaskAI(contextPrompt);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      return {
 | 
					      return {
 | 
				
			||||||
        taskType,
 | 
					        taskType,
 | 
				
			||||||
@ -1280,13 +1209,11 @@ class AIPipeline {
 | 
				
			|||||||
    context.contextHistory.push(newEntry);
 | 
					    context.contextHistory.push(newEntry);
 | 
				
			||||||
    context.currentContextLength += entryTokens;
 | 
					    context.currentContextLength += entryTokens;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    /*while (context.currentContextLength > this.config.maxContextTokens && context.contextHistory.length > 1) {
 | 
					    if (context.contextHistory.length > 1) {
 | 
				
			||||||
      const removed = context.contextHistory.shift()!;
 | 
					 | 
				
			||||||
      context.currentContextLength -= aiService.estimateTokens(removed);
 | 
					 | 
				
			||||||
    }*/
 | 
					 | 
				
			||||||
      const removed = context.contextHistory.shift()!;
 | 
					      const removed = context.contextHistory.shift()!;
 | 
				
			||||||
      context.currentContextLength -= aiService.estimateTokens(removed);
 | 
					      context.currentContextLength -= aiService.estimateTokens(removed);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private addToolToSelection(
 | 
					  private addToolToSelection(
 | 
				
			||||||
    context: PipelineContext,
 | 
					    context: PipelineContext,
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,6 @@ export interface AIServiceConfig {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface AICallOptions {
 | 
					export interface AICallOptions {
 | 
				
			||||||
  maxTokens?: number;
 | 
					 | 
				
			||||||
  temperature?: number;
 | 
					  temperature?: number;
 | 
				
			||||||
  timeout?: number;
 | 
					  timeout?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -34,9 +33,8 @@ class AIService {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.defaultOptions = {
 | 
					    this.defaultOptions = {
 | 
				
			||||||
      maxTokens: 32768,
 | 
					 | 
				
			||||||
      temperature: 0.3,
 | 
					      temperature: 0.3,
 | 
				
			||||||
      timeout: 30000
 | 
					      timeout: 60000
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log('[AI-SERVICE] Initialized with model:', this.config.model);
 | 
					    console.log('[AI-SERVICE] Initialized with model:', this.config.model);
 | 
				
			||||||
@ -55,7 +53,6 @@ class AIService {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    console.log('[AI-SERVICE] Making API call:', {
 | 
					    console.log('[AI-SERVICE] Making API call:', {
 | 
				
			||||||
      promptLength: prompt.length,
 | 
					      promptLength: prompt.length,
 | 
				
			||||||
      maxTokens: mergedOptions.maxTokens,
 | 
					 | 
				
			||||||
      temperature: mergedOptions.temperature
 | 
					      temperature: mergedOptions.temperature
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,7 +67,6 @@ class AIService {
 | 
				
			|||||||
    const requestBody = {
 | 
					    const requestBody = {
 | 
				
			||||||
      model: this.config.model,
 | 
					      model: this.config.model,
 | 
				
			||||||
      messages: [{ role: 'user', content: prompt }],
 | 
					      messages: [{ role: 'user', content: prompt }],
 | 
				
			||||||
      max_tokens: mergedOptions.maxTokens,
 | 
					 | 
				
			||||||
      temperature: mergedOptions.temperature
 | 
					      temperature: mergedOptions.temperature
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -122,11 +118,10 @@ class AIService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async callMicroTaskAI(prompt: string, maxTokens: number = 500): Promise<AIResponse> {
 | 
					  async callMicroTaskAI(prompt: string): Promise<AIResponse> {
 | 
				
			||||||
    return this.callAI(prompt, { 
 | 
					    return this.callAI(prompt, { 
 | 
				
			||||||
      maxTokens, 
 | 
					 | 
				
			||||||
      temperature: 0.3,
 | 
					      temperature: 0.3,
 | 
				
			||||||
      timeout: 15000 
 | 
					      timeout: 30000 
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -134,14 +129,6 @@ class AIService {
 | 
				
			|||||||
    return Math.ceil(text.length / 4);
 | 
					    return Math.ceil(text.length / 4);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  validatePromptLength(prompt: string, maxTokens: number = 35000): void {
 | 
					 | 
				
			||||||
    const estimatedTokens = this.estimateTokens(prompt);
 | 
					 | 
				
			||||||
    if (estimatedTokens > maxTokens) {
 | 
					 | 
				
			||||||
      console.warn('[AI-SERVICE] WARNING: Prompt may exceed model limits:', estimatedTokens);
 | 
					 | 
				
			||||||
      throw new Error(`Prompt too long: ${estimatedTokens} tokens (max: ${maxTokens})`);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  getConfig(): AIServiceConfig {
 | 
					  getConfig(): AIServiceConfig {
 | 
				
			||||||
    return { ...this.config };
 | 
					    return { ...this.config };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -85,7 +85,7 @@ let cachedData: ToolsData | null = null;
 | 
				
			|||||||
let cachedRandomizedData: ToolsData | null = null;
 | 
					let cachedRandomizedData: ToolsData | null = null;
 | 
				
			||||||
let cachedCompressedData: EnhancedCompressedToolsData | null = null;
 | 
					let cachedCompressedData: EnhancedCompressedToolsData | null = null;
 | 
				
			||||||
let lastRandomizationDate: string | null = null;
 | 
					let lastRandomizationDate: string | null = null;
 | 
				
			||||||
let dataVersion: string | null = null;
 | 
					let cachedToolsHash: string | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function seededRandom(seed: number): () => number {
 | 
					function seededRandom(seed: number): () => number {
 | 
				
			||||||
  let x = Math.sin(seed) * 10000;
 | 
					  let x = Math.sin(seed) * 10000;
 | 
				
			||||||
@ -110,17 +110,6 @@ function shuffleArray<T>(array: T[], randomFn: () => number): T[] {
 | 
				
			|||||||
  return shuffled;
 | 
					  return shuffled;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function generateDataVersion(data: any): string {
 | 
					 | 
				
			||||||
  const str = JSON.stringify(data, Object.keys(data).sort());
 | 
					 | 
				
			||||||
  let hash = 0;
 | 
					 | 
				
			||||||
  for (let i = 0; i < str.length; i++) {
 | 
					 | 
				
			||||||
    const char = str.charCodeAt(i);
 | 
					 | 
				
			||||||
    hash = ((hash << 5) - hash) + char;
 | 
					 | 
				
			||||||
    hash = hash & hash;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return Math.abs(hash).toString(36);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
async function loadRawData(): Promise<ToolsData> {
 | 
					async function loadRawData(): Promise<ToolsData> {
 | 
				
			||||||
  if (!cachedData) {
 | 
					  if (!cachedData) {
 | 
				
			||||||
    const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
 | 
					    const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
 | 
				
			||||||
@ -142,8 +131,9 @@ async function loadRawData(): Promise<ToolsData> {
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      dataVersion = generateDataVersion(cachedData);
 | 
					      const { getToolsFileHash } = await import('./hashUtils.js');
 | 
				
			||||||
      console.log(`[DATA SERVICE] Loaded enhanced data version: ${dataVersion}`);
 | 
					    cachedToolsHash = await getToolsFileHash();
 | 
				
			||||||
 | 
					    console.log(`[DATA SERVICE] Loaded data with hash: ${cachedToolsHash.slice(0, 12)}...`);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
    } catch (error) {
 | 
					    } catch (error) {
 | 
				
			||||||
      if (error instanceof z.ZodError) {
 | 
					      if (error instanceof z.ZodError) {
 | 
				
			||||||
@ -234,7 +224,7 @@ export async function getCompressedToolsDataForAI(): Promise<EnhancedCompressedT
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function getDataVersion(): string | null {
 | 
					export function getDataVersion(): string | null {
 | 
				
			||||||
  return dataVersion;
 | 
					  return cachedToolsHash;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function clearCache(): void {
 | 
					export function clearCache(): void {
 | 
				
			||||||
@ -242,7 +232,7 @@ export function clearCache(): void {
 | 
				
			|||||||
  cachedRandomizedData = null;
 | 
					  cachedRandomizedData = null;
 | 
				
			||||||
  cachedCompressedData = null;
 | 
					  cachedCompressedData = null;
 | 
				
			||||||
  lastRandomizationDate = null;
 | 
					  lastRandomizationDate = null;
 | 
				
			||||||
  dataVersion = null;
 | 
					  cachedToolsHash = null;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  console.log('[DATA SERVICE] Enhanced cache cleared');
 | 
					  console.log('[DATA SERVICE] Enhanced cache cleared');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -100,7 +100,8 @@ class EmbeddingsService {
 | 
				
			|||||||
      await fs.mkdir(path.dirname(this.embeddingsPath), { recursive: true });
 | 
					      await fs.mkdir(path.dirname(this.embeddingsPath), { recursive: true });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const toolsData = await getCompressedToolsDataForAI();
 | 
					      const toolsData = await getCompressedToolsDataForAI();
 | 
				
			||||||
      const currentDataHash = await this.hashToolsFile();
 | 
					      const { getToolsFileHash } = await import('./hashUtils.js');
 | 
				
			||||||
 | 
					      const currentDataHash = await getToolsFileHash();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const existing = await this.loadEmbeddings();
 | 
					      const existing = await this.loadEmbeddings();
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
@ -129,12 +130,6 @@ class EmbeddingsService {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private async hashToolsFile(): Promise<string> {
 | 
					 | 
				
			||||||
    const file = path.join(process.cwd(), 'src', 'data', 'tools.yaml');
 | 
					 | 
				
			||||||
    const raw = await fs.readFile(file, 'utf8');
 | 
					 | 
				
			||||||
    return crypto.createHash('sha256').update(raw).digest('hex');
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  private async loadEmbeddings(): Promise<EmbeddingsDatabase | null> {
 | 
					  private async loadEmbeddings(): Promise<EmbeddingsDatabase | null> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const data = await fs.readFile(this.embeddingsPath, 'utf8');
 | 
					      const data = await fs.readFile(this.embeddingsPath, 'utf8');
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										20
									
								
								src/utils/hashUtils.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/utils/hashUtils.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
				
			|||||||
 | 
					// src/utils/hashUtils.ts
 | 
				
			||||||
 | 
					import { promises as fs } from 'fs';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import crypto from 'crypto';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export async function getToolsFileHash(): Promise<string> {
 | 
				
			||||||
 | 
					  const file = path.join(process.cwd(), 'src', 'data', 'tools.yaml');
 | 
				
			||||||
 | 
					  const raw = await fs.readFile(file, 'utf8');
 | 
				
			||||||
 | 
					  return crypto.createHash('sha256').update(raw).digest('hex');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function getToolsFileHashSync(): string | null {
 | 
				
			||||||
 | 
					  try {
 | 
				
			||||||
 | 
					    const file = path.join(process.cwd(), 'src', 'data', 'tools.yaml');
 | 
				
			||||||
 | 
					    const raw = require('fs').readFileSync(file, 'utf8');
 | 
				
			||||||
 | 
					    return crypto.createHash('sha256').update(raw).digest('hex');
 | 
				
			||||||
 | 
					  } catch {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -38,7 +38,6 @@ export interface SelectionContext {
 | 
				
			|||||||
export interface ToolSelectionResult {
 | 
					export interface ToolSelectionResult {
 | 
				
			||||||
  selectedTools: any[];
 | 
					  selectedTools: any[];
 | 
				
			||||||
  selectedConcepts: any[];
 | 
					  selectedConcepts: any[];
 | 
				
			||||||
  //selectionMethod: string;
 | 
					 | 
				
			||||||
  confidence: number;
 | 
					  confidence: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -84,13 +83,11 @@ class ToolSelector {
 | 
				
			|||||||
    domains: any[];
 | 
					    domains: any[];
 | 
				
			||||||
    phases: any[];
 | 
					    phases: any[];
 | 
				
			||||||
    'domain-agnostic-software': any[];
 | 
					    'domain-agnostic-software': any[];
 | 
				
			||||||
    //selectionMethod: string;
 | 
					 | 
				
			||||||
  }> {
 | 
					  }> {
 | 
				
			||||||
    console.log('[TOOL-SELECTOR] Getting intelligent candidates for query');
 | 
					    console.log('[TOOL-SELECTOR] Getting intelligent candidates for query');
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    let candidateTools: any[] = [];
 | 
					    let candidateTools: any[] = [];
 | 
				
			||||||
    let candidateConcepts: any[] = [];
 | 
					    let candidateConcepts: any[] = [];
 | 
				
			||||||
    //let selectionMethod = 'unknown';
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    context.embeddingsSimilarities.clear();
 | 
					    context.embeddingsSimilarities.clear();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -133,23 +130,19 @@ class ToolSelector {
 | 
				
			|||||||
    if (similarTools.length >= this.config.embeddingsMinTools && reductionRatio <= this.config.embeddingsMaxReductionRatio) {
 | 
					    if (similarTools.length >= this.config.embeddingsMinTools && reductionRatio <= this.config.embeddingsMaxReductionRatio) {
 | 
				
			||||||
      candidateTools = similarTools;
 | 
					      candidateTools = similarTools;
 | 
				
			||||||
      candidateConcepts = similarConcepts;
 | 
					      candidateConcepts = similarConcepts;
 | 
				
			||||||
      //selectionMethod = 'embeddings_candidates';
 | 
					 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      console.log('[TOOL-SELECTOR] Using embeddings filtering:', totalAvailableTools, '→', similarTools.length, 'tools');
 | 
					      console.log('[TOOL-SELECTOR] Using embeddings filtering:', totalAvailableTools, '→', similarTools.length, 'tools');
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      console.log('[TOOL-SELECTOR] Embeddings filtering insufficient, using full dataset');
 | 
					      console.log('[TOOL-SELECTOR] Embeddings filtering insufficient, using full dataset');
 | 
				
			||||||
      candidateTools = toolsData.tools;
 | 
					      candidateTools = toolsData.tools;
 | 
				
			||||||
      candidateConcepts = toolsData.concepts;
 | 
					      candidateConcepts = toolsData.concepts;
 | 
				
			||||||
      //selectionMethod = 'full_dataset';
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    const selection = await this.performAISelection(
 | 
					    const selection = await this.performAISelection(
 | 
				
			||||||
      userQuery,
 | 
					      userQuery,
 | 
				
			||||||
      candidateTools,
 | 
					      candidateTools,
 | 
				
			||||||
      candidateConcepts,
 | 
					      candidateConcepts,
 | 
				
			||||||
      mode,
 | 
					      mode,
 | 
				
			||||||
      //selectionMethod,
 | 
					 | 
				
			||||||
      context
 | 
					      context
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@ -158,8 +151,7 @@ class ToolSelector {
 | 
				
			|||||||
      concepts: selection.selectedConcepts,
 | 
					      concepts: selection.selectedConcepts,
 | 
				
			||||||
      domains: toolsData.domains,
 | 
					      domains: toolsData.domains,
 | 
				
			||||||
      phases: toolsData.phases,
 | 
					      phases: toolsData.phases,
 | 
				
			||||||
      'domain-agnostic-software': toolsData['domain-agnostic-software'],
 | 
					      'domain-agnostic-software': toolsData['domain-agnostic-software']
 | 
				
			||||||
      //selectionMethod
 | 
					 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -206,8 +198,6 @@ class ToolSelector {
 | 
				
			|||||||
    const basePrompt = getPrompt('toolSelection', mode, userQuery, this.config.maxSelectedItems);
 | 
					    const basePrompt = getPrompt('toolSelection', mode, userQuery, this.config.maxSelectedItems);
 | 
				
			||||||
    const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
 | 
					    const prompt = getPrompt('toolSelectionWithData', basePrompt, toolsToSend, conceptsToSend);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    aiService.validatePromptLength(prompt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    console.log('[TOOL-SELECTOR] Sending to AI:',
 | 
					    console.log('[TOOL-SELECTOR] Sending to AI:',
 | 
				
			||||||
      toolsToSend.filter((t: any) => t.type === 'method').length, 'methods,',
 | 
					      toolsToSend.filter((t: any) => t.type === 'method').length, 'methods,',
 | 
				
			||||||
      toolsToSend.filter((t: any) => t.type === 'software').length, 'software,',
 | 
					      toolsToSend.filter((t: any) => t.type === 'software').length, 'software,',
 | 
				
			||||||
@ -215,7 +205,7 @@ class ToolSelector {
 | 
				
			|||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const response = await aiService.callAI(prompt, { maxTokens: 32768 });
 | 
					      const response = await aiService.callAI(prompt);
 | 
				
			||||||
      const result = JSONParser.safeParseJSON(response.content, null);
 | 
					      const result = JSONParser.safeParseJSON(response.content, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
 | 
					      if (!result || !Array.isArray(result.selectedTools) || !Array.isArray(result.selectedConcepts)) {
 | 
				
			||||||
@ -256,7 +246,6 @@ class ToolSelector {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
  async selectToolsForPhase(
 | 
					  async selectToolsForPhase(
 | 
				
			||||||
    userQuery: string,
 | 
					    userQuery: string,
 | 
				
			||||||
    phase: any,
 | 
					    phase: any,
 | 
				
			||||||
@ -278,7 +267,7 @@ class ToolSelector {
 | 
				
			|||||||
    const prompt = getPrompt('phaseToolSelection', userQuery, phase, availableTools);
 | 
					    const prompt = getPrompt('phaseToolSelection', userQuery, phase, availableTools);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
      const response = await aiService.callMicroTaskAI(prompt, 1000);
 | 
					      const response = await aiService.callMicroTaskAI(prompt);
 | 
				
			||||||
      const selections = JSONParser.safeParseJSON(response.content, []);
 | 
					      const selections = JSONParser.safeParseJSON(response.content, []);
 | 
				
			||||||
      
 | 
					      
 | 
				
			||||||
      if (Array.isArray(selections)) {
 | 
					      if (Array.isArray(selections)) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user