amazing
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
|
||||
**Files:**
|
||||
- `gui.py` - main GUI, `App` class, all panels, all callbacks, confirmation dialog, layout persistence
|
||||
- `ai_client.py` - unified provider wrapper, model listing, session management, send, tool/function-call loop
|
||||
- `ai_client.py` - unified provider wrapper, model listing, session management, send, tool/function-call loop, comms log
|
||||
- `aggregate.py` - reads config, collects files/screenshots/discussion, writes numbered `.md` files to `output_dir`
|
||||
- `shell_runner.py` - subprocess wrapper that runs PowerShell scripts sandboxed to `base_dir`, returns stdout/stderr/exit code as a string
|
||||
- `config.toml` - namespace, output_dir, files paths+base_dir, screenshots paths+base_dir, discussion history array, ai provider+model
|
||||
@@ -23,10 +23,11 @@
|
||||
- **Files** - base_dir, scrollable path list with remove, add file(s), add wildcard
|
||||
- **Screenshots** - base_dir, scrollable path list with remove, add screenshot(s)
|
||||
- **Discussion History** - multiline text box, `---` as separator between excerpts, save splits on `---` back into toml array
|
||||
- **Provider** - provider combo (gemini/anthropic), model listbox populated from API, fetch models button, status line
|
||||
- **Provider** - provider combo (gemini/anthropic), model listbox populated from API, fetch models button
|
||||
- **Message** - multiline input, Gen+Send button, MD Only button, Reset session button
|
||||
- **Response** - readonly multiline displaying last AI response
|
||||
- **Tool Calls** - scrollable log of every PowerShell tool call the AI made, showing script and result; Clear button
|
||||
- **Comms History** - live log of every raw request/response/tool_call/tool_result exchanged with the vendor API; status line lives here; Clear button; heavy fields (message, text, script, output) clamped to an 80px scrollable box when they exceed `COMMS_CLAMP_CHARS` (300) characters
|
||||
|
||||
**Layout persistence:**
|
||||
- `dpg.configure_app(..., init_file="dpg_layout.ini")` loads the ini at startup if it exists; DPG silently ignores a missing file
|
||||
@@ -42,11 +43,26 @@
|
||||
- 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
|
||||
- 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`
|
||||
- Every script (original, before Set-Location is prepended) is saved to ./scripts/generated/ai_<timestamp>.ps1 before execution; the saved path appears in the tool result
|
||||
- stdout, stderr, and exit code are returned to the AI as the tool result
|
||||
- Rejections return `"USER REJECTED: command was not executed"` to the AI
|
||||
- All tool calls (script + result/rejection) are appended to `_tool_log` and displayed in the Tool Calls panel
|
||||
|
||||
**Comms Log (ai_client.py):**
|
||||
- `_comms_log: list[dict]` accumulates every API interaction during a session
|
||||
- `_append_comms(direction, kind, payload)` called at each boundary: OUT/request before sending, IN/response after each model reply, OUT/tool_call before executing, IN/tool_result after executing, OUT/tool_result_send when returning results to the model
|
||||
- Entry fields: `ts` (HH:MM:SS), `direction` (OUT/IN), `kind`, `provider`, `model`, `payload` (dict)
|
||||
- Anthropic responses also include `usage` (input_tokens/output_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
|
||||
- `MAX_FIELD_CHARS = 400` in ai_client is the threshold used for the clamp decision in the UI (`COMMS_CLAMP_CHARS = 300` in gui.py governs the display cutoff)
|
||||
|
||||
**Comms History panel rendering:**
|
||||
- Each entry shows: index, timestamp, direction (colour-coded blue=OUT / green=IN), kind (colour-coded), provider/model
|
||||
- Payload fields rendered below the header; fields in `_HEAVY_KEYS` (`message`, `text`, `script`, `output`, `content`) that exceed `COMMS_CLAMP_CHARS` are shown in an 80px tall readonly scrollable `input_text` box instead of a plain `add_text`
|
||||
- Colour legend row at the top of the panel
|
||||
- Status line (formerly in Provider panel) moved to top of Comms History panel
|
||||
- Reset session also clears the comms log and panel; Clear button in Comms History clears only the comms log
|
||||
|
||||
**Data flow:**
|
||||
1. GUI edits are held in `App` state lists (`self.files`, `self.screenshots`, `self.history`) and dpg widget values
|
||||
2. `_flush_to_config()` pulls all widget values into `self.config` dict
|
||||
@@ -54,7 +70,7 @@
|
||||
4. `cb_generate_send()` calls `_do_generate()` then threads a call to `ai_client.send(md, message, base_dir)`
|
||||
5. `ai_client.send()` prepends the md as a `<context>` block to the user message and sends via the active provider chat session
|
||||
6. If the AI responds with tool calls, the loop handles them (with GUI confirmation) before returning the final text response
|
||||
7. Sessions are stateful within a run (chat history maintained), `Reset` clears them and the tool log
|
||||
7. Sessions are stateful within a run (chat history maintained), `Reset` clears them, the tool log, and the comms log
|
||||
|
||||
**Config persistence:**
|
||||
- Every send and save writes `config.toml` with current state including selected provider and model under `[ai]`
|
||||
@@ -66,9 +82,11 @@
|
||||
- AI sends and model fetches run on daemon background threads
|
||||
- `_pending_dialog` (guarded by a `threading.Lock`) is set by the background thread and consumed by the render loop each frame, calling `dialog.show()` on the main thread
|
||||
- `dialog.wait()` blocks the background thread on a `threading.Event` until the user acts
|
||||
- `_pending_comms` (guarded by a separate `threading.Lock`) is populated by `_on_comms_entry` (background thread) and drained by `_flush_pending_comms()` each render frame (main thread)
|
||||
|
||||
**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`
|
||||
- System prompt support could be added as a field in `config.toml` and passed in `ai_client.send()`
|
||||
- Discussion history excerpts could be individually toggleable for inclusion in the generated md
|
||||
- `MAX_TOOL_ROUNDS` in `ai_client.py` caps agentic loops at 5 rounds; adjustable
|
||||
- `COMMS_CLAMP_CHARS` in `gui.py` controls the character threshold for clamping heavy payload fields
|
||||
|
||||
Reference in New Issue
Block a user