File size: 3,259 Bytes
d3d0e0e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
"""Map technical operations to executive-friendly narratives."""

from typing import Dict, Tuple


# Action to executive-friendly description mapping
ACTION_NARRATIVES: Dict[str, Tuple[str, str]] = {
    # (emoji, narrative description)
    "list_context": ("📂", "Cataloging available data sources"),
    "read_csv": ("📊", "Examining structured data files"),
    "read_knowledge": ("📚", "Reading business context and rules"),
    "build_auto_db": ("🔧", "Preparing unified data workspace"),
    "semantic_extraction": ("🧠", "Extracting domain knowledge and relationships"),
    "planner": ("🎯", "Designing solution strategy"),
    "critic_plan": ("🔍", "Validating approach feasibility"),
    "execute_python": ("⚙️", "Executing data analysis"),
    "critic_execute": ("✅", "Verifying results quality"),
}


def get_action_narrative(action: str) -> Tuple[str, str]:
    """Get emoji and narrative for an action."""
    return ACTION_NARRATIVES.get(action, ("🔄", f"Processing: {action}"))


def get_phase_description(phase: str) -> str:
    """Get human-readable phase description."""
    phase_map = {
        "exploration": "🔍 Data Discovery & Understanding",
        "planning": "📋 Solution Strategy Development", 
        "execution": "⚙️ Analysis Execution & Refinement",
        "validation": "✅ Quality Assurance & Verification",
        "completion": "🎉 Task Completion",
    }
    return phase_map.get(phase, phase)


def format_reasoning(reasoning: str, max_length: int = 200) -> str:
    """Format plan reasoning for executive display."""
    if not reasoning:
        return "No reasoning provided"
    
    # Clean up technical jargon
    cleaned = reasoning.replace("filtering by", "finding records where")
    cleaned = cleaned.replace("joining", "connecting")
    cleaned = cleaned.replace("DataFrame", "data table")
    
    if len(cleaned) > max_length:
        return cleaned[:max_length-3] + "..."
    return cleaned


def get_success_emoji(succeeded: bool) -> str:
    """Get appropriate emoji for success status."""
    return "✅" if succeeded else "❌"


def get_confidence_indicator(attempts: int) -> Tuple[str, str]:
    """Get confidence level based on number of attempts."""
    if attempts == 1:
        return "🟢", "High - Solved on first try"
    elif attempts <= 3:
        return "🟡", "Good - Minor refinements needed"
    elif attempts <= 5:
        return "🟠", "Moderate - Multiple iterations required"
    else:
        return "🔴", "Low - Significant challenges encountered"


def summarize_issue(issue: str) -> str:
    """Convert technical issue to executive summary."""
    # Common patterns
    if "empty" in issue.lower():
        return "No matching records found - refining search criteria"
    elif "column" in issue.lower():
        return "Data structure mismatch - adjusting field selection"
    elif "type" in issue.lower() or "error" in issue.lower():
        return "Data format issue - applying corrections"
    elif "filter" in issue.lower():
        return "Search criteria too restrictive - broadening scope"
    else:
        # Truncate long technical messages
        if len(issue) > 80:
            return issue[:77] + "..."
        return issue