Add Dependencies section to Tool Builder GUI

- Add Dependencies group box with dropdown to select installed tools
- Dropdown is editable for typing tool references (e.g., official/summarize)
- Add/Remove buttons to manage dependency list
- Dependencies are loaded when editing existing tools
- Dependencies are saved with the tool

This allows users to declare dependencies for tools that call other tools
via subprocess in code steps, making them visible to the dependency system.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2026-01-27 00:25:27 -04:00
parent a36c2db05c
commit b0e8bb3e65
1 changed files with 110 additions and 1 deletions

View File

@ -133,6 +133,47 @@ class ToolBuilderPage(QWidget):
left_layout.addWidget(args_box)
# Dependencies group
deps_box = QGroupBox()
deps_layout = QVBoxLayout(deps_box)
deps_label = QLabel("Dependencies")
deps_label.setObjectName("sectionHeading")
deps_label.setToolTip(
"<p>Dependencies are other CmdForge tools this tool requires.</p>"
"<p>If your code steps call other tools via subprocess,<br>"
"declare them here so the dependency system knows about them.</p>"
"<p>Use this when you can't use a Tool step directly<br>"
"(e.g., calling tools in a loop or with complex logic).</p>"
)
deps_layout.addWidget(deps_label)
self.deps_list = QListWidget()
self.deps_list.setMaximumHeight(100)
deps_layout.addWidget(self.deps_list)
# Dependency add row: combo + add button
deps_add_row = QHBoxLayout()
self.deps_combo = QComboBox()
self.deps_combo.setEditable(True)
self.deps_combo.setPlaceholderText("Select or type tool name...")
self.deps_combo.setToolTip("Select an installed tool or type a tool reference (e.g., official/summarize)")
self._populate_deps_combo()
deps_add_row.addWidget(self.deps_combo, 1)
self.btn_add_dep = QPushButton("Add")
self.btn_add_dep.clicked.connect(self._add_dependency)
deps_add_row.addWidget(self.btn_add_dep)
self.btn_del_dep = QPushButton("Remove")
self.btn_del_dep.setObjectName("danger")
self.btn_del_dep.clicked.connect(self._delete_dependency)
deps_add_row.addWidget(self.btn_del_dep)
deps_layout.addLayout(deps_add_row)
left_layout.addWidget(deps_box)
splitter.addWidget(left)
# Right: Steps and output
@ -406,6 +447,9 @@ class ToolBuilderPage(QWidget):
# Load arguments
self._refresh_arguments()
# Load dependencies
self._refresh_dependencies()
# Load steps
self._refresh_steps()
@ -579,6 +623,66 @@ class ToolBuilderPage(QWidget):
del self._tool.arguments[idx]
self._refresh_arguments()
def _populate_deps_combo(self):
"""Populate dependencies combo with installed tools."""
from ...tool import TOOLS_DIR
self.deps_combo.clear()
# Get all installed tools
tools = []
if TOOLS_DIR.exists():
for item in TOOLS_DIR.iterdir():
if item.is_dir():
config = item / "config.yaml"
if config.exists():
tools.append(item.name)
# Sort and add to combo
for tool in sorted(tools):
self.deps_combo.addItem(tool)
def _add_dependency(self):
"""Add selected tool to dependencies."""
tool_ref = self.deps_combo.currentText().strip()
if not tool_ref:
return
if not self._tool:
# Create a minimal tool object if none exists
self._tool = Tool(name="", description="")
# Initialize dependencies list if needed
if not hasattr(self._tool, 'dependencies') or self._tool.dependencies is None:
self._tool.dependencies = []
# Check if already in list
if tool_ref in self._tool.dependencies:
self.main_window.show_status(f"'{tool_ref}' is already a dependency")
return
self._tool.dependencies.append(tool_ref)
self._refresh_dependencies()
self.deps_combo.setCurrentText("")
self.main_window.show_status(f"Added dependency: {tool_ref}")
def _delete_dependency(self):
"""Remove selected dependency."""
items = self.deps_list.selectedItems()
if not items:
return
dep = items[0].text()
if self._tool and self._tool.dependencies and dep in self._tool.dependencies:
self._tool.dependencies.remove(dep)
self._refresh_dependencies()
def _refresh_dependencies(self):
"""Refresh dependencies list widget."""
self.deps_list.clear()
if self._tool and self._tool.dependencies:
for dep in self._tool.dependencies:
self.deps_list.addItem(dep)
def _add_tool_dependency(self, tool_ref: str):
"""Add a tool reference to the dependencies list if not already present.
@ -830,13 +934,18 @@ class ToolBuilderPage(QWidget):
category=category,
arguments=self._tool.arguments if self._tool else [],
steps=self._tool.steps if self._tool else [],
output=output
output=output,
dependencies=self._tool.dependencies if self._tool else []
)
# Preserve source if editing
if self._tool and self._tool.source:
tool.source = self._tool.source
# Preserve version if editing
if self._tool and self._tool.version:
tool.version = self._tool.version
try:
save_tool(tool)
self.main_window.show_status(f"Saved tool '{name}'")