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:
@@ -1,6 +1,7 @@
|
||||
"""Registry commands."""
|
||||
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
@@ -359,6 +360,32 @@ def _cmd_registry_publish(args):
|
||||
readme_path = tool_path / "README.md"
|
||||
readme = readme_path.read_text() if readme_path.exists() else ""
|
||||
|
||||
# Read defaults if exists
|
||||
defaults_path = tool_path / "defaults.yaml"
|
||||
defaults = ""
|
||||
if defaults_path.exists():
|
||||
defaults = defaults_path.read_text()
|
||||
|
||||
# Warn about potential secrets in defaults
|
||||
defaults_lower = defaults.lower()
|
||||
secret_patterns = ['api_key:', 'api_secret:', 'password:', 'token:', 'secret:']
|
||||
for pattern in secret_patterns:
|
||||
if pattern in defaults_lower:
|
||||
# Check if it has a non-empty value
|
||||
match = re.search(rf'{pattern}\s*["\']?([^"\'\n]+)', defaults_lower)
|
||||
if match and match.group(1).strip() and match.group(1).strip() not in ('""', "''", ''):
|
||||
print(f"Warning: defaults.yaml contains '{pattern[:-1]}' with a value.")
|
||||
print(" Make sure you're not publishing actual credentials!")
|
||||
if not getattr(args, 'force', False):
|
||||
try:
|
||||
confirm = input("Continue anyway? [y/N] ")
|
||||
if confirm.lower() != 'y':
|
||||
return 1
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
print("\nCancelled.")
|
||||
return 1
|
||||
break
|
||||
|
||||
# Validate
|
||||
try:
|
||||
data = yaml.safe_load(config_yaml)
|
||||
@@ -408,7 +435,7 @@ def _cmd_registry_publish(args):
|
||||
|
||||
try:
|
||||
client = get_client()
|
||||
result = client.publish_tool(config_yaml, readme)
|
||||
result = client.publish_tool(config_yaml, readme, defaults)
|
||||
|
||||
pr_url = result.get("pr_url", "")
|
||||
status = result.get("status", "")
|
||||
|
||||
Reference in New Issue
Block a user