Add registry sort/pagination features and improve code step dialog

Registry:
- Add owner and rating sort options to both server endpoints
- Add letter-based prefix filtering (A-Z, #) with server-side validation
- LEFT JOIN tool_stats for average_rating/rating_count in responses
- Add interactive numbered page buttons with sliding window and ellipsis
- Add letter bar UI (shown when sorting by name) with highlight state
- Auto-select asc/desc order based on sort field
- Disable cell editing on results table
- Client: add order and prefix params to list_tools/search_tools

Code step dialog:
- Split AI prompt into user instruction input and collapsible wrapper
- User types plain instruction, wrapper is hidden by default
- Injection of user text into wrapper via {user_instruction} placeholder
- Increase dialog minimum height to 750px

Runner:
- Support variable substitution in prompt step provider name

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
rob
2026-01-30 01:35:03 -04:00
co-authored by Claude Opus 4.5
parent 0ee21f27f7
commit b00115a52e
5 changed files with 330 additions and 37 deletions
+42 -13
View File
@@ -177,7 +177,7 @@ class CodeStepDialog(QDialog):
def __init__(self, parent, step: CodeStep = None, available_vars: list = None):
super().__init__(parent)
self.setWindowTitle("Edit Code Step" if step else "Add Code Step")
self.setMinimumSize(900, 600)
self.setMinimumSize(900, 750)
self._step = step
self._available_vars = available_vars or ["input"]
self._worker = None
@@ -254,16 +254,30 @@ class CodeStepDialog(QDialog):
provider_layout.addStretch()
ai_layout.addLayout(provider_layout)
# Prompt editor
prompt_label = QLabel("Describe what you want the code to do:")
ai_layout.addWidget(prompt_label)
# User instruction input (always visible)
instruction_label = QLabel("Describe what you want the code to do:")
ai_layout.addWidget(instruction_label)
self.ai_prompt_input = QPlainTextEdit()
self.ai_prompt_input.setPlaceholderText(
self.user_instruction_input = QPlainTextEdit()
self.user_instruction_input.setPlaceholderText(
"Example: Parse the input as JSON and extract the 'name' field"
)
# Set default prompt template
self.user_instruction_input.setMaximumHeight(100)
ai_layout.addWidget(self.user_instruction_input, 1)
# Collapsible prompt wrapper section
self.wrapper_toggle = QPushButton("Edit prompt wrapper ▶")
self.wrapper_toggle.setFlat(True)
self.wrapper_toggle.setStyleSheet(
"QPushButton { color: #4a5568; font-size: 12px; text-align: left; "
"padding: 2px 0; } QPushButton:hover { color: #2d3748; }"
)
self.wrapper_toggle.clicked.connect(self._toggle_wrapper)
ai_layout.addWidget(self.wrapper_toggle)
self.ai_prompt_input = QPlainTextEdit()
self._set_default_prompt()
self.ai_prompt_input.hide()
ai_layout.addWidget(self.ai_prompt_input, 2)
# Generate button
@@ -306,6 +320,15 @@ class CodeStepDialog(QDialog):
layout.addLayout(buttons)
def _toggle_wrapper(self):
"""Toggle visibility of the prompt wrapper editor."""
if self.ai_prompt_input.isVisible():
self.ai_prompt_input.hide()
self.wrapper_toggle.setText("Edit prompt wrapper ▶")
else:
self.ai_prompt_input.show()
self.wrapper_toggle.setText("Edit prompt wrapper ▼")
def _set_default_prompt(self):
"""Set the default AI prompt template."""
vars_formatted = ', '.join(f'"{{{v}}}"' for v in self._available_vars)
@@ -317,7 +340,7 @@ Example:
my_var = \"\"\"{{input}}\"\"\"
result = my_var.upper()
INSTRUCTION: [Describe what you want the code to do]
INSTRUCTION: {{user_instruction}}
CURRENT CODE:
{{code}}
@@ -329,14 +352,20 @@ IMPORTANT: Return ONLY executable inline Python code. No function definitions, n
def _generate_code(self):
"""Generate code using AI."""
prompt_template = self.ai_prompt_input.toPlainText().strip()
if not prompt_template:
self.ai_output.setHtml("<span style='color: #e53e3e;'>Please enter a prompt</span>")
user_instruction = self.user_instruction_input.toPlainText().strip()
if not user_instruction:
self.ai_output.setHtml("<span style='color: #e53e3e;'>Please describe what you want the code to do</span>")
return
# Replace {code} placeholder with current code
prompt_template = self.ai_prompt_input.toPlainText().strip()
if not prompt_template:
self.ai_output.setHtml("<span style='color: #e53e3e;'>Prompt wrapper is empty</span>")
return
# Inject user instruction and current code into the wrapper
current_code = self.code_input.toPlainText().strip() or "# No code yet"
prompt = prompt_template.replace("{code}", current_code)
prompt = prompt_template.replace("{user_instruction}", user_instruction)
prompt = prompt.replace("{code}", current_code)
provider = self.ai_provider_combo.currentText()