Redesign AI auto-adjust UI with boxed section

- Move auto-adjust feature to a dedicated LineBox panel
- Add full editable prompt template with {code} placeholder
- Add scrollable output/feedback area showing AI responses
- Display success/error messages with provider info
- Side-by-side layout: Code editor on left, AI assist on right
- Increase dialog size to accommodate new layout (90x30)
- Default prompt shows available variables and clear instructions

The AI assist panel now shows:
- Provider selector with dropdown
- Editable prompt (user can customize the full AI instruction)
- Output area with status messages and error details
- Centered Auto-adjust button

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
rob 2025-12-05 01:27:22 -04:00
parent c4b5492dc7
commit bdaf9e48de
1 changed files with 61 additions and 37 deletions

View File

@ -1486,40 +1486,53 @@ class SmartToolsUI:
'button', 'button_focus' 'button', 'button_focus'
) )
adjust_instruction = urwid.Edit(('label', ""), "") # Default prompt template for AI code generation/adjustment
default_ai_prompt = f"""Modify or generate Python code according to my instruction below.
def on_auto_adjust(_): INSTRUCTION: [Describe what you want]
instruction = adjust_instruction.edit_text.strip()
if not instruction:
status_text.set_text(('error', "Enter an instruction for the AI"))
return
current_code = code_edit.edit_text.strip()
if not current_code:
status_text.set_text(('error', "No code to adjust"))
return
provider_name = selected_ai_provider[0]
status_text.set_text(('label', f"Calling {provider_name}..."))
self.refresh()
prompt = f"""Modify the following Python code according to this instruction:
INSTRUCTION: {instruction}
CURRENT CODE: CURRENT CODE:
```python ```python
{current_code} {{code}}
``` ```
AVAILABLE VARIABLES: {', '.join(vars_available)} AVAILABLE VARIABLES: {', '.join(vars_available)}
Return ONLY the modified Python code, no explanations or markdown fencing.""" Return ONLY the Python code, no explanations or markdown fencing."""
# Multiline editable prompt for AI
ai_prompt_edit = TabPassEdit(edit_text=default_ai_prompt, multiline=True)
ai_prompt_styled = urwid.AttrMap(ai_prompt_edit, 'edit', 'edit_focus')
ai_prompt_walker = urwid.SimpleFocusListWalker([ai_prompt_styled])
ai_prompt_listbox = urwid.ListBox(ai_prompt_walker)
ai_prompt_box = urwid.LineBox(ai_prompt_listbox, title="Prompt")
# Output/feedback area for AI responses
ai_output_text = urwid.Text("")
ai_output_walker = urwid.SimpleFocusListWalker([ai_output_text])
ai_output_listbox = urwid.ListBox(ai_output_walker)
ai_output_box = urwid.LineBox(ai_output_listbox, title="Output & Feedback")
def on_auto_adjust(_):
prompt_template = ai_prompt_edit.edit_text.strip()
if not prompt_template:
ai_output_text.set_text(('error', "Enter a prompt for the AI"))
return
current_code = code_edit.edit_text.strip()
# Replace {code} placeholder with actual code
prompt = prompt_template.replace("{code}", current_code)
provider_name = selected_ai_provider[0]
ai_output_text.set_text(('label', f"Calling {provider_name}...\nPlease wait..."))
self.refresh()
result = call_provider(provider_name, prompt) result = call_provider(provider_name, prompt)
if result.success: if result.success:
new_code = result.text.strip() new_code = result.text.strip()
# Strip markdown code fences if present
if new_code.startswith("```python"): if new_code.startswith("```python"):
new_code = new_code[9:] new_code = new_code[9:]
if new_code.startswith("```"): if new_code.startswith("```"):
@ -1529,14 +1542,31 @@ Return ONLY the modified Python code, no explanations or markdown fencing."""
new_code = new_code.strip() new_code = new_code.strip()
code_edit.set_edit_text(new_code) code_edit.set_edit_text(new_code)
status_text.set_text(('success', "Code updated by AI")) ai_output_text.set_text(('success', f"✓ Code updated successfully!\n\nProvider: {provider_name}\nResponse length: {len(result.text)} chars"))
else: else:
status_text.set_text(('error', f"AI error: {result.error[:50]}")) error_msg = result.error or "Unknown error"
ai_output_text.set_text(('error', f"✗ Error from {provider_name}:\n\n{error_msg}"))
auto_adjust_btn = urwid.AttrMap( auto_adjust_btn = urwid.AttrMap(
urwid.Button("Auto-adjust", on_auto_adjust), urwid.Button("Auto-adjust", on_auto_adjust),
'button', 'button_focus' 'button', 'button_focus'
) )
# Build the AI assist box with provider selector, prompt editor, output area, and button
ai_provider_row = urwid.Columns([
('pack', urwid.Text(('label', "Provider: "))),
('pack', ai_provider_btn),
('pack', ai_provider_select_btn),
])
ai_assist_content = urwid.Pile([
('pack', ai_provider_row),
('pack', urwid.Divider()),
('weight', 2, ai_prompt_box),
('weight', 1, ai_output_box),
('pack', urwid.Padding(auto_adjust_btn, align='center', width=16)),
])
ai_assist_box = urwid.LineBox(ai_assist_content, title="AI Assisted Auto-adjust")
# --- End Auto-adjust feature --- # --- End Auto-adjust feature ---
def do_load(): def do_load():
@ -1624,15 +1654,11 @@ Return ONLY the modified Python code, no explanations or markdown fencing."""
code_scrollbar = DOSScrollBar(code_listbox) code_scrollbar = DOSScrollBar(code_listbox)
code_box = urwid.LineBox(code_scrollbar, title="Code") code_box = urwid.LineBox(code_scrollbar, title="Code")
# Auto-adjust row # Layout: Code editor on left, AI assist box on right
auto_adjust_row = urwid.Columns([ main_columns = urwid.Columns([
('pack', ai_provider_btn), ('weight', 1, code_box),
('pack', ai_provider_select_btn), ('weight', 1, ai_assist_box),
('pack', urwid.Text(" ")), ], dividechars=1)
('weight', 1, urwid.AttrMap(adjust_instruction, 'edit', 'edit_focus')),
('pack', urwid.Text(" ")),
('pack', auto_adjust_btn),
])
# Use TabCyclePile so Tab cycles between sections # Use TabCyclePile so Tab cycles between sections
# Note: All flow widgets must be explicitly wrapped in ('pack', ...) when # Note: All flow widgets must be explicitly wrapped in ('pack', ...) when
@ -1646,16 +1672,14 @@ Return ONLY the modified Python code, no explanations or markdown fencing."""
('pack', load_btn), ('pack', load_btn),
])), ])),
('pack', status_text), ('pack', status_text),
('weight', 1, code_box), ('weight', 1, main_columns),
('pack', urwid.Divider()),
('pack', auto_adjust_row),
('pack', urwid.Divider()), ('pack', urwid.Divider()),
('pack', urwid.AttrMap(output_edit, 'edit', 'edit_focus')), ('pack', urwid.AttrMap(output_edit, 'edit', 'edit_focus')),
], tab_positions=[2, 4, 6, 8]) ], tab_positions=[2, 4, 6])
title = "Edit Code Step" if existing else "Add Code Step" title = "Edit Code Step" if existing else "Add Code Step"
dialog = Dialog(title, body, [("OK", on_ok), ("Cancel", on_cancel)]) dialog = Dialog(title, body, [("OK", on_ok), ("Cancel", on_cancel)])
self.show_overlay(dialog, width=70, height=24) self.show_overlay(dialog, width=90, height=30)
def _on_save_tool(self, _): def _on_save_tool(self, _):
"""Save the tool.""" """Save the tool."""