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