File size: 4,496 Bytes
1499363
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""Case study viewer — browse saved workflow conversations without API keys."""

import json
from pathlib import Path

import streamlit as st

# Search paths for saved conversations and case-study-memory examples
_APP_ROOT = Path(__file__).resolve().parent.parent  # streamlit-client/
_PROJECT_ROOT = _APP_ROOT.parent                    # SciDER/
_CASE_STUDY_DIRS = [
    _APP_ROOT / "saved_chats",           # conversations saved by the app's own workflows
    _PROJECT_ROOT / "case-study-memory", # pre-bundled example case studies
    _APP_ROOT / "case-study-memory",
]


def list_case_studies() -> list[tuple[Path, dict]]:
    """List all chat_history.json files in case-study-memory directories."""
    results = []
    seen = set()
    for base in _CASE_STUDY_DIRS:
        if not base.exists():
            continue
        dirs = sorted(
            [d for d in base.iterdir() if d.is_dir() and (d / "chat_history.json").exists()],
            key=lambda x: x.stat().st_mtime,
            reverse=True,
        )
        for memo_dir in dirs:
            chat_file = memo_dir / "chat_history.json"
            key = str(chat_file.resolve())
            if key in seen:
                continue
            seen.add(key)
            try:
                with open(chat_file, encoding="utf-8") as f:
                    data = json.load(f)
                ts = data.get("timestamp", "")[:19].replace("T", " ")
                wf = data.get("workflow_type", "unknown")
                query = data.get("metadata", {}).get("query", "")
                label = (query[:80] + "...") if len(query) > 83 else (query or memo_dir.name)
                results.append((chat_file, {"label": label, "timestamp": ts, "workflow_type": wf}))
            except Exception:
                results.append(
                    (
                        chat_file,
                        {"label": memo_dir.name, "timestamp": "", "workflow_type": "unknown"},
                    )
                )
    return results


_WORKFLOW_LABELS = {
    "ideation": "Ideation",
    "data": "Data Analysis",
    "experiment": "Experiment",
    "full": "Full Pipeline",
}


def render_case_study_viewer():
    """Render the case study browser UI."""
    st.markdown(
        """<div class='scider-header'>
        <span class='scider-header-icon'>📚</span>
        <div>
            <div class='scider-header-title'>Case Studies</div>
            <div class='scider-header-sub'>Browse saved workflow conversations and workspace artifacts</div>
        </div>
        </div>""",
        unsafe_allow_html=True,
    )

    available = list_case_studies()
    if not available:
        st.info("No case studies found. Run a workflow first to save conversations.")
        return

    options = [f"{m['label']}  ({m['workflow_type']}, {m['timestamp']})" for _, m in available]
    idx = st.selectbox(
        "Select a case study",
        range(len(options)),
        format_func=lambda i: options[i],
        key="case_study_select",
    )

    selected_path = available[idx][0]
    selected_meta = available[idx][1]
    with open(selected_path, encoding="utf-8") as f:
        data = json.load(f)

    # Metadata card
    wf_type = selected_meta["workflow_type"]
    wf_label = _WORKFLOW_LABELS.get(wf_type, wf_type.title())
    query = data.get("metadata", {}).get("query", selected_meta["label"])
    ts = selected_meta["timestamp"]
    st.markdown(
        f"""<div class='approval-card'>
        <p class='approval-card-title'>{query}</p>
        <p class='approval-card-subtitle'>{wf_label} &nbsp;·&nbsp; {ts}</p>
        </div>""",
        unsafe_allow_html=True,
    )

    # Workflow type badge + message count
    msg_count = len(data.get("messages", []))
    st.markdown(
        f"<span class='chat-agent-badge'>{wf_label}</span>&nbsp;&nbsp;"
        f"<span style='color:#64748b;font-size:0.85rem'>{msg_count} messages</span>",
        unsafe_allow_html=True,
    )
    st.divider()

    messages = data.get("messages", [])
    for m in messages:
        with st.chat_message(m["role"]):
            st.markdown(m["content"])

    # Show workspace files if available
    from components.file_browser import render_file_browser, render_workspace_download

    case_dir = selected_path.parent
    ws_dir = case_dir / "workspace"
    browse_dir = ws_dir if ws_dir.exists() else case_dir
    render_file_browser(browse_dir, key_prefix="cs_fb")
    render_workspace_download(browse_dir, key_prefix="cs_dl")