layout persistence

This commit is contained in:
2026-02-21 15:28:03 -05:00
parent 8380d85bc2
commit 308070e885
4 changed files with 97 additions and 6 deletions

View File

@@ -1,4 +1,6 @@
**manual_slop** is a local GUI tool for manually curating and sending context to AI APIs. It aggregates files, screenshots, and discussion history into a structured markdown file and sends it to a chosen AI provider with a user-written message. The AI can also execute PowerShell scripts within the project directory, with user confirmation required before each execution. Make sure to update this file every time.
**manual_slop** is a local GUI tool for manually curating and sending context to AI APIs. It aggregates files, screenshots, and discussion history into a structured markdown file and sends it to a chosen AI provider with a user-written message. The AI can also execute PowerShell scripts within the project directory, with user confirmation required before each execution.
**Stack:** **Stack:**
- `dearpygui` - GUI with docking/floating/resizable panels - `dearpygui` - GUI with docking/floating/resizable panels
@@ -8,12 +10,13 @@
- `uv` - package/env management - `uv` - package/env management
**Files:** **Files:**
- `gui.py` - main GUI, `App` class, all panels, all callbacks, confirmation dialog - `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
- `aggregate.py` - reads config, collects files/screenshots/discussion, writes numbered `.md` files to `output_dir` - `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 - `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 - `config.toml` - namespace, output_dir, files paths+base_dir, screenshots paths+base_dir, discussion history array, ai provider+model
- `credentials.toml` - gemini api_key, anthropic api_key - `credentials.toml` - gemini api_key, anthropic api_key
- `dpg_layout.ini` - Dear PyGui window layout file (auto-saved on exit, auto-loaded on startup); gitignore this per-user
**GUI Panels:** **GUI Panels:**
- **Config** - namespace, output dir, save - **Config** - namespace, output dir, save
@@ -25,6 +28,13 @@
- **Response** - readonly multiline displaying last AI response - **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 - **Tool Calls** - scrollable log of every PowerShell tool call the AI made, showing script and result; Clear button
**Layout persistence:**
- `dpg.configure_app(..., init_file="dpg_layout.ini")` loads the ini at startup if it exists; DPG silently ignores a missing file
- `dpg.save_init_file("dpg_layout.ini")` is called immediately before `dpg.destroy_context()` on clean exit
- The ini records window positions, sizes, and dock node assignments in DPG's native format
- First run (no ini) uses the hardcoded `pos=` defaults in `_build_ui()`; after that the ini takes over
- Delete `dpg_layout.ini` to reset to defaults
**AI Tool Use (PowerShell):** **AI Tool Use (PowerShell):**
- Both Gemini and Anthropic are configured with a `run_powershell` tool/function declaration - 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 - When the AI wants to edit or create files it emits a tool call with a `script` string
@@ -62,4 +72,3 @@
- System prompt support could be added as a field in `config.toml` and passed in `ai_client.send()` - 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 - 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 - `MAX_TOOL_ROUNDS` in `ai_client.py` caps agentic loops at 5 rounds; adjustable

View File

@@ -17,10 +17,16 @@ paths = [
[screenshots] [screenshots]
base_dir = "C:/Users/Ed/scoop/apps/sharex/current/ShareX/Screenshots/2026-02" base_dir = "C:/Users/Ed/scoop/apps/sharex/current/ShareX/Screenshots/2026-02"
paths = [] paths = [
"C:/Users/Ed/scoop/apps/sharex/current/ShareX/Screenshots/2026-02/python_2026-02-21_15-24-31.png",
]
[discussion] [discussion]
history = [] history = [
"Update the MainContext.md with latest state of codebase. Add support for preserving layout in imgui.",
"[NO response from claude-sonnet-4-6]",
"No code changed but you ran several scripts, whats going on...",
]
[ai] [ai]
provider = "anthropic" provider = "anthropic"

75
dpg_layout.ini Normal file
View File

@@ -0,0 +1,75 @@
[Window][WindowOverViewport_11111111]
Pos=0,0
Size=3840,2137
Collapsed=0
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][###22]
Pos=0,0
Size=376,652
Collapsed=0
DockId=0x00000005,0
[Window][###30]
Pos=0,654
Size=376,835
Collapsed=0
DockId=0x00000009,0
[Window][###66]
Pos=0,1491
Size=376,646
Collapsed=0
DockId=0x0000000A,0
[Window][###79]
Pos=1209,0
Size=968,2137
Collapsed=0
DockId=0x0000000B,0
[Window][###96]
Pos=2179,0
Size=1661,630
Collapsed=0
DockId=0x0000000D,0
[Window][###105]
Pos=378,494
Size=829,1643
Collapsed=0
DockId=0x00000008,0
[Window][###103]
Pos=2179,632
Size=1661,1505
Collapsed=0
DockId=0x0000000E,0
[Window][###86]
Pos=378,0
Size=829,492
Collapsed=0
DockId=0x00000007,0
[Docking][Data]
DockSpace ID=0x7C6B3D9B Window=0xA87D555D Pos=0,0 Size=3840,2137 Split=X Selected=0x40484D8F
DockNode ID=0x00000003 Parent=0x7C6B3D9B SizeRef=376,1161 Split=Y Selected=0xEE087978
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=235,354 Selected=0xEE087978
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=235,805 Split=Y Selected=0x5F94F9BD
DockNode ID=0x00000009 Parent=0x00000006 SizeRef=235,453 Selected=0x5F94F9BD
DockNode ID=0x0000000A Parent=0x00000006 SizeRef=235,350 Selected=0x80199DAE
DockNode ID=0x00000004 Parent=0x7C6B3D9B SizeRef=1286,1161 Split=X
DockNode ID=0x00000001 Parent=0x00000004 SizeRef=829,1161 Split=Y Selected=0x40484D8F
DockNode ID=0x00000007 Parent=0x00000001 SizeRef=595,492 Selected=0xBA13FCDE
DockNode ID=0x00000008 Parent=0x00000001 SizeRef=595,1643 CentralNode=1 Selected=0x40484D8F
DockNode ID=0x00000002 Parent=0x00000004 SizeRef=2631,1161 Split=X Selected=0x714F2F7B
DockNode ID=0x0000000B Parent=0x00000002 SizeRef=968,1161 Selected=0xC915D9DA
DockNode ID=0x0000000C Parent=0x00000002 SizeRef=1661,1161 Split=Y Selected=0x714F2F7B
DockNode ID=0x0000000D Parent=0x0000000C SizeRef=396,342 Selected=0x714F2F7B
DockNode ID=0x0000000E Parent=0x0000000C SizeRef=396,817 Selected=0xCF08B82F

3
gui.py
View File

@@ -598,7 +598,7 @@ class App:
def run(self): def run(self):
dpg.create_context() dpg.create_context()
dpg.configure_app(docking=True, docking_space=True) dpg.configure_app(docking=True, docking_space=True, init_file="dpg_layout.ini")
dpg.create_viewport(title="manual slop", width=1680, height=1200) dpg.create_viewport(title="manual slop", width=1680, height=1200)
dpg.setup_dearpygui() dpg.setup_dearpygui()
dpg.show_viewport() dpg.show_viewport()
@@ -616,6 +616,7 @@ class App:
dpg.render_dearpygui_frame() dpg.render_dearpygui_frame()
dpg.save_init_file("dpg_layout.ini")
dpg.destroy_context() dpg.destroy_context()