304 lines
8.4 KiB
Python
304 lines
8.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Guardian Template Loader
|
|
|
|
Loads and applies Guardian review/planning templates for consistent,
|
|
structured agent interactions.
|
|
|
|
Usage:
|
|
# List available templates
|
|
python template_loader.py --list
|
|
|
|
# Load a template
|
|
python template_loader.py --template security_review
|
|
|
|
# Load template and apply to context
|
|
python template_loader.py --template security_review --file auth.py --output prompt.txt
|
|
|
|
# Create custom template
|
|
python template_loader.py --create my_review --based-on security_review
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
import argparse
|
|
from pathlib import Path
|
|
from typing import Dict, List, Optional, Any
|
|
|
|
|
|
def find_templates_dir() -> Path:
|
|
"""Find the Guardian Templates directory."""
|
|
# First try relative to this script
|
|
script_dir = Path(__file__).parent
|
|
templates_dir = script_dir.parent / 'Templates'
|
|
|
|
if templates_dir.exists():
|
|
return templates_dir
|
|
|
|
# Try from current directory
|
|
templates_dir = Path.cwd() / 'skills' / 'guardian' / 'Templates'
|
|
if templates_dir.exists():
|
|
return templates_dir
|
|
|
|
raise FileNotFoundError("Guardian Templates directory not found")
|
|
|
|
|
|
def list_templates() -> List[Dict[str, str]]:
|
|
"""List all available Guardian templates.
|
|
|
|
Returns:
|
|
List of template metadata dictionaries
|
|
"""
|
|
templates_dir = find_templates_dir()
|
|
templates = []
|
|
|
|
for template_file in templates_dir.glob('*.json'):
|
|
try:
|
|
with open(template_file, 'r', encoding='utf-8') as f:
|
|
template = json.load(f)
|
|
templates.append({
|
|
'name': template.get('name', template_file.stem),
|
|
'description': template.get('description', 'No description'),
|
|
'task_type': template.get('task_type', 'unknown'),
|
|
'file': str(template_file)
|
|
})
|
|
except (json.JSONDecodeError, OSError, IOError):
|
|
continue
|
|
|
|
return templates
|
|
|
|
|
|
def load_template(template_name: str) -> Dict[str, Any]:
|
|
"""Load a Guardian template by name.
|
|
|
|
Args:
|
|
template_name: Name of the template (with or without .json extension)
|
|
|
|
Returns:
|
|
Template configuration dictionary
|
|
"""
|
|
templates_dir = find_templates_dir()
|
|
|
|
# Remove .json extension if provided
|
|
if template_name.endswith('.json'):
|
|
template_name = template_name[:-5]
|
|
|
|
template_file = templates_dir / f"{template_name}.json"
|
|
|
|
if not template_file.exists():
|
|
raise FileNotFoundError(f"Template not found: {template_name}")
|
|
|
|
try:
|
|
with open(template_file, 'r', encoding='utf-8') as f:
|
|
return json.load(f)
|
|
except json.JSONDecodeError as e:
|
|
raise ValueError(f"Invalid template JSON: {e}")
|
|
|
|
|
|
def apply_template_to_context(
|
|
template: Dict[str, Any],
|
|
context: str
|
|
) -> str:
|
|
"""Apply a template to extracted context.
|
|
|
|
Args:
|
|
template: Template configuration
|
|
context: Extracted minimal context
|
|
|
|
Returns:
|
|
Formatted agent prompt
|
|
"""
|
|
prompt_template = template.get('agent_prompt_template', '')
|
|
|
|
# Replace context placeholder
|
|
prompt = prompt_template.replace('{context}', context)
|
|
|
|
return prompt
|
|
|
|
|
|
def get_template_config(template: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Extract configuration parameters from template.
|
|
|
|
Args:
|
|
template: Template configuration
|
|
|
|
Returns:
|
|
Configuration dictionary for context_filter.py
|
|
"""
|
|
return {
|
|
'task_type': template.get('task_type', 'review'),
|
|
'focus': template.get('focus', ''),
|
|
'oracle_categories': template.get('oracle_categories', ['patterns', 'gotchas']),
|
|
'oracle_tags': template.get('oracle_tags_required', []),
|
|
'max_patterns': template.get('max_oracle_patterns', 5),
|
|
'max_gotchas': template.get('max_oracle_gotchas', 5),
|
|
'validation_rules': template.get('validation_rules', {})
|
|
}
|
|
|
|
|
|
def create_custom_template(
|
|
name: str,
|
|
base_template: Optional[str] = None,
|
|
description: str = "",
|
|
task_type: str = "review"
|
|
) -> Path:
|
|
"""Create a new custom template.
|
|
|
|
Args:
|
|
name: Name for the new template
|
|
base_template: Optional template to base this on
|
|
description: Template description
|
|
task_type: Type of task (review, plan, debug)
|
|
|
|
Returns:
|
|
Path to the created template file
|
|
"""
|
|
templates_dir = find_templates_dir()
|
|
|
|
if base_template:
|
|
# Load base template
|
|
base = load_template(base_template)
|
|
new_template = base.copy()
|
|
new_template['name'] = name
|
|
if description:
|
|
new_template['description'] = description
|
|
else:
|
|
# Create minimal template
|
|
new_template = {
|
|
"name": name,
|
|
"description": description or f"Custom {task_type} template",
|
|
"task_type": task_type,
|
|
"focus": "",
|
|
"agent_prompt_template": "You are a READ-ONLY code reviewer for Guardian.\n\nCRITICAL CONSTRAINTS:\n- DO NOT modify any files\n- ONLY read and analyze\n\n{context}\n\nReturn suggestions as JSON array.",
|
|
"oracle_categories": ["patterns", "gotchas"],
|
|
"oracle_tags_required": [],
|
|
"max_oracle_patterns": 5,
|
|
"max_oracle_gotchas": 5,
|
|
"always_include_files": [],
|
|
"validation_rules": {
|
|
"min_confidence": 0.5,
|
|
"block_contradictions": true
|
|
}
|
|
}
|
|
|
|
# Save template
|
|
template_file = templates_dir / f"{name}.json"
|
|
|
|
with open(template_file, 'w', encoding='utf-8') as f:
|
|
json.dump(new_template, f, indent=2)
|
|
|
|
return template_file
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='Guardian template loader and manager',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--list',
|
|
action='store_true',
|
|
help='List all available templates'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--template',
|
|
help='Template name to load'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--file',
|
|
help='File to apply template to (used with --output)'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--output',
|
|
help='Output file for generated prompt'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--create',
|
|
help='Create a new custom template with this name'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--based-on',
|
|
help='Base the new template on an existing one'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--description',
|
|
help='Description for new template'
|
|
)
|
|
|
|
parser.add_argument(
|
|
'--show-config',
|
|
action='store_true',
|
|
help='Show template configuration (for use with context_filter.py)'
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
# List templates
|
|
if args.list:
|
|
templates = list_templates()
|
|
|
|
print("Available Guardian Templates:")
|
|
print("=" * 60)
|
|
|
|
for template in templates:
|
|
print(f"\nName: {template['name']}")
|
|
print(f" Type: {template['task_type']}")
|
|
print(f" Description: {template['description']}")
|
|
print(f" File: {template['file']}")
|
|
|
|
print("\n" + "=" * 60)
|
|
print(f"Total: {len(templates)} templates")
|
|
sys.exit(0)
|
|
|
|
# Create template
|
|
if args.create:
|
|
template_file = create_custom_template(
|
|
args.create,
|
|
args.based_on,
|
|
args.description or "",
|
|
"review"
|
|
)
|
|
|
|
print(f"Created template: {template_file}")
|
|
print("Edit this file to customize your template")
|
|
sys.exit(0)
|
|
|
|
# Load template
|
|
if args.template:
|
|
template = load_template(args.template)
|
|
|
|
if args.show_config:
|
|
config = get_template_config(template)
|
|
print(json.dumps(config, indent=2))
|
|
sys.exit(0)
|
|
|
|
if args.output and args.file:
|
|
# Apply template to file
|
|
# This would integrate with context_filter.py
|
|
print(f"Applying template '{args.template}' to {args.file}...")
|
|
print(f"Output will be saved to: {args.output}")
|
|
print("\nTo apply this template:")
|
|
print(f" 1. Run context_filter.py with template config")
|
|
print(f" 2. Apply template to extracted context")
|
|
print(f" 3. Save to {args.output}")
|
|
else:
|
|
# Just show template
|
|
print(json.dumps(template, indent=2))
|
|
|
|
sys.exit(0)
|
|
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|