M7 follow-up: block GUI silent overwrite, connect registry publish --dry-run to preflight endpoint

This commit is contained in:
rob 2026-07-20 02:57:38 -03:00
parent 8366ef798b
commit 23ac54f5c8
2 changed files with 69 additions and 3 deletions

View File

@ -414,13 +414,44 @@ def _cmd_registry_publish(args):
return 1
if args.dry_run:
print("Dry run - validating only")
print("Dry run — validating locally and via registry preflight")
print()
print(f"Would publish:")
# Local validation
print(f" Name: {name}")
print(f" Version: {version}")
print(f" Config: {len(config_yaml)} bytes")
print(f" README: {len(readme)} bytes")
print()
# Attempt registry preflight if token is configured
config = load_config()
if config.registry.token:
try:
client = get_client()
result = client.publish_tool(
config_yaml, readme=readme, defaults=defaults,
dry_run=True,
)
errors = result.get("errors") or []
warnings = result.get("warnings") or []
if errors:
print(f"Preflight errors ({len(errors)}):")
for err in errors:
print(f" ERROR: {err}")
if warnings:
print(f"Preflight warnings ({len(warnings)}):")
for warn in warnings:
print(f" WARN: {warn}")
if not errors and not warnings:
print("Registry preflight passed.")
return 0 if not errors else 1
except Exception as e:
print(f"Registry preflight unavailable: {e}")
print("Proceeding with local validation only.")
else:
print("No registry token configured — local validation only.")
print("Configure a token to get registry-side preflight checks.")
return 0
# Check for token

View File

@ -13,7 +13,7 @@ from PySide6.QtCore import Qt
from ...tool import (
Tool, ToolArgument, PromptStep, CodeStep, ToolStep,
load_tool, save_tool, validate_tool_name, get_all_categories,
load_tool, save_tool, tool_exists, validate_tool_name, get_all_categories,
ensure_settings
)
from ..widgets.icons import get_prompt_icon, get_code_icon, get_tool_icon
@ -1075,6 +1075,41 @@ class ToolBuilderPage(QWidget):
QMessageBox.warning(self, "Validation", error)
return
# Block silent overwrite when creating a new tool
if (not self.editing or name != self.original_name) and tool_exists(name):
existing = load_tool(name)
existing_desc = f" ({existing.description})" if existing and existing.description else ""
msg = QMessageBox(self)
msg.setIcon(QMessageBox.Warning)
msg.setWindowTitle("Tool Already Exists")
msg.setText(f"'{name}' already exists.{existing_desc}")
msg.setInformativeText("What would you like to do?")
btn_open = msg.addButton("Open Existing", QMessageBox.ActionRole)
btn_copy = msg.addButton("Create Copy", QMessageBox.ActionRole)
btn_rename = msg.addButton("Choose Another Name", QMessageBox.ActionRole)
msg.setStandardButtons(QMessageBox.Cancel)
msg.setDefaultButton(btn_rename)
msg.exec()
clicked = msg.clickedButton()
if clicked is btn_open:
self.main_window.open_tool_builder(name)
self.main_window.close_tool_builder()
return
elif clicked is btn_copy:
suffix = 2
while tool_exists(f"{name}-{suffix}"):
suffix += 1
copy_name = f"{name}-{suffix}"
self.name_input.setText(copy_name)
self.name_input.setFocus()
return
elif clicked is btn_rename:
self.name_input.setFocus()
return
else:
return
description = self.desc_input.text().strip()
category = self.category_combo.currentText()
output = self.output_input.toPlainText().strip() or "{response}"