- 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.
148 lines
5.5 KiB
Python
148 lines
5.5 KiB
Python
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()
|