Files
playbook/scripts/build_tsl_playbook.py
T
csh c69278283f feat(tsl-codegen): add decoupled documentation toolkit
Generate TSL API Markdown from YAML or JSON into a configurable project scope.\nAdd file and directory lint modes, tags-aware indexing, and keyword search across tags and descriptions.\nBundle the toolkit through the playbook build and sync workflows.
2026-07-20 09:08:38 +08:00

93 lines
2.9 KiB
Python

#!/usr/bin/env python3
"""Build the minimal TSL playbook bundle."""
import argparse
import shutil
import sys
from pathlib import Path
DEFAULT_OUTPUT = Path("tmp") / "tsl-playbook"
def copy_tree(src: Path, dst: Path) -> None:
shutil.copytree(src, dst, ignore=shutil.ignore_patterns("__pycache__", "*.pyc"))
def build_agents_text(ruleset_path: Path) -> str:
text = ruleset_path.read_text(encoding="utf-8")
text = text.replace("# TSL 智能体规则", "# TSL Agent Instructions", 1)
return text.rstrip("\n") + "\n"
def ensure_sources(repo_root: Path) -> tuple[Path, Path, Path, Path, Path]:
docs_tsl = repo_root / "docs" / "tsl"
syntax_skill = repo_root / "skills" / "tsl-syntax-reference"
api_skill = repo_root / "skills" / "tsl-api-reference"
ruleset = repo_root / "rulesets" / "tsl" / "index.md"
codegen_toolkit = repo_root / "tools" / "tsl-codegen"
sources = (docs_tsl, syntax_skill, api_skill, ruleset, codegen_toolkit)
missing = [str(path) for path in sources if not path.exists()]
if missing:
raise FileNotFoundError("missing source path(s): " + ", ".join(missing))
return sources
def clean_output(output: Path, repo_root: Path) -> None:
resolved = output.resolve()
forbidden = {
repo_root.resolve(),
(repo_root / "docs").resolve(),
(repo_root / "skills").resolve(),
(repo_root / "rulesets").resolve(),
}
if resolved in forbidden:
raise ValueError(f"refusing to replace source directory: {output}")
if output.exists():
shutil.rmtree(output)
output.mkdir(parents=True)
def build(output: Path, repo_root: Path) -> None:
docs_tsl, syntax_skill, api_skill, ruleset, codegen_toolkit = ensure_sources(
repo_root
)
clean_output(output, repo_root)
(output / "AGENTS.md").write_text(
build_agents_text(ruleset), encoding="utf-8", newline="\n"
)
copy_tree(docs_tsl, output / "docs" / "tsl")
copy_tree(syntax_skill, output / "skills" / "tsl-syntax-reference")
copy_tree(api_skill, output / "skills" / "tsl-api-reference")
copy_tree(codegen_toolkit, output / "tools" / "tsl-codegen")
def main(argv=None) -> int:
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--output",
default=str(DEFAULT_OUTPUT),
help=f"output directory (default: {DEFAULT_OUTPUT.as_posix()})",
)
args = parser.parse_args(argv)
repo_root = Path(__file__).resolve().parents[1]
output = Path(args.output)
if not output.is_absolute():
output = repo_root / output
try:
build(output, repo_root)
except (FileNotFoundError, ValueError, OSError) as exc:
print(f"ERROR: {exc}", file=sys.stderr)
return 1
print(f"wrote {output}")
return 0
if __name__ == "__main__":
raise SystemExit(main())