From bd5dc1671599f22159216277c7cca7e5c9832a95 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Mon, 23 Feb 2026 19:24:26 -0500 Subject: [PATCH] feat(simulation): implement project scaffolding and discussion loop logic --- gui.py | 6 ++--- simulation/workflow_sim.py | 49 ++++++++++++++++++++++++++++++++++++++ tests/test_workflow_sim.py | 28 ++++++++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 simulation/workflow_sim.py create mode 100644 tests/test_workflow_sim.py diff --git a/gui.py b/gui.py index 63e1810..41792b5 100644 --- a/gui.py +++ b/gui.py @@ -1919,9 +1919,9 @@ class App: with dpg.child_window(tag="projects_scroll", height=120, border=True): pass with dpg.group(horizontal=True): - dpg.add_button(label="Add Project", callback=self.cb_add_project) - dpg.add_button(label="New Project", callback=self.cb_new_project) - dpg.add_button(label="Save All", callback=self.cb_save_config) + dpg.add_button(label="Add Project", tag="btn_project_add", callback=self.cb_add_project) + dpg.add_button(label="New Project", tag="btn_project_new", callback=self.cb_new_project) + dpg.add_button(label="Save All", tag="btn_project_save", callback=self.cb_save_config) dpg.add_checkbox( tag="project_word_wrap", label="Word-Wrap (Read-only panels)", diff --git a/simulation/workflow_sim.py b/simulation/workflow_sim.py new file mode 100644 index 0000000..b77a822 --- /dev/null +++ b/simulation/workflow_sim.py @@ -0,0 +1,49 @@ +import time +import os +from api_hook_client import ApiHookClient +from simulation.user_agent import UserSimAgent + +class WorkflowSimulator: + def __init__(self, hook_client: ApiHookClient): + self.client = hook_client + self.user_agent = UserSimAgent(hook_client) + + def setup_new_project(self, name, git_dir): + print(f"Setting up new project: {name}") + self.client.click("btn_project_new") + time.sleep(1) + self.client.set_value("project_git_dir", git_dir) + self.client.click("btn_project_save") + time.sleep(1) + + def run_discussion_turn(self, user_message=None): + if user_message is None: + # Generate from AI history + session = self.client.get_session() + entries = session.get('session', {}).get('entries', []) + user_message = self.user_agent.generate_response(entries) + + print(f"\n[USER]: {user_message}") + self.client.set_value("ai_input", user_message) + self.client.click("btn_gen_send") + + # Wait for AI + return self.wait_for_ai_response() + + def wait_for_ai_response(self, timeout=60): + print("Waiting for AI response...", end="", flush=True) + start_time = time.time() + last_count = len(self.client.get_session().get('session', {}).get('entries', [])) + + while time.time() - start_time < timeout: + time.sleep(1) + print(".", end="", flush=True) + entries = self.client.get_session().get('session', {}).get('entries', []) + if len(entries) > last_count: + last_entry = entries[-1] + if last_entry.get('role') == 'AI' and last_entry.get('content'): + print(f"\n[AI]: {last_entry.get('content')[:100]}...") + return last_entry + + print("\nTimeout waiting for AI") + return None diff --git a/tests/test_workflow_sim.py b/tests/test_workflow_sim.py new file mode 100644 index 0000000..f3de681 --- /dev/null +++ b/tests/test_workflow_sim.py @@ -0,0 +1,28 @@ +import pytest +import sys +import os +from unittest.mock import MagicMock, patch + +# Ensure project root is in path +sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))) + +from simulation.workflow_sim import WorkflowSimulator + +def test_simulator_instantiation(): + client = MagicMock() + sim = WorkflowSimulator(client) + assert sim is not None + +def test_setup_new_project(): + client = MagicMock() + sim = WorkflowSimulator(client) + + # Mock responses for wait_for_server + client.wait_for_server.return_value = True + + sim.setup_new_project("TestProject", "/tmp/test_git") + + # Verify hook calls + client.click.assert_any_call("btn_project_new") + client.set_value.assert_any_call("project_git_dir", "/tmp/test_git") + client.click.assert_any_call("btn_project_save")