from textual.screen import Screen from textual.containers import Vertical, Horizontal, VerticalScroll from textual.widgets import Static, Button from agentm.logic.db_functions import get_runs_for_agent, insert_run from agentm.theme.palette import get_theme from agentm.utils.logger import log_with_caller from agentm.components.footer import AgentMFooter from agentm.views.agent_home import AgentHomeView from pathlib import Path from datetime import datetime palette = get_theme() class RunCard(Static): def __init__(self, run_data: dict, parent_view): super().__init__(classes="agent_card") self.run_data = run_data self.parent_view = parent_view def render(self) -> str: return f""" [bold {palette.ACCENT}]{self.run_data['name']}[/] [dim]Created:[/] {self.run_data.get('created_at', '—')} """.strip() async def on_click(self): await self.parent_view.display_run_info(self.run_data) class SelectRunView(Screen): BINDINGS = [ ("escape", "app.pop_screen", "Back"), ("r", "refresh_runs", "Refresh"), ] def __init__(self, agent_metadata: dict): super().__init__() self.agent_metadata = agent_metadata self.selected_run = None def compose(self): header_path = Path(__file__).parent.parent / "assets" / "headers" / "select_run.txt" try: header_text = header_path.read_text() except FileNotFoundError: header_text = "=== SELECT RUN ===" self.header = Static(f"[{palette.ACCENT}]{header_text}[/{palette.ACCENT}]", classes="header") self.subheader = Static(f"[b]{self.agent_metadata['name']}[/b]", classes="subheader") self.run_list = VerticalScroll(id="agent_scroll") self.run_info = Horizontal(id="agent_info_panel") self.select_button = Button("✅ Select Run", id="select_run_btn", classes="confirm_button", disabled=True) self.create_button = Button("➕ Create New Run", id="create_run_btn", classes="confirm_button") yield Vertical( self.header, self.subheader, self.run_list, self.run_info, self.select_button, self.create_button, AgentMFooter(compact=True), id="agent_select_layout" ) async def on_mount(self): log_with_caller("debug", f"Mounted SelectRunView for agent_id: {self.agent_metadata['id']}") await self.refresh_run_list() async def refresh_run_list(self): try: for child in list(self.run_list.children): await child.remove() runs = get_runs_for_agent(self.agent_metadata["id"]) log_with_caller("info", f"Refreshed: {len(runs)} runs found for agent {self.agent_metadata['name']}") if runs: for run in runs: await self.run_list.mount(RunCard(run, self)) else: await self.run_list.mount(Static("[dim]No runs found for this agent.[/dim]")) self.selected_run = None await self.display_run_info(None) except Exception as e: log_with_caller("error", f"Error rendering run list: {e}") async def display_run_info(self, run: dict | None): self.selected_run = run await self.run_info.remove_children() if not run: await self.run_info.mount(Static("[dim]Select a run to view details[/dim]")) self.select_button.disabled = True return from rich.panel import Panel from rich.table import Table table = Table.grid(padding=(0, 1)) table.add_column("Key", style="bold underline") table.add_column("Value", style=palette.ACCENT, overflow="fold") table.add_row("Name", run["name"]) table.add_row("Created", run.get("created_at", "—")) table.add_row("Notes", run.get("notes", "—")) info_panel = Static(Panel(table, title="Run Info", border_style=palette.BORDER), classes="agent_info_box") await self.run_info.mount(info_panel) self.select_button.disabled = False async def on_button_pressed(self, event: Button.Pressed) -> None: if event.button.id == "select_run_btn" and self.selected_run: log_with_caller("info", f"Run confirmed: {self.selected_run['name']}") await self.app.push_screen(AgentHomeView(agent=self.agent_metadata, run=self.selected_run)) elif event.button.id == "create_run_btn": # Auto-generate name and basic config run_name = f"{self.agent_metadata['name']} - {datetime.utcnow().strftime('%Y%m%d-%H%M%S')}" config_yaml = "# Auto-generated config for new run\n" notes = f"Initial run for agent {self.agent_metadata['name']}" # Insert into DB insert_run( agent_id=self.agent_metadata["id"], name=run_name, config_yaml=config_yaml, notes=notes ) # Fetch the new run and push to AgentHomeView runs = get_runs_for_agent(self.agent_metadata["id"]) new_run = runs[0] if runs else None if new_run: log_with_caller("info", f"Created and selected new run: {new_run['name']}") await self.app.push_screen(AgentHomeView(agent=self.agent_metadata, run=new_run)) else: log_with_caller("error", "Failed to retrieve newly created run") async def action_refresh_runs(self): await self.refresh_run_list()