Add tool settings files for configurable tool defaults
Tools can now ship with defaults.yaml containing configurable settings
that users can customize via settings.yaml (auto-created from defaults).
Features:
- ensure_settings() helper copies defaults to settings on first use
- Settings available as {settings.key} in templates (scalars only)
- Full dict access via settings['key'] in code steps
- CLI: cmdforge settings <tool> show/edit/reset/diff
- GUI: Defaults editor in Tool Builder, Configure button on Tools page
- Registry: defaults.yaml published with tools, included in downloads
- Secret detection warning on publish (api_key, password, token, etc.)
Fully backward compatible - tools without defaults work unchanged.
Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
@@ -226,6 +226,13 @@ class ToolsPage(QWidget):
|
||||
self.btn_edit.setEnabled(False)
|
||||
btn_layout.addWidget(self.btn_edit)
|
||||
|
||||
self.btn_configure = QPushButton("Configure")
|
||||
self.btn_configure.setObjectName("secondary")
|
||||
self.btn_configure.setToolTip("Edit tool settings (only available for tools with configurable settings)")
|
||||
self.btn_configure.clicked.connect(self._configure_tool)
|
||||
self.btn_configure.setEnabled(False)
|
||||
btn_layout.addWidget(self.btn_configure)
|
||||
|
||||
self.btn_delete = QPushButton("Delete")
|
||||
self.btn_delete.setObjectName("danger")
|
||||
self.btn_delete.clicked.connect(self._delete_tool)
|
||||
@@ -582,12 +589,24 @@ class ToolsPage(QWidget):
|
||||
|
||||
self.info_text.setHtml("\n".join(lines))
|
||||
|
||||
def _has_settings(self, tool: Tool) -> bool:
|
||||
"""Check if a tool has configurable settings."""
|
||||
if not tool or not tool.path:
|
||||
return False
|
||||
defaults_path = tool.path.parent / "defaults.yaml"
|
||||
settings_path = tool.path.parent / "settings.yaml"
|
||||
return defaults_path.exists() or settings_path.exists()
|
||||
|
||||
def _update_buttons(self):
|
||||
"""Update button enabled states."""
|
||||
has_selection = self._current_tool is not None
|
||||
self.btn_edit.setEnabled(has_selection)
|
||||
self.btn_delete.setEnabled(has_selection)
|
||||
|
||||
# Configure button only for tools with settings
|
||||
has_settings = has_selection and self._has_settings(self._current_tool)
|
||||
self.btn_configure.setEnabled(has_settings)
|
||||
|
||||
config = load_config()
|
||||
if config.registry.token:
|
||||
# Connected - enable Publish when tool selected
|
||||
@@ -605,6 +624,25 @@ class ToolsPage(QWidget):
|
||||
if self._current_tool:
|
||||
self.main_window.open_tool_builder(self._current_tool.name)
|
||||
|
||||
def _configure_tool(self):
|
||||
"""Open settings dialog for the selected tool."""
|
||||
if not self._current_tool:
|
||||
return
|
||||
|
||||
if not self._has_settings(self._current_tool):
|
||||
QMessageBox.information(
|
||||
self,
|
||||
"No Settings",
|
||||
f"Tool '{self._current_tool.name}' has no configurable settings.\n\n"
|
||||
"Add a defaults.yaml to the tool to enable settings."
|
||||
)
|
||||
return
|
||||
|
||||
from ..dialogs.settings_dialog import SettingsDialog
|
||||
dialog = SettingsDialog(self, self._current_tool.name)
|
||||
if dialog.exec():
|
||||
self.main_window.show_status(f"Settings saved for '{self._current_tool.name}'")
|
||||
|
||||
def _delete_tool(self):
|
||||
"""Delete the selected tool."""
|
||||
if not self._current_tool:
|
||||
|
||||
Reference in New Issue
Block a user