agent_m/agentm/views/select_run.py
mscrnt 4500bfd388 Refactor agent management views and styles
- Removed commented-out header styles from styles.base.tcss and styles.tcss.
- Added new styles for danger buttons and agent selection views in styles.base.tcss and styles.tcss.
- Implemented AgentHomeView to manage agent actions and display metadata.
- Created AgentSelectView for selecting agents with a new layout and functionality.
- Added CreateAgentView for creating new agents with input validation.
- Removed obsolete eval.py and replaced it with evaluation.py.
- Developed GameSelectView for selecting games with a dynamic loading interface.
- Introduced ModelSelectView for selecting models associated with agents.
- Created SelectRunView for managing runs associated with agents.
- Added SubmissionView and TrainingView for handling model training and submission processes.
- Updated requirements.txt to include pyfiglet for ASCII art rendering.
2025-05-26 07:55:58 -07:00

148 lines
5.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()