Files
Jyotisha/scripts/user_invocation_acceptance_check.py
2026-07-10 22:31:28 +08:00

185 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""One-command smoke check for ordinary AI-app / skill invocation."""
from __future__ import annotations
import json
import os
import subprocess
import sys
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
def _run(args: list[str], *, timeout: int = 120, env: dict[str, str] | None = None) -> dict[str, Any]:
completed = subprocess.run(
args,
cwd=ROOT,
text=True,
capture_output=True,
timeout=timeout,
check=False,
env=env,
)
return {
"command": " ".join(args),
"returncode": completed.returncode,
"stdout": completed.stdout,
"stderr": completed.stderr,
}
def _entrypoint_env() -> dict[str, str]:
env = os.environ.copy()
env.update(
{
"JYOTISH_SKIP_LOCAL_ENV": "1",
"VEDASTRO_API_ENDPOINT": "",
"VEDASTRO_ENABLE_NETWORK": "",
"VEDASTRO_TIMEOUT_SECONDS": "",
}
)
return env
def _engine_summary(report: dict[str, Any]) -> dict[str, Any]:
summary: dict[str, Any] = {}
engines = report.get("engines") if isinstance(report.get("engines"), dict) else {}
for name, details in engines.items():
if not isinstance(details, dict):
continue
summary[name] = {
"status": details.get("status"),
"readiness_blockers": details.get("readiness_blockers")
or ([details["missing_dependency"]] if details.get("missing_dependency") else []),
"license_boundary": details.get("license_boundary"),
}
return summary
def _runtime_summary(report: dict[str, Any]) -> dict[str, Any]:
runtime = report.get("runtime_mode") if isinstance(report.get("runtime_mode"), dict) else {}
return {
"mode": runtime.get("mode"),
"official_ready": runtime.get("official_ready"),
"expected_fallback_status": runtime.get("expected_fallback_status"),
}
def _strict_summary(report: dict[str, Any]) -> dict[str, Any]:
strict = report.get("strict_workflow") if isinstance(report.get("strict_workflow"), dict) else {}
return {
"triggered": strict.get("triggered"),
"primary_route": strict.get("primary_route"),
"routes_available": strict.get("routes_available"),
"source": strict.get("source"),
}
def main() -> int:
pytest_check = _run(
[
sys.executable,
"-m",
"pytest",
"-q",
"tests/test_user_invocation_acceptance_contract.py",
"-k",
"not one_command_user_invocation_acceptance_check",
],
timeout=180,
)
entrypoint = _run(
[
sys.executable,
"scripts/vedastro_user_entrypoint.py",
"--year",
"2000",
"--month",
"1",
"--day",
"1",
"--hour",
"12",
"--minute",
"0",
"--lat",
"0.0",
"--lon",
"0.0",
"--tz",
"0",
"--question",
"请先生成 guided_topics 并推荐我最值得看的问题",
"--themes",
"career,marriage,wealth",
"--reference-date",
"2026-07-06",
"--format",
"json",
],
env=_entrypoint_env(),
)
adapters = _run([sys.executable, "scripts/diagnose_external_engine_adapters.py", "--json"], timeout=120)
errors: list[str] = []
entrypoint_report: dict[str, Any] = {}
adapter_report: dict[str, Any] = {}
if pytest_check["returncode"] != 0:
errors.append("user_invocation_pytest_failed")
if entrypoint["returncode"] != 0:
errors.append("user_entrypoint_failed")
else:
try:
entrypoint_report = json.loads(entrypoint["stdout"])
except json.JSONDecodeError:
errors.append("user_entrypoint_invalid_json")
if adapters["returncode"] != 0:
errors.append("external_adapter_diagnostic_failed")
else:
try:
adapter_report = json.loads(adapters["stdout"])
except json.JSONDecodeError:
errors.append("external_adapter_diagnostic_invalid_json")
required_entrypoint_paths = [
("strict_workflow", "triggered"),
("strict_workflow", "routes_available"),
("runtime_mode", "expected_fallback_status"),
("honesty_boundary", "all_641_methods_executed"),
]
for path in required_entrypoint_paths:
cursor: Any = entrypoint_report
for key in path:
cursor = cursor.get(key) if isinstance(cursor, dict) else None
if cursor in (None, [], ""):
errors.append(f"missing_entrypoint_{'_'.join(path)}")
usable_adapter_statuses = {"pass", "partial", "complete"}
if adapter_report.get("status") not in usable_adapter_statuses:
errors.append("external_adapter_status_unusable")
result = {
"scope": "user_invocation_acceptance_check",
"status": "pass" if not errors else "fail",
"errors": errors,
"checks": {
"user_invocation_tests": pytest_check["returncode"] == 0,
"guided_topics_entrypoint": entrypoint["returncode"] == 0 and not any(e.startswith("missing_entrypoint_") for e in errors),
"external_adapter_diagnostics": adapter_report.get("status") in usable_adapter_statuses,
},
"entrypoint_runtime_mode": _runtime_summary(entrypoint_report),
"entrypoint_strict_workflow": _strict_summary(entrypoint_report),
"external_adapter_status": adapter_report.get("status"),
"external_engines": _engine_summary(adapter_report),
}
print(json.dumps(result, ensure_ascii=False, indent=2, sort_keys=True))
return 0 if not errors else 1
if __name__ == "__main__":
raise SystemExit(main())