feat(gui): Rename gui.py to gui_legacy.py and update references
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
* **Configuration:** TOML (`tomli-w`)
|
||||
|
||||
**Architecture:**
|
||||
* **`gui.py`:** The main entry point and Dear PyGui application logic. Handles all panels, layouts, user input, and confirmation dialogs.
|
||||
* **`gui_legacy.py`:** The main entry point and Dear PyGui application logic. Handles all panels, layouts, user input, and confirmation dialogs.
|
||||
* **`ai_client.py`:** A unified wrapper for both Gemini and Anthropic APIs. Manages sessions, tool/function-call loops, token estimation, and context history management.
|
||||
* **`aggregate.py`:** Responsible for building the `file_items` context. It reads project configurations, collects files and screenshots, and builds the context into markdown format to send to the AI.
|
||||
* **`mcp_client.py`:** Implements MCP-like tools (e.g., `read_file`, `list_directory`, `search_files`, `web_search`) as native functions that the AI can call. Enforces a strict allowlist for file access.
|
||||
@@ -30,7 +30,7 @@
|
||||
```
|
||||
* **Run the Application:**
|
||||
```powershell
|
||||
uv run .\gui.py
|
||||
uv run .\gui_legacy.py
|
||||
```
|
||||
|
||||
# Development Conventions
|
||||
|
||||
@@ -37,7 +37,7 @@ coder = "deepseek:deepseek-coder"
|
||||
|
||||
```
|
||||
|
||||
Then, your UI (`gui.py` / `gui_2.py`) only talks to the Orchestrator. The Orchestrator's system prompt is given access to tools like `call_deepseek_coder(prompt)` or `call_flash_reader(filepath)`.
|
||||
Then, your UI (`gui_legacy.py` / `gui_2.py`) only talks to the Orchestrator. The Orchestrator's system prompt is given access to tools like `call_deepseek_coder(prompt)` or `call_flash_reader(filepath)`.
|
||||
|
||||
This completely isolates your token bloat. The expensive models only process highly compressed summaries and orchestration logic, while the cheap models (DeepSeek/Flash) do the heavy, token-burning manual labor of reading and writing text. It keeps your telemetry clean, your costs incredibly low, and gives you the exact metric discipline you built the tool for in the first place.
|
||||
|
||||
@@ -809,13 +809,13 @@ Would you like to draft out the AST parser logic for the "Curated Implementation
|
||||
|
||||
# [User]
|
||||
|
||||
We'd use tree-sitter for all parsing. I want to focus on only scripting languages for now so it should be fine. You'd I guess curate from their based on what your saying. If you want an idea for how the gui currently works I'd suggest reading gui.py, but for this usage it would need to be overhauled as its only focused on single-agent use right now.
|
||||
We'd use tree-sitter for all parsing. I want to focus on only scripting languages for now so it should be fine. You'd I guess curate from their based on what your saying. If you want an idea for how the gui currently works I'd suggest reading gui_legacy.py, but for this usage it would need to be overhauled as its only focused on single-agent use right now.
|
||||
|
||||
# [AI]
|
||||
|
||||
Tree-sitter is the absolute best choice for this. It is incredibly fast, language-agnostic at the query level, and outputs an exact syntax tree that makes filtering out function bodies while preserving docstrings and class signatures mathematically precise, rather than relying on messy regex.
|
||||
|
||||
Transitioning `gui.py` from a single-agent chat box to a multi-agent control center is going to be the heaviest lift of this entire refactor. A single-agent UI assumes a linear flow: *User types -> UI waits -> LLM responds -> UI updates.* In a 4-Tier architecture, that linear flow is entirely destroyed. The Tier 1 PM might be waiting on you for a Track approval, while two Tier 3 Workers are simultaneously running local tests in the background, and a Tier 4 QA agent is silently fixing a linter error. If your GUI is not perfectly decoupled from the agent execution loops, the entire application will freeze the moment a second agent spawns.
|
||||
Transitioning `gui_legacy.py` from a single-agent chat box to a multi-agent control center is going to be the heaviest lift of this entire refactor. A single-agent UI assumes a linear flow: *User types -> UI waits -> LLM responds -> UI updates.* In a 4-Tier architecture, that linear flow is entirely destroyed. The Tier 1 PM might be waiting on you for a Track approval, while two Tier 3 Workers are simultaneously running local tests in the background, and a Tier 4 QA agent is silently fixing a linter error. If your GUI is not perfectly decoupled from the agent execution loops, the entire application will freeze the moment a second agent spawns.
|
||||
|
||||
Here is the blueprint for overhauling your GUI architecture to handle the `manual_slop` multi-model hierarchy without locking up the main thread.
|
||||
|
||||
@@ -858,7 +858,7 @@ If a test fails, the GUI simply renders a small inline badge in the Worker's log
|
||||
|
||||
### The Immediate Next Step
|
||||
|
||||
To avoid ripping `gui.py` entirely apart on day one, the safest path forward is to build the decoupled **Agent Bus (Message Queue)** in your `conductor` logic first. Once you can spawn dummy agents in a background python script and have them print their statuses to the console concurrently, wiring them up to a new multi-pane GUI becomes purely a frontend rendering task.
|
||||
To avoid ripping `gui_legacy.py` entirely apart on day one, the safest path forward is to build the decoupled **Agent Bus (Message Queue)** in your `conductor` logic first. Once you can spawn dummy agents in a background python script and have them print their statuses to the console concurrently, wiring them up to a new multi-pane GUI becomes purely a frontend rendering task.
|
||||
|
||||
# [User]
|
||||
|
||||
@@ -1084,7 +1084,7 @@ Here is how you architect this Global Execution Toggle into your new Conductor e
|
||||
|
||||
### 1. The Global Execution Toggle
|
||||
|
||||
This should be defined at the highest level of your application—ideally passed as a CLI argument when starting `manual_slop` (e.g., `uv run .\gui.py --mode=linear`) or set in a global `config.toml` so it overrides all individual agent trust levels.
|
||||
This should be defined at the highest level of your application—ideally passed as a CLI argument when starting `manual_slop` (e.g., `uv run .\gui_legacy.py --mode=linear`) or set in a global `config.toml` so it overrides all individual agent trust levels.
|
||||
|
||||
```toml
|
||||
# config.toml
|
||||
@@ -1193,7 +1193,7 @@ Here is the high-level structural diff: **Current State vs. Proposed Architectur
|
||||
|
||||
### 2. Execution Engine & Orchestration
|
||||
|
||||
* **Current State:** Linear, single-thread execution. `gui.py` or `gui_2.py` takes an input, calls `ai_client.py`, waits for the stream, and appends it to the global history. The current `conductor/` directory acts mostly as a wrapper/automation script for the Gemini CLI.
|
||||
* **Current State:** Linear, single-thread execution. `gui_legacy.py` or `gui_2.py` takes an input, calls `ai_client.py`, waits for the stream, and appends it to the global history. The current `conductor/` directory acts mostly as a wrapper/automation script for the Gemini CLI.
|
||||
* **Future State:** * A dedicated `state_machine.py` defining strict `Track` and `Ticket` dataclasses.
|
||||
* A decoupled `orchestrator.py` containing an asynchronous Event Bus (`asyncio.Queue`).
|
||||
* A Global Execution Toggle (`mode="async"` vs. `mode="linear"`) that can force the entire swarm to pause and run synchronously for debugging.
|
||||
|
||||
@@ -12,7 +12,7 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
|
||||
- `uv` - package/env management
|
||||
|
||||
**Files:**
|
||||
- `gui.py` - main GUI, `App` class, all panels, all callbacks, confirmation dialog, layout persistence, rich comms rendering; `[+ Maximize]` buttons in `ConfirmDialog` and `win_script_output` now pass text directly as `user_data` / read from `self._last_script` / `self._last_output` instance vars instead of `dpg.get_value(tag)` — fixes glitch when word-wrap is ON or dialog is dismissed before viewer opens
|
||||
- `gui_legacy.py` - main GUI, `App` class, all panels, all callbacks, confirmation dialog, layout persistence, rich comms rendering; `[+ Maximize]` buttons in `ConfirmDialog` and `win_script_output` now pass text directly as `user_data` / read from `self._last_script` / `self._last_output` instance vars instead of `dpg.get_value(tag)` — fixes glitch when word-wrap is ON or dialog is dismissed before viewer opens
|
||||
- `ai_client.py` - unified provider wrapper, model listing, session management, send, tool/function-call loop, comms log, provider error classification, token estimation, and aggressive history truncation
|
||||
- `aggregate.py` - reads config, collects files/screenshots/discussion, builds `file_items` with `mtime` for cache optimization, writes numbered `.md` files to `output_dir` using `build_markdown_from_items` to avoid double I/O; `run()` returns `(markdown_str, path, file_items)` tuple; `summary_only=False` by default (full file contents sent, not heuristic summaries)
|
||||
- `shell_runner.py` - subprocess wrapper that runs PowerShell scripts sandboxed to `base_dir`, returns stdout/stderr/exit code as a string
|
||||
@@ -79,7 +79,7 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
|
||||
- Both Gemini and Anthropic are configured with a `run_powershell` tool/function declaration
|
||||
- When the AI wants to edit or create files it emits a tool call with a `script` string
|
||||
- `ai_client` runs a loop (max `MAX_TOOL_ROUNDS = 10`) feeding tool results back until the AI stops calling tools
|
||||
- Before any script runs, `gui.py` shows a modal `ConfirmDialog` on the main thread; the background send thread blocks on a `threading.Event` until the user clicks Approve or Reject
|
||||
- Before any script runs, `gui_legacy.py` shows a modal `ConfirmDialog` on the main thread; the background send thread blocks on a `threading.Event` until the user clicks Approve or Reject
|
||||
- The dialog displays `base_dir`, shows the script in an editable text box (allowing last-second tweaks), and has Approve & Run / Reject buttons
|
||||
- On approval the (possibly edited) script is passed to `shell_runner.run_powershell()` which prepends `Set-Location -LiteralPath '<base_dir>'` and runs it via `powershell -NoProfile -NonInteractive -Command`
|
||||
- stdout, stderr, and exit code are returned to the AI as the tool result
|
||||
@@ -107,10 +107,10 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
|
||||
- Entry fields: `ts` (HH:MM:SS), `direction` (OUT/IN), `kind`, `provider`, `model`, `payload` (dict)
|
||||
- Anthropic responses also include `usage` (input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens) and `stop_reason` in payload
|
||||
- `get_comms_log()` returns a snapshot; `clear_comms_log()` empties it
|
||||
- `comms_log_callback` (injected by gui.py) is called from the background thread with each new entry; gui queues entries in `_pending_comms` (lock-protected) and flushes them to the DPG panel each render frame
|
||||
- `COMMS_CLAMP_CHARS = 300` in gui.py governs the display cutoff for heavy text fields
|
||||
- `comms_log_callback` (injected by gui_legacy.py) is called from the background thread with each new entry; gui queues entries in `_pending_comms` (lock-protected) and flushes them to the DPG panel each render frame
|
||||
- `COMMS_CLAMP_CHARS = 300` in gui_legacy.py governs the display cutoff for heavy text fields
|
||||
|
||||
**Comms History panel — rich structured rendering (gui.py):**
|
||||
**Comms History panel — rich structured rendering (gui_legacy.py):**
|
||||
|
||||
Rather than showing raw JSON, each comms entry is rendered using a kind-specific renderer function. Unknown kinds fall back to a generic key/value layout.
|
||||
|
||||
@@ -195,10 +195,10 @@ Entry layout: index + timestamp + direction + kind + provider/model header row,
|
||||
- Comms log: MCP tool calls log `OUT/tool_call` with `{"name": ..., "args": {...}}` and `IN/tool_result` with `{"name": ..., "output": ...}`; rendered in the Comms History panel via `_render_payload_tool_call` (shows each arg key/value) and `_render_payload_tool_result` (shows output)
|
||||
|
||||
**Known extension points:**
|
||||
- Add more providers by adding a section to `credentials.toml`, a `_list_*` and `_send_*` function in `ai_client.py`, and the provider name to the `PROVIDERS` list in `gui.py`
|
||||
- Add more providers by adding a section to `credentials.toml`, a `_list_*` and `_send_*` function in `ai_client.py`, and the provider name to the `PROVIDERS` list in `gui_legacy.py`
|
||||
- Discussion history excerpts could be individually toggleable for inclusion in the generated md
|
||||
- `MAX_TOOL_ROUNDS` in `ai_client.py` caps agentic loops at 10 rounds; adjustable
|
||||
- `COMMS_CLAMP_CHARS` in `gui.py` controls the character threshold for clamping heavy payload fields in the Comms History panel
|
||||
- `COMMS_CLAMP_CHARS` in gui_legacy.py controls the character threshold for clamping heavy payload fields in the Comms History panel
|
||||
- Additional project metadata (description, tags, created date) could be added to `[project]` in the per-project toml
|
||||
|
||||
### Gemini Context Management
|
||||
@@ -222,7 +222,7 @@ Entry layout: index + timestamp + direction + kind + provider/model header row,
|
||||
|
||||
|
||||
## Recent Changes (Text Viewer Maximization)
|
||||
- **Global Text Viewer (gui.py)**: Added a dedicated, large popup window (win_text_viewer) to allow reading and scrolling through large, dense text blocks without feeling cramped.
|
||||
- **Global Text Viewer (gui_legacy.py)**: Added a dedicated, large popup window (win_text_viewer) to allow reading and scrolling through large, dense text blocks without feeling cramped.
|
||||
- **Comms History**: Every multi-line text field in the comms log now has a [+] button next to its label that opens the text in the Global Text Viewer.
|
||||
- **Tool Log History**: Added [+ Script] and [+ Output] buttons next to each logged tool call to easily maximize and read the full executed scripts and raw tool outputs.
|
||||
- **Last Script Output Popup**: Expanded the default size of the popup (now 800x600) and gave the input script panel more vertical space to prevent it from feeling 'scrunched'. Added [+ Maximize] buttons for both the script and the output sections to inspect them in full detail.
|
||||
@@ -266,10 +266,10 @@ Documentation has been completely rewritten matching the strict, structural form
|
||||
### aggregate.py — run() double-I/O elimination
|
||||
- `run()` now calls `build_file_items()` once, then passes the result to `build_markdown_from_items()` instead of calling `build_files_section()` separately. This avoids reading every file twice per send.
|
||||
- `build_markdown_from_items()` accepts a `summary_only` flag (default `False`); when `False` it inlines full file content; when `True` it delegates to `summarize.build_summary_markdown()` for compact structural summaries.
|
||||
- `run()` returns a 3-tuple `(markdown_str, output_path, file_items)` — the `file_items` list is passed through to `gui.py` as `self.last_file_items` for dynamic context refresh after tool calls.
|
||||
- `run()` returns a 3-tuple `(markdown_str, output_path, file_items)` — the `file_items` list is passed through to `gui_legacy.py` as `self.last_file_items` for dynamic context refresh after tool calls.
|
||||
|
||||
|
||||
## Updates (2026-02-22 — gui.py [+ Maximize] bug fix)
|
||||
## Updates (2026-02-22 — gui_legacy.py [+ Maximize] bug fix)
|
||||
|
||||
### Problem
|
||||
Three `[+ Maximize]` buttons were reading their text content via `dpg.get_value(tag)` at click time:
|
||||
|
||||
@@ -41,5 +41,5 @@ api_key = "****"
|
||||
2. Have fun. This is experiemntal slop.
|
||||
|
||||
```ps1
|
||||
uv run .\gui.py
|
||||
uv run .\gui_legacy.py
|
||||
```
|
||||
|
||||
@@ -17,7 +17,7 @@ All synchronization between these boundaries is managed via lock-protected queue
|
||||
|
||||
### Lifetime & Application Boot
|
||||
|
||||
The application lifetime is localized within App.run in gui.py.
|
||||
The application lifetime is localized within App.run in gui_legacy.py.
|
||||
|
||||
1. __init__ parses the global config.toml (which sets the active provider, theme, and project paths).
|
||||
2. It immediately hands off to project_manager.py to deserialize the active <project>.toml which hydrates the session's files, discussion histories, and prompts.
|
||||
|
||||
@@ -36,7 +36,7 @@ The core manipulation mechanism. This is a single, heavily guarded tool.
|
||||
### Flow
|
||||
|
||||
1. The AI generates a 'run_powershell' payload containing a PowerShell script.
|
||||
2. The AI background thread calls confirm_and_run_callback (injected by gui.py).
|
||||
2. The AI background thread calls confirm_and_run_callback (injected by gui_legacy.py).
|
||||
3. The background thread blocks completely, creating a modal popup on the main GUI thread.
|
||||
4. The user reads the script and chooses to Approve or Reject.
|
||||
5. If Approved, shell_runner.py executes the script using -NoProfile -NonInteractive -Command within the specified base_dir.
|
||||
|
||||
@@ -45,7 +45,7 @@ _allowed_paths: set[Path] = set()
|
||||
_base_dirs: set[Path] = set()
|
||||
_primary_base_dir: Path | None = None
|
||||
|
||||
# Injected by gui.py - returns a dict of performance metrics
|
||||
# Injected by gui_legacy.py - returns a dict of performance metrics
|
||||
perf_monitor_callback = None
|
||||
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ def kill_process_tree(pid):
|
||||
except Exception as e:
|
||||
print(f"[Fixture] Error killing process tree {pid}: {e}")
|
||||
|
||||
@pytest.fixture(scope="session", params=["gui.py", "gui_2.py"])
|
||||
@pytest.fixture(scope="session", params=["gui_legacy.py", "gui_2.py"])
|
||||
def live_gui(request):
|
||||
"""
|
||||
Session-scoped fixture that starts a GUI script with --enable-test-hooks.
|
||||
|
||||
@@ -67,11 +67,11 @@ def test_performance_parity():
|
||||
"""
|
||||
Compare the metrics collected in the parameterized test_performance_benchmarking.
|
||||
"""
|
||||
if "gui.py" not in _shared_metrics or "gui_2.py" not in _shared_metrics:
|
||||
if "gui_legacy.py" not in _shared_metrics or "gui_2.py" not in _shared_metrics:
|
||||
if len(_shared_metrics) < 2:
|
||||
pytest.skip("Metrics for both GUIs not yet collected.")
|
||||
|
||||
gui_m = _shared_metrics["gui.py"]
|
||||
gui_m = _shared_metrics["gui_legacy.py"]
|
||||
gui2_m = _shared_metrics["gui_2.py"]
|
||||
|
||||
# FPS Parity Check (+/- 15% leeway for now, target is 5%)
|
||||
|
||||
Reference in New Issue
Block a user