Add provider fallback, visual schema builder, and UI improvements
Provider fallback system: - Add optional fallback field to Provider dataclass - Automatically try fallback provider when primary fails (timeout, error, offline) - Prevent infinite loops with circular fallback detection - Add fallback column and dropdown in providers UI Visual schema builder for prompt steps: - Add SchemaBuilderDialog with table-based field editor - Support field name, type, description, and required flag - Live JSON schema preview - Integrate into PromptStepDialog with Edit Schema button - Fix output_schema being lost when editing prompt steps Other improvements: - Add search box to tools page - Improve schema example generation for structured output - Update CLAUDE.md documentation Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
@@ -9,7 +9,7 @@ import yaml
|
||||
from PySide6.QtWidgets import (
|
||||
QWidget, QVBoxLayout, QHBoxLayout, QSplitter,
|
||||
QTreeWidget, QTreeWidgetItem, QTextEdit, QLabel,
|
||||
QPushButton, QGroupBox, QMessageBox, QFrame
|
||||
QPushButton, QGroupBox, QMessageBox, QFrame, QLineEdit
|
||||
)
|
||||
from PySide6.QtCore import Qt, QThread, Signal, QTimer
|
||||
from PySide6.QtGui import QFont, QColor, QBrush, QShortcut, QKeySequence
|
||||
@@ -402,6 +402,13 @@ class ToolsPage(QWidget):
|
||||
left_layout.setContentsMargins(0, 0, 0, 0)
|
||||
left_layout.setSpacing(8)
|
||||
|
||||
# Search box
|
||||
self.search_box = QLineEdit()
|
||||
self.search_box.setPlaceholderText("Search tools...")
|
||||
self.search_box.setClearButtonEnabled(True)
|
||||
self.search_box.textChanged.connect(self._filter_tools)
|
||||
left_layout.addWidget(self.search_box)
|
||||
|
||||
self.tool_tree = QTreeWidget()
|
||||
self.tool_tree.setHeaderHidden(True)
|
||||
self.tool_tree.setIndentation(16)
|
||||
@@ -555,6 +562,7 @@ class ToolsPage(QWidget):
|
||||
|
||||
def refresh(self):
|
||||
"""Refresh the tool list."""
|
||||
self.search_box.clear()
|
||||
self.tool_tree.clear()
|
||||
self._current_tool = None
|
||||
self.info_text.clear()
|
||||
@@ -741,6 +749,43 @@ class ToolsPage(QWidget):
|
||||
self.refresh()
|
||||
self.main_window.show_status(f"Status updated for '{tool_name}'")
|
||||
|
||||
def _filter_tools(self, text: str):
|
||||
"""Filter tools by name or description based on search text."""
|
||||
search = text.lower().strip()
|
||||
|
||||
for i in range(self.tool_tree.topLevelItemCount()):
|
||||
category_item = self.tool_tree.topLevelItem(i)
|
||||
visible_children = 0
|
||||
|
||||
for j in range(category_item.childCount()):
|
||||
tool_item = category_item.child(j)
|
||||
tool_name = tool_item.data(0, Qt.UserRole)
|
||||
|
||||
if not search:
|
||||
# No filter - show all
|
||||
tool_item.setHidden(False)
|
||||
visible_children += 1
|
||||
else:
|
||||
# Check if name matches
|
||||
matches = search in tool_name.lower()
|
||||
|
||||
# Also check description if we have the tool loaded
|
||||
if not matches:
|
||||
tool = load_tool(tool_name)
|
||||
if tool and tool.description:
|
||||
matches = search in tool.description.lower()
|
||||
|
||||
tool_item.setHidden(not matches)
|
||||
if matches:
|
||||
visible_children += 1
|
||||
|
||||
# Hide category if no children match
|
||||
category_item.setHidden(visible_children == 0)
|
||||
|
||||
# Expand categories when filtering to show results
|
||||
if search and visible_children > 0:
|
||||
category_item.setExpanded(True)
|
||||
|
||||
def _on_selection_changed(self):
|
||||
"""Handle tool selection change."""
|
||||
items = self.tool_tree.selectedItems()
|
||||
|
||||
Reference in New Issue
Block a user