import io import json import zipfile import pandas as pd from typing import Tuple from .sim import World from .kpi import compute_kpis def export_run(w: World) -> Tuple[bytes, str]: """ Returns (zip_bytes, filename) Contents: - events.jsonl - metrics.csv - run_summary.json """ # events events_jsonl = w.events.to_jsonl().encode("utf-8") # metrics (single-row snapshot; you can also store per-tick KPI series later) kpi = compute_kpis(w) df = pd.DataFrame([kpi]) metrics_csv = df.to_csv(index=False).encode("utf-8") # summary summary = { "run_id": w.run_id, "seed": w.seed, "tick": w.step, "minutes_per_tick": w.config.minutes_per_tick, "ledger": { "spend_usd": w.ledger.spend_usd, "llm_calls": w.ledger.llm_calls, "tool_calls": w.ledger.tool_calls, "tokens_prompt": w.ledger.tokens_prompt, "tokens_completion": w.ledger.tokens_completion, }, "kpi": kpi, "alerts": w.ledger.alerts[-10:], "tasks_total": len(w.tasks.tasks), "tasks_done": len(w.tasks.done_tasks()), "tasks_overdue": len(w.tasks.overdue_tasks(w.step)), } summary_json = json.dumps(summary, indent=2).encode("utf-8") # zip buf = io.BytesIO() with zipfile.ZipFile(buf, mode="w", compression=zipfile.ZIP_DEFLATED) as z: z.writestr("events.jsonl", events_jsonl) z.writestr("metrics.csv", metrics_csv) z.writestr("run_summary.json", summary_json) buf.seek(0) fname = f"zen_orchestrator_export__{w.run_id}.zip" return buf.read(), fname