feat: unify card runtime and event-driven web ui
This commit is contained in:
parent
0edf8c3fef
commit
4dfb7ca3cc
105 changed files with 17382 additions and 8505 deletions
119
scripts/check_card_runtime.py
Normal file
119
scripts/check_card_runtime.py
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#!/usr/bin/env python3
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
LIVE_TEMPLATES_DIR = Path.home() / ".nanobot" / "cards" / "templates"
|
||||
EXAMPLE_TEMPLATES_DIR = (
|
||||
Path(__file__).resolve().parent.parent / "examples" / "cards" / "templates"
|
||||
)
|
||||
|
||||
|
||||
LEGACY_MARKERS = (
|
||||
"__nanobot",
|
||||
"document.currentScript",
|
||||
"mountLegacyTemplate",
|
||||
"legacy-template-module",
|
||||
)
|
||||
|
||||
|
||||
def iter_template_dirs(root: Path) -> dict[str, Path]:
|
||||
templates: dict[str, Path] = {}
|
||||
if not root.exists():
|
||||
return templates
|
||||
for child in sorted(root.iterdir()):
|
||||
if not child.is_dir():
|
||||
continue
|
||||
if not (child / "manifest.json").exists():
|
||||
continue
|
||||
templates[child.name] = child
|
||||
return templates
|
||||
|
||||
|
||||
def validate_template_dir(template_dir: Path, failures: list[str]) -> None:
|
||||
manifest_path = template_dir / "manifest.json"
|
||||
template_path = template_dir / "template.html"
|
||||
runtime_path = template_dir / "card.js"
|
||||
|
||||
for required in (manifest_path, template_path, runtime_path):
|
||||
if not required.exists():
|
||||
failures.append(f"{template_dir}: missing {required.name}")
|
||||
return
|
||||
|
||||
try:
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
except Exception as exc:
|
||||
failures.append(f"{manifest_path}: invalid JSON ({exc})")
|
||||
return
|
||||
if not isinstance(manifest, dict):
|
||||
failures.append(f"{manifest_path}: manifest must be an object")
|
||||
|
||||
template_html = template_path.read_text(encoding="utf-8")
|
||||
if "<script" in template_html.lower():
|
||||
failures.append(f"{template_path}: inline script tags are not allowed")
|
||||
|
||||
runtime_js = runtime_path.read_text(encoding="utf-8")
|
||||
if "export function mount" not in runtime_js:
|
||||
failures.append(f"{runtime_path}: missing `export function mount`")
|
||||
for marker in LEGACY_MARKERS:
|
||||
if marker in runtime_js:
|
||||
failures.append(f"{runtime_path}: legacy marker `{marker}` still present")
|
||||
|
||||
result = subprocess.run(
|
||||
["node", "--check", str(runtime_path)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
detail = (result.stderr or result.stdout).strip()
|
||||
failures.append(f"{runtime_path}: node --check failed: {detail}")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("--live-root", type=Path, default=LIVE_TEMPLATES_DIR)
|
||||
parser.add_argument("--example-root", type=Path, default=EXAMPLE_TEMPLATES_DIR)
|
||||
args = parser.parse_args()
|
||||
|
||||
live_root = args.live_root.expanduser()
|
||||
example_root = args.example_root.expanduser()
|
||||
|
||||
failures: list[str] = []
|
||||
for template_dir in iter_template_dirs(live_root).values():
|
||||
validate_template_dir(template_dir, failures)
|
||||
for template_dir in iter_template_dirs(example_root).values():
|
||||
validate_template_dir(template_dir, failures)
|
||||
|
||||
sync_check = subprocess.run(
|
||||
[
|
||||
"python3",
|
||||
str(Path(__file__).resolve().parent / "sync_card_templates.py"),
|
||||
"--check",
|
||||
"--source",
|
||||
str(live_root),
|
||||
"--dest",
|
||||
str(example_root),
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
if sync_check.returncode != 0:
|
||||
detail = (sync_check.stdout + sync_check.stderr).strip()
|
||||
if detail:
|
||||
print(detail)
|
||||
failures.append("template mirror drift detected")
|
||||
|
||||
if failures:
|
||||
for failure in failures:
|
||||
print(failure)
|
||||
return 1
|
||||
|
||||
print("card runtime ok")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue