Files
NestQuest/scripts/render-cycle-prompt
T

63 lines
2.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Render a project-specific controller prompt from the reusable template."""
from __future__ import annotations
import argparse
import json
from pathlib import Path
import re
import sys
TEMPLATE = Path(__file__).resolve().parent.parent / "templates/ORCHESTRATOR-PROMPT.template.md"
RUNTIME_DIR = TEMPLATE.parent / "runtime"
PLACEHOLDER = re.compile(r"\{\{([A-Z][A-Z0-9_]*)\}\}")
def render(template: str, profile: dict[str, str]) -> str:
keys = set(PLACEHOLDER.findall(template))
missing = sorted(keys - profile.keys())
if missing:
raise ValueError("missing profile values: " + ", ".join(missing))
for key in keys:
if not isinstance(profile[key], str) or not profile[key].strip():
raise ValueError(f"{key} must be a nonempty string")
result = PLACEHOLDER.sub(lambda match: profile[match.group(1)], template)
if PLACEHOLDER.search(result):
raise ValueError("profile values must not contain template placeholders")
return result
def select_runtime(template: str, runtime: str) -> str:
if runtime == "service":
return template
marker = "# 27. HOST CONTROLLER RUNTIME"
if template.count(marker) != 1:
raise ValueError("controller runtime section is missing or duplicated")
prefix = template.split(marker, 1)[0].rstrip()
overlay = (RUNTIME_DIR / f"{runtime}.md").read_text().strip()
return prefix + "\n\n" + overlay + "\n"
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("profile", type=Path)
parser.add_argument("--runtime", choices=("service", "terminal"), default="service")
parser.add_argument("--output", type=Path)
args = parser.parse_args()
profile = json.loads(args.profile.read_text())
if not isinstance(profile, dict):
parser.error("profile must be a JSON object")
content = render(select_runtime(TEMPLATE.read_text(), args.runtime), profile)
if args.output:
args.output.write_text(content)
print(args.output)
else:
sys.stdout.write(content)
return 0
if __name__ == "__main__":
raise SystemExit(main())