Preserve registry fields on tool save and store owner in all publish paths

- save_tool() now preserves registry_hash, registry_status, registry_owner,
  and registry_feedback from existing config when writing Tool.to_dict(),
  preventing edits from erasing registry metadata.
- CLI publish (registry_commands.py) and collection publish
  (collections_commands.py) now save registry_owner from the publish
  response, matching the GUI publish dialog behavior.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
rob 2026-01-30 03:07:00 -04:00
parent 5ff108cdb3
commit fe5b2047a9
3 changed files with 25 additions and 2 deletions

View File

@ -731,6 +731,9 @@ def _publish_single_tool(tool_name: str, client) -> dict:
config_data = yaml.safe_load(config_path.read_text()) or {} config_data = yaml.safe_load(config_path.read_text()) or {}
config_data["registry_hash"] = config_hash config_data["registry_hash"] = config_hash
config_data["registry_status"] = moderation_status config_data["registry_status"] = moderation_status
registry_owner = result.get("owner")
if registry_owner:
config_data["registry_owner"] = registry_owner
# Clear any old feedback when republishing # Clear any old feedback when republishing
if "registry_feedback" in config_data: if "registry_feedback" in config_data:
del config_data["registry_feedback"] del config_data["registry_feedback"]

View File

@ -600,6 +600,9 @@ def _cmd_registry_publish(args):
config_data = yaml.safe_load(config_path.read_text()) or {} config_data = yaml.safe_load(config_path.read_text()) or {}
config_data["registry_hash"] = config_hash config_data["registry_hash"] = config_hash
config_data["registry_status"] = moderation_status config_data["registry_status"] = moderation_status
registry_owner = result.get("owner")
if registry_owner:
config_data["registry_owner"] = registry_owner
# Clear any old feedback when republishing # Clear any old feedback when republishing
if "registry_feedback" in config_data: if "registry_feedback" in config_data:
del config_data["registry_feedback"] del config_data["registry_feedback"]

View File

@ -511,13 +511,30 @@ def load_tool(name: str) -> Optional[Tool]:
return None return None
_REGISTRY_FIELDS = ("registry_hash", "registry_status", "registry_owner", "registry_feedback")
def save_tool(tool: Tool) -> Path: def save_tool(tool: Tool) -> Path:
"""Save a tool to disk.""" """Save a tool to disk, preserving registry metadata from existing config."""
tool_dir = get_tools_dir() / tool.name tool_dir = get_tools_dir() / tool.name
tool_dir.mkdir(parents=True, exist_ok=True) tool_dir.mkdir(parents=True, exist_ok=True)
config_path = tool_dir / "config.yaml" config_path = tool_dir / "config.yaml"
config_path.write_text(yaml.dump(tool.to_dict(), default_flow_style=False, sort_keys=False))
# Preserve registry fields from existing config (not part of Tool model)
preserved = {}
if config_path.exists():
try:
existing = yaml.safe_load(config_path.read_text()) or {}
for key in _REGISTRY_FIELDS:
if key in existing:
preserved[key] = existing[key]
except Exception:
pass
new_data = tool.to_dict()
new_data.update(preserved)
config_path.write_text(yaml.dump(new_data, default_flow_style=False, sort_keys=False))
# Create wrapper script # Create wrapper script
create_wrapper_script(tool.name) create_wrapper_script(tool.name)