Spaces:
Running
Running
| """Case study viewer — browse saved workflow conversations without API keys.""" | |
| import json | |
| from pathlib import Path | |
| import streamlit as st | |
| # Search paths for case-study-memory | |
| _PROJECT_ROOT = Path(__file__).resolve().parent.parent.parent | |
| _CASE_STUDY_DIRS = [ | |
| _PROJECT_ROOT / "case-study-memory", | |
| Path(__file__).resolve().parent.parent / "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 | |
| def render_case_study_viewer(): | |
| """Render the case study browser UI.""" | |
| st.title("SciDER — Case Studies") | |
| 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] | |
| with open(selected_path, encoding="utf-8") as f: | |
| data = json.load(f) | |
| messages = data.get("messages", []) | |
| st.divider() | |
| 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") | |