Abid Ali Awan
Fix setup dialog open handler
95222e8
from __future__ import annotations
import asyncio
import time
import reflex as rx
from .pdf_export import markdown_to_pdf_bytes
from .report_formatting import markdown_to_html, plain_markdown
from .research_assistant import environment_status, run_research_assistant
_RUNNING_TASKS: dict[str, asyncio.Task] = {}
class State(rx.State):
query: str = ""
logs: list[str] = []
report_markdown: str = ""
report_html: str = ""
trace_url: str = ""
error: str = ""
is_running: bool = False
status: str = "Ready"
active_run_id: int = 0
step_started_at: float = 0.0
show_setup_dialog: bool = False
missing_env_text: str = ""
def set_query(self, value: str) -> None:
self.query = value
def close_setup_dialog(self) -> None:
self.show_setup_dialog = False
def set_setup_dialog_open(self, open: bool) -> None:
self.show_setup_dialog = open
def _client_token(self) -> str:
return self.router.session.client_token or "default"
def _cancel_active_task(self) -> bool:
task = _RUNNING_TASKS.pop(self._client_token(), None)
if task is not None and not task.done():
task.cancel()
return True
return False
def clear_all(self) -> None:
self._cancel_active_task()
self.active_run_id += 1
self.query = ""
self.logs = []
self.report_markdown = ""
self.report_html = ""
self.trace_url = ""
self.error = ""
self.is_running = False
self.status = "Ready"
self.step_started_at = 0.0
def stop_report(self) -> None:
if not self.is_running:
return
now = time.monotonic()
elapsed = max(0.0, now - self.step_started_at) if self.step_started_at else 0.0
self._cancel_active_task()
self.is_running = False
self.error = ""
self.status = "Stopped"
self.step_started_at = now
self.logs.append(f"{elapsed:.1f}s Research stopped by user.")
async def _log(self, message: str) -> None:
async with self:
now = time.monotonic()
elapsed = max(0.0, now - self.step_started_at) if self.step_started_at else 0.0
self.step_started_at = now
self.logs.append(f"{elapsed:.1f}s {message}")
def handle_key_down(self, key: str):
if key == "Enter":
return State.run_report
def run_report(self):
query = self.query.strip()
if not query:
self.error = ""
return
env_ready, missing_names, _, _ = environment_status()
if not env_ready:
self.error = ""
self.status = "Ready"
self.missing_env_text = ", ".join(missing_names)
self.show_setup_dialog = True
return
return State.run_report_background
@rx.event(background=True)
async def run_report_background(self):
task = asyncio.current_task()
run_id = 0
async with self:
query = self.query.strip()
if not query:
self.error = ""
return
self.active_run_id += 1
run_id = self.active_run_id
if task is not None:
_RUNNING_TASKS[self._client_token()] = task
self.logs = []
self.report_markdown = ""
self.report_html = ""
self.trace_url = ""
self.error = ""
self.is_running = True
self.status = "Researching"
self.step_started_at = time.monotonic()
try:
report, trace_url = await run_research_assistant(query, progress=self._log)
async with self:
self.report_markdown = plain_markdown(report.markdown_report)
self.report_html = markdown_to_html(self.report_markdown)
self.trace_url = trace_url
self.status = "Complete"
except asyncio.CancelledError:
async with self:
if self.active_run_id == run_id:
self.error = ""
self.status = "Stopped"
except Exception as exc:
async with self:
if self.active_run_id == run_id:
self.error = str(exc)
self.status = "Failed"
finally:
async with self:
if self.active_run_id == run_id:
self.is_running = False
_RUNNING_TASKS.pop(self._client_token(), None)
def download_markdown(self):
if not self.report_markdown:
return rx.window_alert("Generate a report before downloading.")
return rx.download(data=self.report_markdown, filename="research-report.md")
def download_pdf(self):
if not self.report_markdown:
return rx.window_alert("Generate a report before downloading.")
try:
pdf_bytes = markdown_to_pdf_bytes(self.report_markdown)
except ImportError:
return rx.window_alert(
"PDF support is not installed. Run: pip install -r requirements.txt"
)
except Exception as exc:
return rx.window_alert(f"Could not generate PDF: {exc}")
return rx.download(data=pdf_bytes, filename="research-report.pdf")