Agent scripting ux improvements

This commit is contained in:
2026-02-21 23:15:48 -05:00
parent caa67206fa
commit d7d0583b4e
3 changed files with 106 additions and 24 deletions

View File

@@ -1,4 +1,4 @@
# Manual Slop
# Manual Slop
## Summary
@@ -55,7 +55,7 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
- `_flush_to_project()` pulls widget values into `self.project` (the per-project dict) and serialises disc_entries into the active discussion's history list
- `_flush_to_config()` writes global settings ([ai], [theme], [projects]) into `self.config`
- `_save_active_project()` writes `self.project` to the active `.toml` path via `project_manager.save_project()`
- `_do_generate()` calls both flush methods, saves both files, then uses `project_manager.flat_config()` to produce the dict that `aggregate.run()` expects so `aggregate.py` needs zero changes
- `_do_generate()` calls both flush methods, saves both files, then uses `project_manager.flat_config()` to produce the dict that `aggregate.run()` expects — so `aggregate.py` needs zero changes
- Switching projects: saves current project, loads new one, refreshes all GUI state, resets AI session
- New project: file dialog for save path, creates default project structure, saves it, switches to it
@@ -71,8 +71,8 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
- Timestamps: each disc entry carries a `ts` field (ISO datetime); shown next to the role combo; new entries from `-> History` or `+ Entry` get `now_ts()`
**Entry serialisation (project_manager):**
- `entry_to_str(entry)` `"@<ts>\n<role>:\n<content>"` (or `"<role>:\n<content>"` if no ts)
- `str_to_entry(raw, roles)` parses optional `@<ts>` prefix, then role line, then content; returns `{role, content, collapsed, ts}`
- `entry_to_str(entry)` → `"@<ts>\n<role>:\n<content>"` (or `"<role>:\n<content>"` if no ts)
- `str_to_entry(raw, roles)` → parses optional `@<ts>` prefix, then role line, then content; returns `{role, content, collapsed, ts}`
- Round-trips correctly through TOML string arrays; handles legacy entries without timestamps
**AI Tool Use (PowerShell):**
@@ -92,7 +92,7 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
- For Gemini: files are re-read (updating the `file_items` list in place) but cannot be injected into tool results due to Gemini's structured function response format
- `_build_file_context_text(file_items)` formats the refreshed files as markdown code blocks (same format as the original context)
- The `tool_result_send` comms log entry filters out the injected text block (only logs actual `tool_result` entries) to keep the comms panel clean
- `file_items` flows from `aggregate.build_file_items()` `gui.py` `self.last_file_items` `ai_client.send(file_items=...)` `_send_anthropic(file_items=...)` / `_send_gemini(file_items=...)`
- `file_items` flows from `aggregate.build_file_items()` → `gui.py` `self.last_file_items` → `ai_client.send(file_items=...)` → `_send_anthropic(file_items=...)` / `_send_gemini(file_items=...)`
- System prompt updated to tell the AI: "the user's context files are automatically refreshed after every tool call, so you do NOT need to re-read files that are already provided in the <context> block"
**Anthropic bug fixes applied (session history):**
@@ -110,7 +110,7 @@ Is a local GUI tool for manually curating and sending context to AI APIs. It agg
- `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 History panel rich structured rendering (gui.py):**
**Comms History panel — rich structured rendering (gui.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.
@@ -120,18 +120,18 @@ Colour maps:
- Labels: grey `(180,180,180)`; values: near-white `(220,220,220)`; dict keys/indices: `(140,200,255)`; numbers/token counts: `(180,255,180)`; sub-headers: `(220,200,120)`
Helper functions:
- `_add_text_field(parent, label, value)` labelled text; strings longer than `COMMS_CLAMP_CHARS` render as an 80px readonly scrollable `input_text`; shorter strings render as `add_text`
- `_add_kv_row(parent, key, val)` single horizontal key: value row
- `_render_usage(parent, usage)` renders Anthropic token usage dict in a fixed display order (input cache_read cache_creation output)
- `_render_tool_calls_list(parent, tool_calls)` iterates tool call list, showing name, id, and all args via `_add_text_field`
- `_add_text_field(parent, label, value)` — labelled text; strings longer than `COMMS_CLAMP_CHARS` render as an 80px readonly scrollable `input_text`; shorter strings render as `add_text`
- `_add_kv_row(parent, key, val)` — single horizontal key: value row
- `_render_usage(parent, usage)` — renders Anthropic token usage dict in a fixed display order (input → cache_read → cache_creation → output)
- `_render_tool_calls_list(parent, tool_calls)` — iterates tool call list, showing name, id, and all args via `_add_text_field`
Kind-specific renderers (in `_KIND_RENDERERS` dict, dispatched by `_render_comms_entry`):
- `_render_payload_request` shows `message` field via `_add_text_field`
- `_render_payload_response` shows round, stop_reason (orange), text, tool_calls list, usage block
- `_render_payload_tool_call` shows name, optional id, script via `_add_text_field`
- `_render_payload_tool_result` shows name, optional id, output via `_add_text_field`
- `_render_payload_tool_result_send` iterates results list, shows tool_use_id and content per result
- `_render_payload_generic` fallback for unknown kinds; renders all keys, using `_add_text_field` for keys in `_HEAVY_KEYS`, `_add_kv_row` for others; dicts/lists are JSON-serialised
- `_render_payload_request` — shows `message` field via `_add_text_field`
- `_render_payload_response` — shows round, stop_reason (orange), text, tool_calls list, usage block
- `_render_payload_tool_call` — shows name, optional id, script via `_add_text_field`
- `_render_payload_tool_result` — shows name, optional id, output via `_add_text_field`
- `_render_payload_tool_result_send` — iterates results list, shows tool_use_id and content per result
- `_render_payload_generic` — fallback for unknown kinds; renders all keys, using `_add_text_field` for keys in `_HEAVY_KEYS`, `_add_kv_row` for others; dicts/lists are JSON-serialised
Entry layout: index + timestamp + direction + kind + provider/model header row, then payload rendered by the appropriate function, then a separator line.
@@ -158,8 +158,8 @@ Entry layout: index + timestamp + direction + kind + provider/model header row,
8. Sessions are stateful within a run (chat history maintained), `Reset` clears them, the tool log, and the comms log
**Config persistence:**
- `config.toml` global only: `[ai]` provider+model, `[theme]` palette+font+scale, `[projects]` paths array + active path
- `<project>.toml` per-project: output, files, screenshots, discussion (roles, active discussion name, all named discussions with their history+metadata)
- `config.toml` — global only: `[ai]` provider+model, `[theme]` palette+font+scale, `[projects]` paths array + active path
- `<project>.toml` — per-project: output, files, screenshots, discussion (roles, active discussion name, all named discussions with their history+metadata)
- On every send and save, both files are written
- On clean exit, `run()` calls `_flush_to_project()`, `_save_active_project()`, `_flush_to_config()`, `save_config()` before destroying context
@@ -181,11 +181,11 @@ Entry layout: index + timestamp + direction + kind + provider/model header row,
- `mcp_client.dispatch(tool_name, tool_input)` is the single dispatch entry point used by both Anthropic and Gemini tool-use loops
- Anthropic: MCP tools appear before `run_powershell` in the tools list (no `cache_control` on them; only `run_powershell` carries `cache_control: ephemeral`)
- Gemini: MCP tools are included in the `FunctionDeclaration` list alongside `run_powershell`
- `get_file_summary` uses `summarize.summarise_file()` same heuristic used for the initial `<context>` block, so the AI gets the same compact structural view it already knows
- `get_file_summary` uses `summarize.summarise_file()` — same heuristic used for the initial `<context>` block, so the AI gets the same compact structural view it already knows
- `list_directory` sorts dirs before files; shows name, type, and size
- `search_files` uses `Path.glob()` with the caller-supplied pattern (supports `**/*.py` style)
- `read_file` returns raw UTF-8 text; errors (not found, access denied, decode error) are returned as error strings rather than exceptions, so the AI sees them as tool results
- `summarize.py` heuristics: `.py` AST imports + ALL_CAPS constants + classes+methods + top-level functions; `.toml` table headers + top-level keys; `.md` → h1h3 headings with indentation; all others line count + first 8 lines preview
- `summarize.py` heuristics: `.py` → AST imports + ALL_CAPS constants + classes+methods + top-level functions; `.toml` → table headers + top-level keys; `.md` → h1–h3 headings with indentation; all others → line count + first 8 lines preview
- 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:**
@@ -205,3 +205,7 @@ Entry layout: index + timestamp + direction + kind + provider/model header row,
- `output_dir` was moved into the Projects panel.
- `auto_add_history` was moved to the Discussion History panel.
- `namespace` is no longer a configurable field; `aggregate.py` automatically uses the active project's `name` property.
### UI / Visual Updates
- The success blink notification on the response text box is now dimmer and more transparent to be less visually jarring.
- Added a new floating **Last Script Output** popup window. This window automatically displays and blinks blue whenever the AI executes a PowerShell tool, showing both the executed script and its result in real-time.