From 34ed257cd61d7acc9a4c7ffc5f27e33dfcb7c1f2 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 22 Feb 2026 09:38:31 -0500 Subject: [PATCH] corrections --- docs/Readme.md | 11 +++++++++++ docs/guide_architecture.md | 25 +++++++++++++------------ docs/guide_tools.md | 24 +++++++++++++----------- shell_runner.py | 3 ++- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/docs/Readme.md b/docs/Readme.md index 76f8b55..9b558f4 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -5,20 +5,26 @@ A GUI orchestrator for local LLM-driven coding sessions, built to prevent the AI ## Core Management Panels ### Projects Panel + The heart of context management. + - **Configuration:** You specify the Git Directory (for commit tracking) and a Main Context File (the markdown file containing your project's notes and schema). - **Word-Wrap Toggle:** Dynamically swaps text rendering in large read-only panels (Responses, Comms Log) between unwrapped (ideal for viewing precise code formatting) and wrapped (ideal for prose). - **Project Switching:** Switch between different .toml profiles to instantly swap out your entire active file list, discussion history, and settings. ### Discussion History + Manages your conversational branches, preventing context poisoning across different tasks. + - **Discussions Sub-Menu:** Allows you to create separate timelines for different tasks (e.g., "Refactoring Auth" vs. "Adding API Endpoints"). - **Git Commit Tracking:** Clicking "Update Commit" reads HEAD from your project's git directory and stamps the discussion. - **Entry Management:** Each turn has a Role (User, AI, System). You can toggle entries between **Read** and **Edit** modes, collapse them, or hit [+ Max] to open them in the Global Text Viewer. - **Auto-Add:** If toggled, anything sent from the "Message" panel and returned to the "Response" panel is automatically appended to the current discussion history. ### Files & Screenshots + Controls what is explicitly fed into the context compiler. + - **Base Dir:** Defines the root for path resolution and tool constraints. - **Paths:** Explicit files or wildcard globs (e.g., src/**/*.rs). - When generating a request, these files are summarized symbolically (summarize.py) to conserve tokens, unless the AI explicitly decides to read their full contents via its internal tools. @@ -26,20 +32,25 @@ Controls what is explicitly fed into the context compiler. ## Interaction Panels ### Provider + Switch between API backends (Gemini, Anthropic) on the fly. Clicking "Fetch Models" queries the active provider for the latest model list. ### Message & Response + - **Message:** Your input field. - **Gen + Send:** Compiles the markdown context and dispatches the background thread to the AI. - **MD Only:** Dry-runs the compiler so you can inspect the generated _00N.md without triggering an API charge. - **Response:** The read-only output. Flashes green when a new response arrives. ### Global Text Viewer & Script Outputs + - **Last Script Output:** Whenever the AI executes a background script, this window pops up, flashing blue. It contains both the executed script and the stdout/stderr. - **Text Viewer:** A large, resizable global popup invoked anytime you click a [+] or [+ Maximize] button in the UI. Used for deep-reading long logs, discussion entries, or script bodies. ## System Prompts + Provides two text inputs for overriding default instructions: + 1. **Global:** Applied across every project you load. 2. **Project:** Specific to the active workspace. These are concatenated onto the strict tool-usage guidelines the agent is initialized with. diff --git a/docs/guide_architecture.md b/docs/guide_architecture.md index a7d334b..d72c47e 100644 --- a/docs/guide_architecture.md +++ b/docs/guide_architecture.md @@ -28,18 +28,19 @@ The application lifetime is localized within App.run in gui.py. ### Context Shaping & Aggregation Before making a call to an AI Provider, the current state of the workspace is resolved into a dense Markdown representation. -This occurs inside ggregate.run. +This occurs inside aggregate.run. -If using the default workflow, ggregate.py hashes through the following process: -1. **Glob Resolution:** Iterates through config["files"]["paths"] and unpacks any wildcards (e.g., src/**/*.rs) against the designated ase_dir. +If using the default workflow, aggregate.py hashes through the following process: + +1. **Glob Resolution:** Iterates through config["files"]["paths"] and unpacks any wildcards (e.g., src/**/*.rs) against the designated base_dir. 2. **Summarization Pass:** Instead of concatenating raw file bodies (which would quickly overwhelm the ~200k token limit over multiple rounds), the files are passed to summarize.py. -3. **AST Parsing:** summarize.py runs a heuristic pass. For Python files, it uses the standard st module to read structural nodes (Classes, Methods, Imports, Constants). It outputs a compact Markdown table. +3. **AST Parsing:** summarize.py runs a heuristic pass. For Python files, it uses the standard ast module to read structural nodes (Classes, Methods, Imports, Constants). It outputs a compact Markdown table. 4. **Markdown Generation:** The final _00N.md string is constructed, comprising the truncated AST summaries, the user's current project system prompt, and the active discussion branch. 5. The Markdown file is persisted to disk (./md_gen/ by default) for auditing. ### AI Communication & The Tool Loop -The communication model is unified under i_client.py, which normalizes the Gemini and Anthropic SDKs into a singular interface send(md_content, user_message, base_dir, file_items). +The communication model is unified under ai_client.py, which normalizes the Gemini and Anthropic SDKs into a singular interface send(md_content, user_message, base_dir, file_items). The loop is defined as follows: @@ -55,24 +56,23 @@ The loop is defined as follows: ### On Tool Execution & Concurrency -When the AI calls a safe MCP tool (like -ead_file or search_files), the daemon thread immediately executes it via mcp_client.py and returns the result. +When the AI calls a safe MCP tool (like read_file or search_files), the daemon thread immediately executes it via mcp_client.py and returns the result. -However, when the AI requests -un_powershell, the operation halts: +However, when the AI requests run_powershell, the operation halts: -1. The Daemon Thread instantiates a ConfirmDialog object containing the payload and calls .wait(). This blocks the thread on a hreading.Event(). +1. The Daemon Thread instantiates a ConfirmDialog object containing the payload and calls .wait(). This blocks the thread on a threading.Event(). 2. The ConfirmDialog instance is safely placed in a _pending_dialog_lock. 3. The Main Thread, during its next frame cycle, pops the dialog from the lock and renders an OS-level modal window using dpg.window(modal=True). 4. The user can inspect the script, modify it in the text box, or reject it entirely. -5. Upon the user clicking "Approve & Run", the main thread triggers the hreading.Event, unblocking the Daemon Thread. +5. Upon the user clicking "Approve & Run", the main thread triggers the threading.Event, unblocking the Daemon Thread. 6. The Daemon Thread passes the script to shell_runner.py, captures stdout, stderr, and exit_code, logs it to session_logger.py, and returns it to the LLM. ### On Context History Pruning (Anthropic) Because the Anthropic API requires sending the entire conversation history on every request, long sessions will inevitably hit the invalid_request_error: prompt is too long. -To solve this, i_client.py implements an aggressive pruning algorithm: +To solve this, ai_client.py implements an aggressive pruning algorithm: + 1. _strip_stale_file_refreshes: It recursively sweeps backward through the history dict and strips out large [FILES UPDATED] data blocks from old turns, preserving only the most recent snapshot. 2. _trim_anthropic_history: If the estimated token count still exceeds _ANTHROPIC_MAX_PROMPT_TOKENS (~180,000), it slices off the oldest user/assistant message pairs from the beginning of the history array. 3. The loop guarantees that at least the System prompt, Tool Definitions, and the final user prompt are preserved. @@ -80,6 +80,7 @@ To solve this, i_client.py implements an aggressive pruning algorithm: ### Session Persistence All I/O bound session data is recorded sequentially. session_logger.py hooks into the execution loops and records: + - logs/comms_.log: A JSON-L structured timeline of every raw payload sent/received. - logs/toolcalls_.log: A sequential markdown record detailing every AI tool invocation and its exact stdout result. - scripts/generated/: Every .ps1 script approved and executed by the shell runner is physically written to disk for version control transparency. diff --git a/docs/guide_tools.md b/docs/guide_tools.md index 81d66a0..ec02adc 100644 --- a/docs/guide_tools.md +++ b/docs/guide_tools.md @@ -11,38 +11,40 @@ The agent is provided two classes of tools: Read-Only MCP Tools, and a Destructi Implemented in mcp_client.py. These tools allow the AI to selectively expand its knowledge of the codebase without requiring the user to dump entire 10,000-line files into the static context prefix. ### Security & Scope + Every filesystem MCP tool passes its arguments through _resolve_and_check. This function ensures that the requested path falls under one of the allowed directories defined in the GUI's Base Dir configurations. If the AI attempts to read or search a path outside the project bounds, the tool safely catches the constraint violation and returns ACCESS DENIED. ### Supplied Tools: -* -ead_file(path): Returns the raw UTF-8 text of a file. + +* read_file(path): Returns the raw UTF-8 text of a file. * list_directory(path): Returns a formatted table of a directory's contents, showing file vs dir and byte sizes. * search_files(path, pattern): Executes an absolute glob search (e.g., **/*.py) to find specific files. * get_file_summary(path): Invokes the local summarize.py heuristic parser to get the AST structure of a file without reading the whole body. * web_search(query): Queries DuckDuckGo's raw HTML endpoint and returns the top 5 results (Titles, URLs, Snippets) using a native HTMLParser to avoid heavy dependencies. -* etch_url(url): Downloads a target webpage and strips out all scripts, styling, and structural HTML, returning only the raw prose content (clamped to 40,000 characters). +* fetch_url(url): Downloads a target webpage and strips out all scripts, styling, and structural HTML, returning only the raw prose content (clamped to 40,000 characters). -## 2. Destructive Execution ( -un_powershell) +## 2. Destructive Execution (run_powershell) The core manipulation mechanism. This is a single, heavily guarded tool. ### Flow -1. The AI generates a -un_powershell payload containing a PowerShell script. + +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). 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 ase_dir. +5. If Approved, shell_runner.py executes the script using -NoProfile -NonInteractive -Command within the specified base_dir. 6. The combined stdout, stderr, and EXIT CODE are captured and returned to the AI in the tool result block. ### AI Guidelines + The core system prompt explicitly guides the AI on how to use this tool safely: + * Prefer targeted replacements (using PowerShell's .Replace()) over full rewrites where possible. * If a file is large and complex (requiring specific escape characters), do not attempt an inline python -c script. Instead, use a PowerShell here-string (@'...'@) to write a temporary python helper script to disk, execute the python script, and then delete it. ### Synthetic Context Refresh -Immediately after **any** tool call turn finishes, i_client runs _reread_file_items. It fetches the latest disk state of all files in the current project context and appends them as a synthetic [FILES UPDATED] message to the tool result. -This means if the AI writes to a file, it instantly "sees" the modification in its next turn without having to waste a cycle calling -ead_file. + +Immediately after **any** tool call turn finishes, ai_client runs _reread_file_items. It fetches the latest disk state of all files in the current project context and appends them as a synthetic [FILES UPDATED] message to the tool result. +This means if the AI writes to a file, it instantly "sees" the modification in its next turn without having to waste a cycle calling read_file. diff --git a/shell_runner.py b/shell_runner.py index 0615875..d920776 100644 --- a/shell_runner.py +++ b/shell_runner.py @@ -1,4 +1,5 @@ -import subprocess, shutil +# shell_runner.py +import subprocess, shutil from pathlib import Path TIMEOUT_SECONDS = 60