embeddings-1 #2
@ -215,6 +215,9 @@ const domainAgnosticSoftware = data['domain-agnostic-software'] || [];
|
|||||||
// SIMPLIFIED AI QUERY INTERFACE - CONSOLIDATED & MAINTAINABLE
|
// SIMPLIFIED AI QUERY INTERFACE - CONSOLIDATED & MAINTAINABLE
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
|
// Enhanced AI Interface JavaScript - Fix for text rendering issues in AIQueryInterface.astro
|
||||||
|
// This code replaces the existing <script> section in AIQueryInterface.astro
|
||||||
|
|
||||||
class AIQueryInterface {
|
class AIQueryInterface {
|
||||||
constructor() {
|
constructor() {
|
||||||
this.currentMode = 'workflow';
|
this.currentMode = 'workflow';
|
||||||
@ -368,9 +371,7 @@ class AIQueryInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// [Previous methods remain the same until displayResults...]
|
||||||
// INPUT HANDLING & SMART PROMPTING
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
handleInputChange() {
|
handleInputChange() {
|
||||||
this.updateCharacterCount();
|
this.updateCharacterCount();
|
||||||
@ -578,9 +579,7 @@ class AIQueryInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// [Queue monitoring methods remain the same...]
|
||||||
// QUEUE MONITORING
|
|
||||||
// ===================================================================
|
|
||||||
|
|
||||||
startQueueMonitoring(taskId) {
|
startQueueMonitoring(taskId) {
|
||||||
if (this.elements.queueStatus) {
|
if (this.elements.queueStatus) {
|
||||||
@ -712,7 +711,7 @@ class AIQueryInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// RESULTS DISPLAY
|
// RESULTS DISPLAY - ENHANCED with proper text formatting
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
displayResults(recommendation, originalQuery) {
|
displayResults(recommendation, originalQuery) {
|
||||||
@ -757,7 +756,6 @@ class AIQueryInterface {
|
|||||||
${this.renderBackgroundKnowledge(recommendation.background_knowledge)}
|
${this.renderBackgroundKnowledge(recommendation.background_knowledge)}
|
||||||
${this.renderWorkflowPhases(toolsByPhase, phaseOrder, phaseNames)}
|
${this.renderWorkflowPhases(toolsByPhase, phaseOrder, phaseNames)}
|
||||||
${this.renderWorkflowSuggestion(recommendation.workflow_suggestion)}
|
${this.renderWorkflowSuggestion(recommendation.workflow_suggestion)}
|
||||||
${this.renderAdditionalNotes(recommendation.additional_notes)}
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -789,6 +787,7 @@ class AIQueryInterface {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ENHANCED: Fixed text rendering to prevent markdown/list interpretation
|
||||||
renderContextualAnalysis(recommendation, mode) {
|
renderContextualAnalysis(recommendation, mode) {
|
||||||
let html = '';
|
let html = '';
|
||||||
|
|
||||||
@ -799,7 +798,7 @@ class AIQueryInterface {
|
|||||||
<h4 style="margin: 0 0 1rem 0; color: var(--color-primary);">
|
<h4 style="margin: 0 0 1rem 0; color: var(--color-primary);">
|
||||||
${mode === 'workflow' ? 'Szenario-Analyse' : 'Problem-Analyse'}
|
${mode === 'workflow' ? 'Szenario-Analyse' : 'Problem-Analyse'}
|
||||||
</h4>
|
</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(analysisField)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(analysisField)}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -810,7 +809,7 @@ class AIQueryInterface {
|
|||||||
<h4 style="margin: 0 0 1rem 0; color: var(--color-accent);">
|
<h4 style="margin: 0 0 1rem 0; color: var(--color-accent);">
|
||||||
${mode === 'workflow' ? 'Untersuchungsansatz' : 'Lösungsansatz'}
|
${mode === 'workflow' ? 'Untersuchungsansatz' : 'Lösungsansatz'}
|
||||||
</h4>
|
</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.investigation_approach)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.investigation_approach)}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -821,7 +820,7 @@ class AIQueryInterface {
|
|||||||
<h4 style="margin: 0 0 1rem 0; color: var(--color-warning);">
|
<h4 style="margin: 0 0 1rem 0; color: var(--color-warning);">
|
||||||
${mode === 'workflow' ? 'Kritische Überlegungen' : 'Wichtige Voraussetzungen'}
|
${mode === 'workflow' ? 'Kritische Überlegungen' : 'Wichtige Voraussetzungen'}
|
||||||
</h4>
|
</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.critical_considerations)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.critical_considerations)}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -841,9 +840,9 @@ class AIQueryInterface {
|
|||||||
</button>
|
</button>
|
||||||
<span class="badge" style="background-color: var(--color-concept); color: white; font-size: 0.625rem;">Hintergrundwissen</span>
|
<span class="badge" style="background-color: var(--color-concept); color: white; font-size: 0.625rem;">Hintergrundwissen</span>
|
||||||
</div>
|
</div>
|
||||||
<p style="margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary);">
|
<div style="margin: 0; font-size: 0.8125rem; line-height: 1.5; color: var(--color-text-secondary); white-space: pre-wrap; word-wrap: break-word;">
|
||||||
${this.escapeHtml(concept.relevance)}
|
${this.sanitizeText(concept.relevance)}
|
||||||
</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
`).join('');
|
`).join('');
|
||||||
|
|
||||||
@ -898,8 +897,8 @@ class AIQueryInterface {
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic;">
|
<div class="tool-rec-justification" style="background-color: var(--color-bg-tertiary); padding: 0.75rem; border-radius: 0.375rem; border-left: 3px solid var(--color-primary); margin: 0.75rem 0; font-style: italic; white-space: pre-wrap; word-wrap: break-word;">
|
||||||
"${this.escapeHtml(tool.recommendation.justification)}"
|
"${this.sanitizeText(tool.recommendation.justification)}"
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style="font-size: 0.75rem; color: var(--color-text-secondary);">
|
<div style="font-size: 0.75rem; color: var(--color-text-secondary);">
|
||||||
@ -949,11 +948,11 @@ class AIQueryInterface {
|
|||||||
|
|
||||||
<div style="margin-bottom: 1.5rem;">
|
<div style="margin-bottom: 1.5rem;">
|
||||||
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-accent);">Warum diese Methode?</h4>
|
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-accent);">Warum diese Methode?</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.detailed_explanation)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.detailed_explanation)}</div>
|
||||||
|
|
||||||
${recommendation.implementation_approach ? `
|
${recommendation.implementation_approach ? `
|
||||||
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-primary);">Anwendungsansatz</h4>
|
<h4 style="margin: 0.8rem 0 0.75rem 0; color: var(--color-primary);">Anwendungsansatz</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(recommendation.implementation_approach)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(recommendation.implementation_approach)}</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -973,7 +972,7 @@ class AIQueryInterface {
|
|||||||
<div style="background-color: var(--color-oss-bg); padding: 1rem; border-radius: 0.5rem; border-left: 3px solid var(--color-accent);">
|
<div style="background-color: var(--color-oss-bg); padding: 1rem; border-radius: 0.5rem; border-left: 3px solid var(--color-accent);">
|
||||||
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-accent); font-size: 0.875rem;">✓ Vorteile</h5>
|
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-accent); font-size: 0.875rem;">✓ Vorteile</h5>
|
||||||
<ul style="margin: 0; padding-left: 1rem;">
|
<ul style="margin: 0; padding-left: 1rem;">
|
||||||
${pros.map(pro => `<li style="margin-bottom: 0.25rem;">${this.escapeHtml(pro)}</li>`).join('')}
|
${pros.map(pro => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(pro)}</li>`).join('')}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
@ -981,7 +980,7 @@ class AIQueryInterface {
|
|||||||
<div style="background-color: var(--color-hosted-bg); padding: 1rem; border-radius: 0.5rem; border-left: 3px solid var(--color-warning);">
|
<div style="background-color: var(--color-hosted-bg); padding: 1rem; border-radius: 0.5rem; border-left: 3px solid var(--color-warning);">
|
||||||
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-warning); font-size: 0.875rem;">✗ Nachteile</h5>
|
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-warning); font-size: 0.875rem;">✗ Nachteile</h5>
|
||||||
<ul style="margin: 0; padding-left: 1rem;">
|
<ul style="margin: 0; padding-left: 1rem;">
|
||||||
${cons.map(con => `<li style="margin-bottom: 0.25rem;">${this.escapeHtml(con)}</li>`).join('')}
|
${cons.map(con => `<li style="margin-bottom: 0.25rem;">${this.sanitizeText(con)}</li>`).join('')}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
` : ''}
|
` : ''}
|
||||||
@ -1006,7 +1005,7 @@ class AIQueryInterface {
|
|||||||
return `
|
return `
|
||||||
<div style="background-color: var(--color-bg-secondary); padding: 1rem; border-radius: 0.5rem; margin-bottom: 1rem;">
|
<div style="background-color: var(--color-bg-secondary); padding: 1rem; border-radius: 0.5rem; margin-bottom: 1rem;">
|
||||||
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-text-secondary); font-size: 0.875rem;">Alternative Ansätze</h5>
|
<h5 style="margin: 0 0 0.5rem 0; color: var(--color-text-secondary); font-size: 0.875rem;">Alternative Ansätze</h5>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(alternatives)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(alternatives)}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -1017,18 +1016,7 @@ class AIQueryInterface {
|
|||||||
return `
|
return `
|
||||||
<div class="card" style="margin-top: 2rem; border-left: 4px solid var(--color-accent);">
|
<div class="card" style="margin-top: 2rem; border-left: 4px solid var(--color-accent);">
|
||||||
<h4 style="margin: 0 0 1rem 0; color: var(--color-accent);">Workflow-Empfehlung</h4>
|
<h4 style="margin: 0 0 1rem 0; color: var(--color-accent);">Workflow-Empfehlung</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(suggestion)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(suggestion)}</div>
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderAdditionalNotes(notes) {
|
|
||||||
if (!notes) return '';
|
|
||||||
|
|
||||||
return `
|
|
||||||
<div class="card" style="margin-top: 1rem; background-color: var(--color-warning); color: white;">
|
|
||||||
<h4 style="margin: 0 0 1rem 0;">Wichtige Hinweise</h4>
|
|
||||||
<p style="margin: 0; line-height: 1.6; color: white;">${this.escapeHtml(notes)}</p>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -1039,7 +1027,7 @@ class AIQueryInterface {
|
|||||||
return `
|
return `
|
||||||
<div class="card" style="margin-top: 2rem; background-color: var(--color-bg-secondary); border-left: 4px solid var(--color-text-secondary);">
|
<div class="card" style="margin-top: 2rem; background-color: var(--color-bg-secondary); border-left: 4px solid var(--color-text-secondary);">
|
||||||
<h4 style="margin: 0 0 1rem 0; color: var(--color-text-secondary);">Zusätzliche Überlegungen</h4>
|
<h4 style="margin: 0 0 1rem 0; color: var(--color-text-secondary);">Zusätzliche Überlegungen</h4>
|
||||||
<p style="margin: 0; line-height: 1.6;">${this.escapeHtml(considerations)}</p>
|
<div style="margin: 0; line-height: 1.6; white-space: pre-wrap; word-wrap: break-word;">${this.sanitizeText(considerations)}</div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -1065,9 +1053,37 @@ class AIQueryInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
// UTILITY METHODS
|
// ENHANCED UTILITY METHODS with proper text sanitization
|
||||||
// ===================================================================
|
// ===================================================================
|
||||||
|
|
||||||
|
// CRITICAL: Sanitize text to prevent markdown interpretation
|
||||||
|
sanitizeText(text) {
|
||||||
|
if (typeof text !== 'string') return '';
|
||||||
|
|
||||||
|
// Remove/escape potential markdown and HTML
|
||||||
|
return text
|
||||||
|
// Remove markdown headers
|
||||||
|
.replace(/^#{1,6}\s+/gm, '')
|
||||||
|
// Remove markdown lists (bullet points and numbered)
|
||||||
|
.replace(/^\s*[-*+]\s+/gm, '')
|
||||||
|
.replace(/^\s*\d+\.\s+/gm, '')
|
||||||
|
// Remove markdown bold/italic
|
||||||
|
.replace(/\*\*(.+?)\*\*/g, '$1')
|
||||||
|
.replace(/\*(.+?)\*/g, '$1')
|
||||||
|
.replace(/__(.+?)__/g, '$1')
|
||||||
|
.replace(/_(.+?)_/g, '$1')
|
||||||
|
// Remove markdown links
|
||||||
|
.replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
|
||||||
|
// Remove code blocks
|
||||||
|
.replace(/```[\s\S]*?```/g, '[CODE BLOCK]')
|
||||||
|
.replace(/`([^`]+)`/g, '$1')
|
||||||
|
// Remove HTML tags
|
||||||
|
.replace(/<[^>]+>/g, '')
|
||||||
|
// Clean up excessive whitespace but preserve paragraphs
|
||||||
|
.replace(/\n\s*\n\s*\n/g, '\n\n')
|
||||||
|
.trim();
|
||||||
|
}
|
||||||
|
|
||||||
isToolHosted(tool) {
|
isToolHosted(tool) {
|
||||||
return tool.projectUrl !== undefined &&
|
return tool.projectUrl !== undefined &&
|
||||||
tool.projectUrl !== null &&
|
tool.projectUrl !== null &&
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// src/pages/api/ai/enhance-input.ts
|
// src/pages/api/ai/enhance-input.ts - ENHANCED with forensics methodology
|
||||||
import type { APIRoute } from 'astro';
|
import type { APIRoute } from 'astro';
|
||||||
import { withAPIAuth } from '../../../utils/auth.js';
|
import { withAPIAuth } from '../../../utils/auth.js';
|
||||||
import { apiError, apiServerError, createAuthErrorResponse } from '../../../utils/api.js';
|
import { apiError, apiServerError, createAuthErrorResponse } from '../../../utils/api.js';
|
||||||
@ -63,31 +63,31 @@ function cleanupExpiredRateLimits() {
|
|||||||
setInterval(cleanupExpiredRateLimits, 5 * 60 * 1000);
|
setInterval(cleanupExpiredRateLimits, 5 * 60 * 1000);
|
||||||
|
|
||||||
function createEnhancementPrompt(input: string): string {
|
function createEnhancementPrompt(input: string): string {
|
||||||
return `Du bist eine KI für digitale Forensik-Anfragen. Der Nutzer beschreibt ein forensisches Szenario oder Problem. Analysiere die Eingabe auf Vollständigkeit und Klarheit.
|
return `Sie sind ein DFIR-Experte mit Spezialisierung auf forensische Methodik. Ein Nutzer beschreibt ein forensisches Szenario oder Problem. Analysieren Sie die Eingabe auf Vollständigkeit für eine wissenschaftlich fundierte forensische Untersuchung.
|
||||||
|
|
||||||
ANALYSIERE DIESE KATEGORIEN:
|
ANALYSIEREN SIE DIESE FORENSISCHEN KATEGORIEN:
|
||||||
1. **Vorfalltyp**: Was ist passiert? (Malware, Datendiebstahl, Compliance-Verstoß, etc.)
|
1. **Incident Context**: Was ist passiert? Welche Angriffsvektoren oder technischen Probleme liegen vor?
|
||||||
2. **Betroffene Systeme**: Welche Technologien/Plattformen? (Windows, Linux, Mobile, Cloud, etc.)
|
2. **Affected Systems**: Welche spezifischen Technologien/Plattformen sind betroffen? (Windows/Linux/ICS/SCADA/Mobile/Cloud/Network Infrastructure)
|
||||||
3. **Verfügbare Datenquellen**: Was kann untersucht werden? (Logs, Images, Memory Dumps, etc.)
|
3. **Available Evidence**: Welche forensischen Datenquellen stehen zur Verfügung? (RAM-Dumps, Disk-Images, Log-Files, Network-Captures, Registry-Hives)
|
||||||
4. **Untersuchungsziel**: Was soll erreicht werden? (IOCs finden, Timeline erstellen, etc.)
|
4. **Investigation Objectives**: Was soll erreicht werden? (IOC-Extraktion, Timeline-Rekonstruktion, Attribution, Impact-Assessment)
|
||||||
5. **Zeitrahmen & Dringlichkeit**: Wann ist etwas passiert? Wie dringend?
|
5. **Timeline Constraints**: Wie zeitkritisch ist die Untersuchung?
|
||||||
6. **Ressourcen & Constraints**: Budget, Skills, Tools, rechtliche Aspekte
|
6. **Legal & Compliance**: Rechtliche Anforderungen, Chain of Custody, Compliance-Rahmen (DSGVO, sector-specific regulations)
|
||||||
7. **Beweisziele**: Dokumentation, Gerichtsverfahren, interne Aufklärung?
|
7. **Technical Constraints**: Verfügbare Ressourcen, Skills, Infrastrukturbeschränkungen
|
||||||
|
|
||||||
WENN die Beschreibung vollständig und spezifisch ist: Gib eine leere Liste [] zurück.
|
WENN die Beschreibung alle kritischen forensischen Aspekte abdeckt: Geben Sie eine leere Liste [] zurück.
|
||||||
|
|
||||||
WENN wichtige Details fehlen: Formuliere 2-3 präzise Fragen, die die kritischsten Lücken schließen. Fokussiere auf Details, die die Tool-/Methoden-Auswahl stark beeinflussen.
|
WENN wichtige forensische Details fehlen: Formulieren Sie 2-3 präzise Fragen, die die kritischsten Lücken für eine wissenschaftlich fundierte forensische Analyse schließen.
|
||||||
|
|
||||||
FRAGE-QUALITÄT:
|
QUALITÄTSKRITERIEN FÜR FRAGEN:
|
||||||
- Spezifisch, nicht allgemein (❌ "Mehr Details?" ✅ "Welche Betriebssysteme sind betroffen?")
|
- Forensisch spezifisch, nicht allgemein (❌ "Mehr Details?" ✅ "Welche forensischen Artefakte (RAM-Dumps, Disk-Images, Logs) stehen zur Verfügung?")
|
||||||
- Handlungsrelevant (❌ "Wann passierte das?" ✅ "Haben Sie Logs aus der Vorfallzeit verfügbar?")
|
- Methodisch relevant (❌ "Wann passierte das?" ✅ "Liegen Log-Dateien aus dem Incident-Zeitraum vor, und welche Retention-Policy gilt?")
|
||||||
- Priorisiert nach Wichtigkeit für die forensische Analyse
|
- Priorisiert nach Auswirkung auf die forensische Untersuchungsqualität
|
||||||
|
|
||||||
ANTWORTFORMAT (NUR JSON):
|
ANTWORTFORMAT (NUR JSON, KEIN ZUSÄTZLICHER TEXT):
|
||||||
[
|
[
|
||||||
"Spezifische Frage 1?",
|
"Forensisch spezifische Frage 1?",
|
||||||
"Spezifische Frage 2?",
|
"Forensisch spezifische Frage 2?",
|
||||||
"Spezifische Frage 3?"
|
"Forensisch spezifische Frage 3?"
|
||||||
]
|
]
|
||||||
|
|
||||||
NUTZER-EINGABE:
|
NUTZER-EINGABE:
|
||||||
@ -139,7 +139,11 @@ export const POST: APIRoute = async ({ request }) => {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
max_tokens: 300,
|
max_tokens: 300,
|
||||||
temperature: 0.7
|
temperature: 0.7,
|
||||||
|
// Enhanced: Better parameters for consistent forensics output
|
||||||
|
top_p: 0.9,
|
||||||
|
frequency_penalty: 0.2,
|
||||||
|
presence_penalty: 0.1
|
||||||
})
|
})
|
||||||
}), taskId);
|
}), taskId);
|
||||||
|
|
||||||
@ -167,14 +171,20 @@ export const POST: APIRoute = async ({ request }) => {
|
|||||||
throw new Error('Response is not an array');
|
throw new Error('Response is not an array');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enhanced validation and cleaning
|
// Enhanced validation and cleaning for forensics context
|
||||||
questions = questions
|
questions = questions
|
||||||
.filter(q => typeof q === 'string' && q.length > 10 && q.length < 150) // More reasonable length limits
|
.filter(q => typeof q === 'string' && q.length > 20 && q.length < 200) // More appropriate length for forensics questions
|
||||||
.filter(q => q.includes('?')) // Must be a question
|
.filter(q => q.includes('?')) // Must be a question
|
||||||
|
.filter(q => {
|
||||||
|
// Enhanced: Filter for forensics-relevant questions
|
||||||
|
const forensicsTerms = ['forensisch', 'log', 'dump', 'image', 'artefakt', 'evidence', 'incident', 'system', 'netzwerk', 'zeitraum', 'verfügbar'];
|
||||||
|
const lowerQ = q.toLowerCase();
|
||||||
|
return forensicsTerms.some(term => lowerQ.includes(term));
|
||||||
|
})
|
||||||
.map(q => q.trim())
|
.map(q => q.trim())
|
||||||
.slice(0, 3); // Max 3 questions
|
.slice(0, 3); // Max 3 questions
|
||||||
|
|
||||||
// If no valid questions, return empty array (means input is complete)
|
// If no valid forensics questions, return empty array (means input is complete)
|
||||||
if (questions.length === 0) {
|
if (questions.length === 0) {
|
||||||
questions = [];
|
questions = [];
|
||||||
}
|
}
|
||||||
@ -185,7 +195,7 @@ export const POST: APIRoute = async ({ request }) => {
|
|||||||
questions = [];
|
questions = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[AI Enhancement] User: ${userId}, Questions: ${questions.length}, Input length: ${sanitizedInput.length}`);
|
console.log(`[AI Enhancement] User: ${userId}, Forensics Questions: ${questions.length}, Input length: ${sanitizedInput.length}`);
|
||||||
|
|
||||||
return new Response(JSON.stringify({
|
return new Response(JSON.stringify({
|
||||||
success: true,
|
success: true,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// src/utils/aiPipeline.ts - REDESIGNED with micro-task architecture
|
// src/utils/aiPipeline.ts - ENHANCED with improved forensics prompts
|
||||||
import { getCompressedToolsDataForAI } from './dataService.js';
|
import { getCompressedToolsDataForAI } from './dataService.js';
|
||||||
import { embeddingsService, type EmbeddingData } from './embeddings.js';
|
import { embeddingsService, type EmbeddingData } from './embeddings.js';
|
||||||
|
|
||||||
@ -72,8 +72,6 @@ class MicroTaskAIPipeline {
|
|||||||
this.maxSelectedItems = parseInt(process.env.AI_MAX_SELECTED_ITEMS || '15', 10);
|
this.maxSelectedItems = parseInt(process.env.AI_MAX_SELECTED_ITEMS || '15', 10);
|
||||||
this.embeddingCandidates = parseInt(process.env.AI_EMBEDDING_CANDIDATES || '30', 10);
|
this.embeddingCandidates = parseInt(process.env.AI_EMBEDDING_CANDIDATES || '30', 10);
|
||||||
this.similarityThreshold = parseFloat(process.env.AI_SIMILARITY_THRESHOLD || '0.3');
|
this.similarityThreshold = parseFloat(process.env.AI_SIMILARITY_THRESHOLD || '0.3');
|
||||||
|
|
||||||
// New: Micro-task delay to respect rate limits
|
|
||||||
this.microTaskDelay = parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10);
|
this.microTaskDelay = parseInt(process.env.AI_MICRO_TASK_DELAY_MS || '500', 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +101,11 @@ class MicroTaskAIPipeline {
|
|||||||
model: this.analyzerConfig.model,
|
model: this.analyzerConfig.model,
|
||||||
messages: [{ role: 'user', content: prompt }],
|
messages: [{ role: 'user', content: prompt }],
|
||||||
max_tokens: maxTokens,
|
max_tokens: maxTokens,
|
||||||
temperature: 0.2 // Lower temperature for consistency
|
temperature: 0.2,
|
||||||
|
// Enhanced: Better parameters for consistent forensics output
|
||||||
|
top_p: 0.9,
|
||||||
|
frequency_penalty: 0.1,
|
||||||
|
presence_penalty: 0.1
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -137,23 +139,29 @@ class MicroTaskAIPipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 1: Scenario/Problem Analysis
|
// ENHANCED MICRO-TASK 1: Scenario/Problem Analysis with improved forensics methodology
|
||||||
private async analyzeScenario(context: AnalysisContext): Promise<MicroTaskResult> {
|
private async analyzeScenario(context: AnalysisContext): Promise<MicroTaskResult> {
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
|
|
||||||
const prompt = `Du bist ein DFIR-Experte. Analysiere das folgende ${isWorkflow ? 'forensische Szenario' : 'spezifische Problem'} detailliert.
|
const prompt = `Sie sind ein erfahrener DFIR-Experte mit Spezialisierung auf Objektivität und wissenschaftliche Methoden. Analysieren Sie das folgende ${isWorkflow ? 'forensische Szenario' : 'technische Problem'}.
|
||||||
|
|
||||||
${isWorkflow ? 'FORENSISCHES SZENARIO' : 'SPEZIFISCHES PROBLEM'}: "${context.userQuery}"
|
${isWorkflow ? 'FORENSISCHES SZENARIO' : 'TECHNISCHES PROBLEM'}: "${context.userQuery}"
|
||||||
|
|
||||||
|
Führen Sie eine systematische ${isWorkflow ? 'Szenario-Analyse' : 'Problem-Analyse'} durch und berücksichtigen Sie dabei:
|
||||||
|
|
||||||
Führe eine ${isWorkflow ? 'Szenario-Analyse' : 'Problem-Analyse'} durch:
|
|
||||||
${isWorkflow ?
|
${isWorkflow ?
|
||||||
'- Identifiziere die Art des Vorfalls\n- Erkenne betroffene Systeme und Technologien\n- Bestimme potentielle Bedrohungen\n- Analysiere forensische Herausforderungen' :
|
`- Angriffsvektoren und Bedrohungsmodellierung nach MITRE ATT&CK
|
||||||
'- Identifiziere technische Anforderungen\n- Erkenne spezifische Herausforderungen\n- Bestimme benötigte Fähigkeiten\n- Analysiere Erfolgsfaktoren'
|
- Betroffene Systeme und kritische Infrastrukturen (ICS/SCADA, AD, Endpoints)
|
||||||
|
- Zeitkritische Faktoren und Beweiserhaltung (Chain of Custody)
|
||||||
|
- Forensische Artefakte und Datenquellen (Logs, Memory, Disk, Network)` :
|
||||||
|
`- Spezifische forensische Herausforderungen
|
||||||
|
- Verfügbare Datenquellen und deren Integrität
|
||||||
|
- Methodische Anforderungen für rechtssichere Analyse`
|
||||||
}
|
}
|
||||||
|
|
||||||
Antworte nur mit der Analyse als Fließtext (keine Listen), maximal 150 Wörter.`;
|
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen, Aufzählungen oder Markdown-Formatierung. Verwenden Sie Fachterminologie und fundierte Methodik. Maximum 150 Wörter.`;
|
||||||
|
|
||||||
const result = await this.callMicroTaskAI(prompt, 200);
|
const result = await this.callMicroTaskAI(prompt, 220);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
if (isWorkflow) {
|
if (isWorkflow) {
|
||||||
@ -166,25 +174,31 @@ Antworte nur mit der Analyse als Fließtext (keine Listen), maximal 150 Wörter.
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 2: Investigation/Solution Approach
|
// ENHANCED MICRO-TASK 2: Investigation/Solution Approach with forensics methodology
|
||||||
private async generateApproach(context: AnalysisContext): Promise<MicroTaskResult> {
|
private async generateApproach(context: AnalysisContext): Promise<MicroTaskResult> {
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
const analysis = isWorkflow ? context.scenarioAnalysis : context.problemAnalysis;
|
const analysis = isWorkflow ? context.scenarioAnalysis : context.problemAnalysis;
|
||||||
|
|
||||||
const prompt = `Basierend auf der vorherigen Analyse entwickle einen strategischen ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'}.
|
const prompt = `Basierend auf der Analyse entwickeln Sie einen fundierten ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'} nach NIST SP 800-86 Methodik.
|
||||||
|
|
||||||
VORHERIGE ANALYSE: "${analysis}"
|
FORENSISCHE ANALYSE: "${analysis}"
|
||||||
${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
|
${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
|
||||||
|
|
||||||
Entwickle einen ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'}:
|
Entwickeln Sie einen systematischen ${isWorkflow ? 'Untersuchungsansatz' : 'Lösungsansatz'} unter Berücksichtigung von:
|
||||||
|
|
||||||
${isWorkflow ?
|
${isWorkflow ?
|
||||||
'- Prioritäten für die Untersuchung\n- Reihenfolge der Phasen\n- Besondere Überlegungen für diesen Fall' :
|
`- Triage-Prioritäten nach forensischer Dringlichkeit (volatile vs. persistent evidence)
|
||||||
'- Optimale Herangehensweise\n- Prioritäten bei der Umsetzung\n- Anwendungsreihenfolge'
|
- Phasenabfolge nach NIST-Methodik (Collection → Examination → Analysis → Reporting)
|
||||||
|
- Kontaminationsvermeidung und forensische Isolierung` :
|
||||||
|
`- Methodik-Auswahl nach wissenschaftlichen Kriterien
|
||||||
|
- Validierung und Verifizierung der gewählten Ansätze
|
||||||
|
- Qualitätssicherung und Reproduzierbarkeit
|
||||||
|
- Integration in bestehende forensische Workflows`
|
||||||
}
|
}
|
||||||
|
|
||||||
Antworte nur mit dem Ansatz als Fließtext, maximal 150 Wörter.`;
|
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Verwenden Sie forensische Fachterminologie. Maximum 150 Wörter.`;
|
||||||
|
|
||||||
const result = await this.callMicroTaskAI(prompt, 200);
|
const result = await this.callMicroTaskAI(prompt, 220);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
context.investigationApproach = result.content;
|
context.investigationApproach = result.content;
|
||||||
@ -193,22 +207,31 @@ Antworte nur mit dem Ansatz als Fließtext, maximal 150 Wörter.`;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 3: Critical Considerations
|
// ENHANCED MICRO-TASK 3: Critical Considerations with forensics focus
|
||||||
private async generateCriticalConsiderations(context: AnalysisContext): Promise<MicroTaskResult> {
|
private async generateCriticalConsiderations(context: AnalysisContext): Promise<MicroTaskResult> {
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
|
|
||||||
const prompt = `Identifiziere ${isWorkflow ? 'kritische Überlegungen' : 'wichtige Voraussetzungen'} für diesen Fall.
|
const prompt = `Identifizieren Sie ${isWorkflow ? 'kritische forensische Überlegungen' : 'wichtige methodische Voraussetzungen'} für diesen Fall basierend auf bewährten DFIR-Praktiken.
|
||||||
|
|
||||||
${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
|
${isWorkflow ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
|
||||||
ANSATZ: "${context.investigationApproach}"
|
ANSATZ: "${context.investigationApproach}"
|
||||||
|
|
||||||
Identifiziere:
|
Berücksichtigen Sie folgende forensische Aspekte:
|
||||||
|
|
||||||
${isWorkflow ?
|
${isWorkflow ?
|
||||||
'- Zeitkritische Faktoren\n- Wichtige Sicherheitsaspekte\n- Besondere Vorsichtsmaßnahmen\n- Rechtliche Überlegungen' :
|
`- Time-sensitive evidence preservation (RAM, log rotation, network captures)
|
||||||
'- Wichtige Voraussetzungen\n- Potentielle Fallstricke\n- Warnungen bei der Anwendung\n- Erforderliche Vorkenntnisse'
|
- Chain of custody requirements und rechtliche Verwertbarkeit
|
||||||
|
- Incident containment vs. evidence preservation Dilemma
|
||||||
|
- Cross-contamination risks zwischen verschiedenen Systemen
|
||||||
|
- Privacy- und Compliance-Anforderungen (DSGVO, sector-specific regulations)` :
|
||||||
|
`- Tool-Validierung und Nachvollziehbarkeit
|
||||||
|
- False positive/negative Risiken bei der gewählten Methodik
|
||||||
|
- Methodische Limitationen und deren Auswirkungen
|
||||||
|
- Qualifikationsanforderungen für die Durchführung
|
||||||
|
- Dokumentations- und Reporting-Standards`
|
||||||
}
|
}
|
||||||
|
|
||||||
Antworte nur mit den Überlegungen als Fließtext, maximal 120 Wörter.`;
|
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 120 Wörter.`;
|
||||||
|
|
||||||
const result = await this.callMicroTaskAI(prompt, 180);
|
const result = await this.callMicroTaskAI(prompt, 180);
|
||||||
|
|
||||||
@ -219,7 +242,7 @@ Antworte nur mit den Überlegungen als Fließtext, maximal 120 Wörter.`;
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 4: Tool Selection (for workflow mode)
|
// ENHANCED MICRO-TASK 4: Tool Selection with forensics validation
|
||||||
private async selectToolsForPhase(context: AnalysisContext, phase: any): Promise<MicroTaskResult> {
|
private async selectToolsForPhase(context: AnalysisContext, phase: any): Promise<MicroTaskResult> {
|
||||||
const phaseTools = context.filteredData.tools.filter((tool: any) =>
|
const phaseTools = context.filteredData.tools.filter((tool: any) =>
|
||||||
tool.phases && tool.phases.includes(phase.id)
|
tool.phases && tool.phases.includes(phase.id)
|
||||||
@ -234,32 +257,37 @@ Antworte nur mit den Überlegungen als Fließtext, maximal 120 Wörter.`;
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const prompt = `Wähle 2-3 passende Tools für die Phase "${phase.name}" basierend auf dem Szenario.
|
const prompt = `Wählen Sie 2-3 Methoden/Tools für die Phase "${phase.name}" basierend auf objektiven, fallbezogenen Kriterien.
|
||||||
|
|
||||||
SZENARIO: "${context.userQuery}"
|
SZENARIO: "${context.userQuery}"
|
||||||
SZENARIO-ANALYSE: "${context.scenarioAnalysis}"
|
FORENSISCHE ANALYSE: "${context.scenarioAnalysis}"
|
||||||
|
|
||||||
VERFÜGBARE TOOLS FÜR ${phase.name.toUpperCase()}:
|
VERFÜGBARE TOOLS FÜR ${phase.name.toUpperCase()}:
|
||||||
${phaseTools.map((tool: any) => `- ${tool.name}: ${tool.description.slice(0, 100)}...`).join('\n')}
|
${phaseTools.map((tool: any) => `- ${tool.name}: ${tool.description.slice(0, 100)}...`).join('\n')}
|
||||||
|
|
||||||
Wähle 2-3 Tools aus und begründe knapp die Auswahl für dieses spezifische Szenario.
|
Wählen Sie Methoden/Tools nach folgenden forensischen Kriterien aus:
|
||||||
|
- Court admissibility und Chain of Custody Kompatibilität
|
||||||
|
- False positive/negative Raten bei ähnlichen Szenarien
|
||||||
|
- Integration in forensische Standard-Workflows
|
||||||
|
- Reproduzierbarkeit und Dokumentationsqualität
|
||||||
|
- Transparenter Untersuchungsprozess
|
||||||
|
- Objektivität
|
||||||
|
|
||||||
Antworte nur mit JSON:
|
Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format (kein zusätzlicher Text):
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"toolName": "Exakter Tool-Name",
|
"toolName": "Exakter Methoden/Tool-Name",
|
||||||
"priority": "high|medium|low",
|
"priority": "high|medium|low",
|
||||||
"justification": "Kurze Begründung warum für dieses Szenario geeignet"
|
"justification": "Objektive Begründung warum diese Methode/Tool für das spezifische Szenario besser geeignet ist als vergleichbare Methoden/Tools"
|
||||||
}
|
}
|
||||||
]`;
|
]`;
|
||||||
|
|
||||||
const result = await this.callMicroTaskAI(prompt, 400);
|
const result = await this.callMicroTaskAI(prompt, 450);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
try {
|
try {
|
||||||
const selections = JSON.parse(result.content.replace(/^```json\s*/i, '').replace(/\s*```\s*$/g, '').trim());
|
const selections = JSON.parse(result.content.replace(/^```json\s*/i, '').replace(/\s*```\s*$/g, '').trim());
|
||||||
|
|
||||||
// Validate and store selections
|
|
||||||
const validSelections = selections.filter((sel: any) =>
|
const validSelections = selections.filter((sel: any) =>
|
||||||
phaseTools.some((tool: any) => tool.name === sel.toolName)
|
phaseTools.some((tool: any) => tool.name === sel.toolName)
|
||||||
);
|
);
|
||||||
@ -291,9 +319,9 @@ Antworte nur mit JSON:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 5: Tool Evaluation (for tool mode)
|
// ENHANCED MICRO-TASK 5: Tool Evaluation with scientific methodology
|
||||||
private async evaluateSpecificTool(context: AnalysisContext, tool: any, rank: number): Promise<MicroTaskResult> {
|
private async evaluateSpecificTool(context: AnalysisContext, tool: any, rank: number): Promise<MicroTaskResult> {
|
||||||
const prompt = `Bewerte dieses Tool detailliert für das spezifische Problem.
|
const prompt = `Bewerten Sie diese Methode/Tool fallbezogen für das spezifische Problem nach forensischen Qualitätskriterien.
|
||||||
|
|
||||||
PROBLEM: "${context.userQuery}"
|
PROBLEM: "${context.userQuery}"
|
||||||
PROBLEM-ANALYSE: "${context.problemAnalysis}"
|
PROBLEM-ANALYSE: "${context.problemAnalysis}"
|
||||||
@ -304,23 +332,22 @@ BESCHREIBUNG: ${tool.description}
|
|||||||
PLATTFORMEN: ${tool.platforms?.join(', ') || 'N/A'}
|
PLATTFORMEN: ${tool.platforms?.join(', ') || 'N/A'}
|
||||||
SKILL LEVEL: ${tool.skillLevel}
|
SKILL LEVEL: ${tool.skillLevel}
|
||||||
|
|
||||||
Bewerte das Tool und antworte nur mit JSON:
|
Bewerten Sie nach forensischen Standards und antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format:
|
||||||
{
|
{
|
||||||
"suitability_score": "high|medium|low",
|
"suitability_score": "high|medium|low",
|
||||||
"detailed_explanation": "Detaillierte Erklärung warum dieses Tool das Problem löst",
|
"detailed_explanation": "Detaillierte forensische Begründung warum diese Methode/Tool das Problem löst, basierend auf objektiven, pragmatischen Kriterien",
|
||||||
"implementation_approach": "Konkrete Schritte zur Anwendung für dieses Problem",
|
"implementation_approach": "Konkrete methodische Schritte zur korrekten Anwendung für dieses spezifische Problem",
|
||||||
"pros": ["Vorteil 1", "Vorteil 2"],
|
"pros": ["Forensischer Vorteil 1", "Validierter Vorteil 2"],
|
||||||
"cons": ["Nachteil 1", "Nachteil 2"],
|
"cons": ["Methodische Limitation 1", "Potenzielle Schwäche 2"],
|
||||||
"alternatives": "Alternative Ansätze wenn relevant"
|
"alternatives": "Alternative Ansätze falls diese Methode/Tool nicht optimal ist"
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
const result = await this.callMicroTaskAI(prompt, 600);
|
const result = await this.callMicroTaskAI(prompt, 650);
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
try {
|
try {
|
||||||
const evaluation = JSON.parse(result.content.replace(/^```json\s*/i, '').replace(/\s*```\s*$/g, '').trim());
|
const evaluation = JSON.parse(result.content.replace(/^```json\s*/i, '').replace(/\s*```\s*$/g, '').trim());
|
||||||
|
|
||||||
// Store the evaluation with the tool
|
|
||||||
if (!context.selectedTools) context.selectedTools = [];
|
if (!context.selectedTools) context.selectedTools = [];
|
||||||
context.selectedTools.push({
|
context.selectedTools.push({
|
||||||
tool: {
|
tool: {
|
||||||
@ -347,7 +374,7 @@ Bewerte das Tool und antworte nur mit JSON:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 6: Background Knowledge Selection
|
// ENHANCED MICRO-TASK 6: Background Knowledge with forensics context
|
||||||
private async selectBackgroundKnowledge(context: AnalysisContext): Promise<MicroTaskResult> {
|
private async selectBackgroundKnowledge(context: AnalysisContext): Promise<MicroTaskResult> {
|
||||||
const availableConcepts = context.filteredData.concepts;
|
const availableConcepts = context.filteredData.concepts;
|
||||||
|
|
||||||
@ -362,7 +389,7 @@ Bewerte das Tool und antworte nur mit JSON:
|
|||||||
|
|
||||||
const selectedToolNames = context.selectedTools?.map(st => st.tool.name) || [];
|
const selectedToolNames = context.selectedTools?.map(st => st.tool.name) || [];
|
||||||
|
|
||||||
const prompt = `Wähle relevante Hintergrundwissen-Konzepte für diesen Fall.
|
const prompt = `Wählen Sie relevante forensische Konzepte für das Verständnis der empfohlenen Methodik.
|
||||||
|
|
||||||
${context.mode === 'workflow' ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
|
${context.mode === 'workflow' ? 'SZENARIO' : 'PROBLEM'}: "${context.userQuery}"
|
||||||
EMPFOHLENE TOOLS: ${selectedToolNames.join(', ')}
|
EMPFOHLENE TOOLS: ${selectedToolNames.join(', ')}
|
||||||
@ -370,13 +397,13 @@ EMPFOHLENE TOOLS: ${selectedToolNames.join(', ')}
|
|||||||
VERFÜGBARE KONZEPTE:
|
VERFÜGBARE KONZEPTE:
|
||||||
${availableConcepts.slice(0, 15).map((concept: any) => `- ${concept.name}: ${concept.description.slice(0, 80)}...`).join('\n')}
|
${availableConcepts.slice(0, 15).map((concept: any) => `- ${concept.name}: ${concept.description.slice(0, 80)}...`).join('\n')}
|
||||||
|
|
||||||
Wähle 2-4 Konzepte aus, die für das Verständnis der empfohlenen Tools oder des Problems wichtig sind.
|
Wählen Sie 2-4 Konzepte aus, die für das Verständnis der forensischen Methodik und der empfohlenen Tools essentiell sind.
|
||||||
|
|
||||||
Antworte nur mit JSON:
|
Antworten Sie AUSSCHLIESSLICH mit diesem JSON-Format:
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
"conceptName": "Exakter Konzept-Name",
|
"conceptName": "Exakter Konzept-Name",
|
||||||
"relevance": "Warum dieses Konzept für die Tools/das Problem relevant ist"
|
"relevance": "Forensische Relevanz: Warum dieses Konzept für das Verständnis der Methodik/Tools kritisch ist"
|
||||||
}
|
}
|
||||||
]`;
|
]`;
|
||||||
|
|
||||||
@ -406,32 +433,34 @@ Antworte nur mit JSON:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// MICRO-TASK 7: Final Workflow/Additional Considerations
|
// ENHANCED MICRO-TASK 7: Final Recommendations with forensics methodology
|
||||||
private async generateFinalRecommendations(context: AnalysisContext): Promise<MicroTaskResult> {
|
private async generateFinalRecommendations(context: AnalysisContext): Promise<MicroTaskResult> {
|
||||||
const isWorkflow = context.mode === 'workflow';
|
const isWorkflow = context.mode === 'workflow';
|
||||||
|
|
||||||
const prompt = isWorkflow ?
|
const prompt = isWorkflow ?
|
||||||
`Erstelle eine finale Workflow-Empfehlung basierend auf der Analyse.
|
`Erstellen Sie eine forensisch fundierte Workflow-Empfehlung basierend auf DFIR-Prinzipien un pragmatischen Aspekten.
|
||||||
|
|
||||||
SZENARIO: "${context.userQuery}"
|
SZENARIO: "${context.userQuery}"
|
||||||
AUSGEWÄHLTE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Tools ausgewählt'}
|
AUSGEWÄHLTE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Tools ausgewählt'}
|
||||||
|
|
||||||
Erstelle eine konkrete Workflow-Empfehlung mit Schritten für dieses spezifische Szenario.
|
Erstellen Sie konkrete methodische Workflow-Schritte für dieses spezifische Szenario unter Berücksichtigung forensischer Best Practices, Objektivität und rechtlicher Verwertbarkeit.
|
||||||
Maximal 120 Wörter, als Fließtext.` :
|
|
||||||
|
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 120 Wörter.` :
|
||||||
|
|
||||||
`Erstelle zusätzliche Überlegungen für die Tool-Anwendung.
|
`Erstellen Sie wichtige methodische Überlegungen für die korrekte Methoden-/Tool-Anwendung.
|
||||||
|
|
||||||
PROBLEM: "${context.userQuery}"
|
PROBLEM: "${context.userQuery}"
|
||||||
EMPFOHLENE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Tools ausgewählt'}
|
EMPFOHLENE TOOLS: ${context.selectedTools?.map(st => st.tool.name).join(', ') || 'Keine Methoden/Tools ausgewählt'}
|
||||||
|
|
||||||
Gib wichtige zusätzliche Überlegungen, Voraussetzungen oder Warnungen.
|
Geben Sie kritische methodische Überlegungen, Validierungsanforderungen und Qualitätssicherungsmaßnahmen für die korrekte Anwendung der empfohlenen Methoden/Tools.
|
||||||
Maximal 100 Wörter, als Fließtext.`;
|
|
||||||
|
WICHTIG: Antworten Sie NUR in fließendem deutschen Text ohne Listen oder Markdown. Maximum 100 Wörter.`;
|
||||||
|
|
||||||
const result = await this.callMicroTaskAI(prompt, 180);
|
const result = await this.callMicroTaskAI(prompt, 180);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main processing pipeline with micro-tasks
|
// Main processing pipeline with micro-tasks (unchanged structure)
|
||||||
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
|
async processQuery(userQuery: string, mode: string): Promise<AnalysisResult> {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
let completedTasks = 0;
|
let completedTasks = 0;
|
||||||
@ -517,7 +546,7 @@ Maximal 100 Wörter, als Fließtext.`;
|
|||||||
const finalResult = await this.generateFinalRecommendations(context);
|
const finalResult = await this.generateFinalRecommendations(context);
|
||||||
if (finalResult.success) completedTasks++; else failedTasks++;
|
if (finalResult.success) completedTasks++; else failedTasks++;
|
||||||
|
|
||||||
// Build final recommendation object
|
// Build final recommendation object (ENHANCED: Remove generic additional_notes)
|
||||||
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
const recommendation = this.buildRecommendation(context, mode, finalResult.content);
|
||||||
|
|
||||||
processingStats.microTasksCompleted = completedTasks;
|
processingStats.microTasksCompleted = completedTasks;
|
||||||
@ -539,6 +568,7 @@ Maximal 100 Wörter, als Fließtext.`;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXED: Remove generic additional_notes message
|
||||||
private buildRecommendation(context: AnalysisContext, mode: string, finalContent: string): any {
|
private buildRecommendation(context: AnalysisContext, mode: string, finalContent: string): any {
|
||||||
const isWorkflow = mode === 'workflow';
|
const isWorkflow = mode === 'workflow';
|
||||||
|
|
||||||
@ -562,8 +592,8 @@ Maximal 100 Wörter, als Fließtext.`;
|
|||||||
priority: st.priority,
|
priority: st.priority,
|
||||||
justification: st.justification || `Empfohlen für ${st.phase}`
|
justification: st.justification || `Empfohlen für ${st.phase}`
|
||||||
})) || [],
|
})) || [],
|
||||||
workflow_suggestion: finalContent,
|
workflow_suggestion: finalContent
|
||||||
additional_notes: "Workflow basierend auf Micro-Task-Analyse generiert."
|
// REMOVED: additional_notes: "Workflow basierend auf Micro-Task-Analyse generiert."
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user