agent_m/agentm/views/agent_select.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

167 lines
6.7 KiB
Python
Raw 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_agents_for_game, delete_agent_by_id
from agentm.theme.palette import get_theme
from agentm.utils.logger import log_with_caller
from agentm.components.footer import AgentMFooter
from .create_agent import CreateAgentView
from .select_run import SelectRunView
from pathlib import Path
palette = get_theme()
class AgentCard(Static):
def __init__(self, agent_data: dict, parent_view):
super().__init__(classes="agent_card")
self.agent_data = agent_data
self.parent_view = parent_view
def render(self) -> str:
return f"""
[bold {palette.ACCENT}]{self.agent_data['name']}[/]
[dim]ID:[/] {self.agent_data['id']}
[dim]Created:[/] {self.agent_data.get('created_at', '')}
[dim]Game ID:[/] {self.agent_data['game_id']}
""".strip()
async def on_click(self):
await self.parent_view.display_agent_info(self.agent_data)
class AgentSelectView(Screen):
BINDINGS = [
("escape", "app.pop_screen", "Back"),
("n", "create_agent", "New Agent"),
("r", "refresh_agents", "Refresh"),
("up", "scroll_up", "Scroll Up"),
("down", "scroll_down", "Scroll Down"),
]
def __init__(self, game_metadata: dict):
super().__init__()
self.game_metadata = game_metadata
self.selected_agent = None
self.delete_mode = False
def compose(self):
ascii_path = Path(__file__).parent.parent / "assets" / "headers" / "agent_select.txt"
try:
header_text = ascii_path.read_text()
except FileNotFoundError:
header_text = "=== SELECT AGENT ==="
self.header = Static(f"[{palette.ACCENT}]{header_text}[/{palette.ACCENT}]", classes="header")
self.subheader = Static(f"[b]{self.game_metadata['title']}[/b]", classes="subheader")
self.agent_list = VerticalScroll(id="agent_scroll")
self.agent_info = Horizontal(id="agent_info_panel")
self.confirm_button = Button("✅ Select Agent", id="confirm_agent_btn", classes="confirm_button", disabled=True)
self.delete_button = Button("🗑️ Delete Agent", id="delete_agent_btn", classes="danger_button", disabled=True)
self.create_button = Button(" Create Agent", id="create_agent_btn", classes="confirm_button")
yield Vertical(
self.header,
self.subheader,
self.agent_list,
self.agent_info,
self.create_button,
AgentMFooter(compact=True),
id="agent_select_layout"
)
async def on_mount(self):
log_with_caller("debug", f"Mounted AgentSelectView for game_id: {self.game_metadata['game_id']}")
await self.refresh_agent_list()
async def on_resume(self):
await self.refresh_agent_list()
async def refresh_agent_list(self):
try:
for child in list(self.agent_list.children):
await child.remove()
agents = get_agents_for_game(self.game_metadata["game_id"])
log_with_caller("info", f"Refreshed: {len(agents)} agents found for {self.game_metadata['game_id']}")
if agents:
for agent in agents:
await self.agent_list.mount(AgentCard(agent, self))
else:
await self.agent_list.mount(Static("[dim]No agents found for this game.[/dim]"))
self.selected_agent = None
self.delete_mode = False
await self.display_agent_info(None)
except Exception as e:
log_with_caller("error", f"Error rendering agent list: {e}")
async def display_agent_info(self, agent: dict | None):
self.selected_agent = agent
self.delete_mode = False
await self.agent_info.remove_children()
if not agent:
await self.agent_info.mount(Static("[dim]Select an agent to view details[/dim]"))
self.confirm_button.disabled = True
self.delete_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", agent["name"])
table.add_row("Agent ID", str(agent["id"]))
table.add_row("Game ID", agent["game_id"])
table.add_row("Created", agent.get("created_at", ""))
table.add_row("Type", agent.get("agent_type", ""))
table.add_row("Framework", agent.get("framework", ""))
table.add_row("Imitation", str(agent.get("is_imitation", False)))
info_panel = Static(Panel(table, title="Agent Info", border_style=palette.BORDER), classes="agent_info_box")
button_column = Vertical(self.confirm_button, self.delete_button, classes="agent_action_box")
await self.agent_info.mount(info_panel, button_column)
self.confirm_button.disabled = False
self.delete_button.disabled = False
self.delete_button.label = "🗑️ Delete Agent"
async def on_button_pressed(self, event: Button.Pressed) -> None:
if event.button.id == "create_agent_btn":
log_with_caller("info", "Create Agent button pressed.")
await self.app.push_screen(CreateAgentView(self.game_metadata))
elif event.button.id == "confirm_agent_btn" and self.selected_agent:
log_with_caller("info", f"Agent confirmed: {self.selected_agent['name']}")
await self.app.push_screen(SelectRunView(self.selected_agent))
elif event.button.id == "delete_agent_btn" and self.selected_agent:
if not self.delete_mode:
self.delete_mode = True
self.delete_button.label = "❌ Confirm Delete"
log_with_caller("warning", f"Pending deletion for agent: {self.selected_agent['name']}")
else:
log_with_caller("info", f"Deleting agent: {self.selected_agent['name']} ({self.selected_agent['id']})")
delete_agent_by_id(self.selected_agent["id"])
await self.refresh_agent_list()
async def action_create_agent(self):
await self.app.push_screen(CreateAgentView(self.game_metadata))
async def action_refresh_agents(self):
await self.refresh_agent_list()
async def action_scroll_up(self):
scroll = self.query_one("#agent_scroll", VerticalScroll)
scroll.scroll_up()
async def action_scroll_down(self):
scroll = self.query_one("#agent_scroll", VerticalScroll)
scroll.scroll_down()