diff --git a/backend/routers/prompts.py b/backend/routers/prompts.py index 257914c..814c126 100644 --- a/backend/routers/prompts.py +++ b/backend/routers/prompts.py @@ -856,6 +856,19 @@ async def execute_unified_prompt( elif result['type'] == 'pipeline': # Pipeline: collect from all stages stages_debug = result['debug'].get('stages', []) + + # First, collect stage outputs (outputs from base prompts in each stage) + stage_outputs = {} + for stage_debug in stages_debug: + stage_num = stage_debug.get('stage', 0) + stage_output = stage_debug.get('output', {}) + if isinstance(stage_output, dict): + for output_key, output_value in stage_output.items(): + # Store stage outputs (e.g., stage_1_body) + placeholder_key = f"stage_{stage_num}_{output_key}" + stage_outputs[placeholder_key] = output_value + + # Collect all resolved placeholders from prompts for stage_debug in stages_debug: for prompt_debug in stage_debug.get('prompts', []): resolved_keys = [] @@ -867,20 +880,25 @@ async def execute_unified_prompt( for key in resolved_keys: if key not in metadata['placeholders']: # Avoid duplicates - # Get full untruncated value - value = cleaned_values.get(key, '') + # Get value: first try stage outputs, then cleaned_values + value = stage_outputs.get(key, cleaned_values.get(key, '')) - # Find description in catalog - desc = None - for cat_items in catalog.values(): - matching = [item for item in cat_items if item['key'] == key] - if matching: - desc = matching[0].get('description', '') - break + # For stage output placeholders, add special description + if key.startswith('stage_'): + desc = f"Output aus Stage {key.split('_')[1]} (Basis-Analyse)" + else: + # Find description in catalog + desc = None + for cat_items in catalog.values(): + matching = [item for item in cat_items if item['key'] == key] + if matching: + desc = matching[0].get('description', '') + break + desc = desc or '' metadata['placeholders'][key] = { - 'value': value, - 'description': desc or '' + 'value': value if isinstance(value, str) else json.dumps(value, ensure_ascii=False), + 'description': desc } # Save to database with metadata diff --git a/frontend/src/pages/Analysis.jsx b/frontend/src/pages/Analysis.jsx index 3021c2c..90dd29f 100644 --- a/frontend/src/pages/Analysis.jsx +++ b/frontend/src/pages/Analysis.jsx @@ -24,6 +24,7 @@ function InsightCard({ ins, onDelete, defaultOpen=false, prompts=[] }) { const showOnlyValues = isBasePrompt && isJsonOutput && Object.keys(placeholdersRaw).length > 0 const [showValues, setShowValues] = useState(showOnlyValues) // Auto-expand for base prompts with JSON + const [expertMode, setExpertMode] = useState(false) // Show empty/technical placeholders // Find matching prompt to get display_name const prompt = prompts.find(p => p.slug === ins.scope) @@ -31,8 +32,20 @@ function InsightCard({ ins, onDelete, defaultOpen=false, prompts=[] }) { // Use already-parsed metadata const metadata = metadataRaw - const placeholders = placeholdersRaw + const allPlaceholders = placeholdersRaw + + // Filter placeholders: In normal mode, hide empty values + const placeholders = expertMode + ? allPlaceholders + : Object.fromEntries( + Object.entries(allPlaceholders).filter(([key, data]) => { + const val = data.value || '' + return val.trim() !== '' && val !== 'nicht verfügbar' && val !== '[Nicht verfügbar]' + }) + ) + const placeholderCount = Object.keys(placeholders).length + const hiddenCount = Object.keys(allPlaceholders).length - placeholderCount return (