Initial commit
This commit is contained in:
303
skills/guardian/scripts/template_loader.py
Normal file
303
skills/guardian/scripts/template_loader.py
Normal file
@@ -0,0 +1,303 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user