Add registry endpoint and CLI command for updating tool READMEs

- PATCH /api/v1/tools/<owner>/<name>/readme updates README without
  affecting config hash or requiring version bump
- Add RegistryClient.update_readme() method
- Add `cmdforge registry update-readme` CLI command with --all flag
  for batch updating all published tools

Co-Authored-By: Claude Opus 4.5 <[email protected]>
This commit is contained in:
rob
2026-02-01 01:35:10 -04:00
co-authored by Claude Opus 4.5
parent f2cb9c0057
commit e83c9c15f3
4 changed files with 148 additions and 0 deletions
+83
View File
@@ -29,6 +29,8 @@ def cmd_registry(args):
return _cmd_registry_update(args)
elif args.registry_cmd == "publish":
return _cmd_registry_publish(args)
elif args.registry_cmd == "update-readme":
return _cmd_registry_update_readme(args)
elif args.registry_cmd == "my-tools":
return _cmd_registry_my_tools(args)
elif args.registry_cmd == "status":
@@ -47,6 +49,7 @@ def cmd_registry(args):
print(" info <tool> Show tool information")
print(" update Update local index cache")
print(" publish [path] Publish a tool")
print(" update-readme Update README for published tool(s)")
print(" my-tools List your published tools")
print(" status <tool> Check moderation status of a tool")
print(" browse Browse tools (GUI)")
@@ -635,6 +638,86 @@ def _cmd_registry_publish(args):
return 0
def _cmd_registry_update_readme(args):
"""Update README for published tool(s) on the registry."""
from ..registry_client import RegistryError, get_client
from ..tool import TOOLS_DIR, list_tools
try:
client = get_client()
except RegistryError as e:
print(f"Error: {e}", file=sys.stderr)
return 1
if getattr(args, "update_all", False):
# Update all published tools that have a local README
tools = list_tools()
updated = 0
skipped = 0
failed = 0
for tool_name in tools:
tool_dir = TOOLS_DIR / tool_name
config_path = tool_dir / "config.yaml"
readme_path = tool_dir / "README.md"
if not readme_path.exists():
continue
# Check if published
try:
config = yaml.safe_load(config_path.read_text()) or {}
except Exception:
continue
owner = config.get("registry_owner", "")
if not owner:
skipped += 1
continue
readme_content = readme_path.read_text()
try:
result = client.update_readme(owner, tool_name, readme_content)
count = result.get("versions_updated", 0)
print(f" {owner}/{tool_name}: updated ({count} version(s))")
updated += 1
except RegistryError as e:
print(f" {owner}/{tool_name}: FAILED - {e}", file=sys.stderr)
failed += 1
print(f"\nDone: {updated} updated, {failed} failed, {skipped} skipped (not published)")
return 0
# Single tool mode
tool_name = args.tool
tool_dir = TOOLS_DIR / tool_name
config_path = tool_dir / "config.yaml"
readme_path = tool_dir / "README.md"
if not config_path.exists():
print(f"Error: Tool '{tool_name}' not found", file=sys.stderr)
return 1
if not readme_path.exists():
print(f"Error: No README.md found for '{tool_name}'", file=sys.stderr)
return 1
config = yaml.safe_load(config_path.read_text()) or {}
owner = config.get("registry_owner", "")
if not owner:
print(f"Error: Tool '{tool_name}' has no registry_owner — not published?", file=sys.stderr)
return 1
readme_content = readme_path.read_text()
try:
result = client.update_readme(owner, tool_name, readme_content)
count = result.get("versions_updated", 0)
print(f"Updated README for {owner}/{tool_name} ({count} version(s))")
except RegistryError as e:
print(f"Error: {e}", file=sys.stderr)
return 1
return 0
def _cmd_registry_my_tools(args):
"""List your published tools."""
from ..registry_client import RegistryError, get_client