scider / streamlit-client /forms /case_study.py
leonardklin's picture
Upload 328 files
978fed5 verified
"""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")