This plan outlines the necessary steps to integrate a "Run/Test" feature directly into the GUI, transforming it into a complete IDE for your agents.
Implementation Plan: Agent Test & Run Facility
Phase 1: GUI - The "Run" Button and Modal Launcher
Modify editor_app.py - Add UI Trigger: In the create_settings_tab method of the ProcEditorFrame, TemplateEditorFrame, and WorkflowEditorFrame classes, add a new button. Code: Generated python # Add this within the create_settings_tab method of each editor frame ctk.CTkButton(tab, text="Run/Test Agent...", command=self.open_run_modal).pack(anchor="w", padx=10, pady=10)
Add a Launcher Method to Each Editor Frame: In ProcEditorFrame, TemplateEditorFrame, and WorkflowEditorFrame, create a new method that gathers the current, potentially unsaved data from the form and calls the main app's launcher. This ensures the test run uses the very latest edits. Code: Generated python # Add this method to each of the three main editor frames def open_run_modal(self): # Get the current data from the editor, including unsaved changes current_agent_data = self.get_data() # The name is part of the data, so we extract it agent_name = current_agent_data.pop('name', self.agent_name) self.app_ref.launch_run_modal(agent_name, current_agent_data)
Add a Global Launcher Method to the App Class: This method in the main App class will be responsible for creating and displaying the modal window. Code: Generated python # Add this new method to the App class in editor_app.py def launch_run_modal(self, agent_name, agent_data): """Launches the modal window for running/testing an agent.""" modal = RunAgentModal(self, agent_name, agent_data, self.config) # The .wait_window() call is not strictly necessary but good practice # if you want to ensure it blocks until closed.
Phase 2: The Core Feature - RunAgentModal
Create the TextboxLogHandler Class: This custom logging handler is crucial for redirecting log output to a GUI widget. Code: Generated python import logging import customtkinter as ctk class TextboxLogHandler(logging.Handler): """A logging handler that redirects records to a CTkTextbox widget.""" def __init__(self, textbox_widget): super().__init__() self.textbox = textbox_widget self.textbox.configure(state="disabled") def emit(self, record): msg = self.format(record) self.textbox.configure(state="normal") self.textbox.insert(ctk.END, msg + "\n") self.textbox.see(ctk.END) # Auto-scroll self.textbox.configure(state="disabled")
Create the RunAgentModal Class Skeleton: Import necessary modules at the top of editor_app.py: import time, import dynamic_workflows_agents, import json. Define the new class. Its __init__ will store the context it needs. Code: Generated python
class RunAgentModal(ctk.CTkToplevel):def __init__(self, parent, agent_name, agent_data, config_manager): super().__init__(parent) self.title(f"Test Run: {agent_name}") self.geometry("1200x700") self.parent = parent self.agent_name = agent_name self.agent_data = agent_data self.config_manager = config_manager self.input_entries = {} self.grid_columnconfigure(1, weight=3) self.grid_columnconfigure(0, weight=2) self.grid_rowconfigure(0, weight=1) self.create_widgets() self.transient(parent) self.grab_set()
Implement create_widgets for RunAgentModal: This method builds the UI for inputs and outputs. Conceptual Code: Generated python
def create_widgets(self):# --- Input Pane (Left) --- input_frame = ctk.CTkFrame(self) input_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew") # Add labels, entries for required inputs from self.agent_data['inputs'] # Populate self.input_entries dictionary mapping input_name -> CTkEntry widget # Add a way to add optional inputs from self.agent_data['optional_inputs'] # Add the "Run Workflow" button, with command=self.execute_run # --- Output Pane (Right) --- output_tabs = ctk.CTkTabview(self) output_tabs.grid(row=0, column=1, padx=10, pady=10, sticky="nsew") # Create "Result", "Log", "Status & Stats" tabs # Add a CTkTextbox to each tab, storing them in self.result_box, self.log_box, etc.
Implement execute_run for RunAgentModal: This is the core logic that orchestrates the test run. Conceptual Code: Generated python
def execute_run(self):# 1. Clear previous outputs # self.result_box.delete(...), self.log_box.delete(...) # 2. Gather inputs from self.input_entries into a cli_args dictionary # 3. Prepare the agent (reuse existing logic) if self.agent_data.get('type') != 'workflow': agent_to_run = dynamic_workflows_agents.create_temp_workflow( self.agent_name, self.agent_data, self.config_manager.config, cli_args ) else: agent_to_run = self.agent_data # 4. Setup logging redirection log_handler = TextboxLogHandler(self.log_box) # Set a formatter for clean output log_handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s')) logging.getLogger().addHandler(log_handler) # 5. Execute in a try...finally block to ensure cleanup try: start_time = time.perf_counter() final_result, status = dynamic_workflows_agents.exec_workflow( workflow=agent_to_run, config=self.config_manager.config, cli_args=cli_args, results={} # Always start with a fresh results tape ) duration = time.perf_counter() - start_time # 6. Display results # Format final_result as pretty JSON and insert into self.result_box # Format status and duration and insert into self.stats_box except Exception as e: # Log any crashes to the log box itself logging.error(f"FATAL EXECUTION ERROR: {e}", exc_info=True) finally: # 7. CRITICAL: Clean up the logger logging.getLogger().removeHandler(log_handler)
No comments:
Post a Comment