Files
2026-07-13 12:29:52 +08:00

151 lines
5.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
"""Check runtime capabilities at the beginning of the workflow."""
from __future__ import annotations
import argparse
import importlib.util
import shutil
import subprocess
from pathlib import Path
from typing import Any
from common import ensure_dir, write_json
def command_version(command: list[str]) -> tuple[bool, str]:
if not shutil.which(command[0]):
return False, "not found"
try:
completed = subprocess.run(command, text=True, capture_output=True, timeout=20)
output = (completed.stdout or completed.stderr).strip().splitlines()
return completed.returncode == 0, output[0] if output else "available"
except Exception as exc:
return False, str(exc)
def run_docx_env(skill_dir: Path) -> tuple[bool, str]:
env_script = skill_dir / "vendor/docx-toolkit/scripts/env_check.sh"
if not env_script.exists():
return False, "vendor/docx-toolkit/scripts/env_check.sh not found"
try:
completed = subprocess.run(["bash", str(env_script)], text=True, capture_output=True, timeout=40)
return completed.returncode == 0, (completed.stdout + completed.stderr).strip()
except Exception as exc:
return False, str(exc)
def module_available(name: str) -> bool:
return importlib.util.find_spec(name) is not None
def check_environment(skill_dir: Path) -> dict[str, Any]:
python_docx = module_available("docx")
pandoc_ok, pandoc_version = command_version(["pandoc", "--version"])
dotnet_ok, dotnet_version = command_version(["dotnet", "--version"])
docx_ready, docx_output = run_docx_env(skill_dir)
final_docx_mode = "docx-openxml" if docx_ready else ("python-docx" if python_docx else "basic-ooxml")
requires_user_input = not docx_ready
next_action = (
"请选择:1) 安装完整 DOCX 环境;2) 使用基础 DOCX 兜底继续。回复选择后再进入项目分析。"
if requires_user_input
else "完整 DOCX 环境可用,可以进入项目分析。"
)
return {
"output_directory": "当前目录/软件著作权申请资料",
"capabilities": {
"markdown_drafts": True,
"application_txt": True,
"basic_docx": python_docx or True,
"python_docx": python_docx,
"pandoc_preview": pandoc_ok,
"docx_openxml_full": docx_ready,
"dotnet_sdk": dotnet_ok,
},
"versions": {
"pandoc": pandoc_version,
"dotnet": dotnet_version,
},
"final_docx_mode": final_docx_mode,
"recommendation": (
"完整 DOCX OpenXML 环境已就绪,建议使用完整 Word 生成和校验流程。"
if docx_ready
else "完整 DOCX OpenXML 环境未就绪。可以继续使用兜底 DOCX 生成;如需更规范的 Word 结构和校验,请先安装 .NET SDK 并运行 vendor/docx-toolkit/scripts/setup.sh。"
),
"install_prompt": (
"是否安装完整 DOCX 环境?安装后文档生成和校验更规范;不安装也可以继续生成 Markdown、TXT 和基础 DOCX。"
if not docx_ready
else "无需安装,完整环境可用。"
),
"requires_user_input": requires_user_input,
"confirmation_stage": "environment" if requires_user_input else None,
"next_action": next_action,
"docx_env_output": docx_output,
}
def write_markdown(path: Path, data: dict[str, Any]) -> None:
caps = data["capabilities"]
lines = [
"# 软著申请资料生成环境检查",
"",
f"- 输出目录:`{data['output_directory']}`",
f"- 最终 Word 模式:`{data['final_docx_mode']}`",
"",
"## 能力状态",
"",
f"- Markdown 草稿:{'可用' if caps['markdown_drafts'] else '不可用'}",
f"- 申请表 TXT{'可用' if caps['application_txt'] else '不可用'}",
f"- 基础 DOCX 生成:{'可用' if caps['basic_docx'] else '不可用'}",
f"- python-docx{'可用' if caps['python_docx'] else '不可用'}",
f"- pandoc 预览:{'可用' if caps['pandoc_preview'] else '不可用'}{data['versions']['pandoc']}",
f"- .NET SDK{'可用' if caps['dotnet_sdk'] else '不可用'}{data['versions']['dotnet']}",
f"- DOCX OpenXML 完整环境:{'可用' if caps['docx_openxml_full'] else '不可用'}",
"",
"## 建议",
"",
data["recommendation"],
"",
"## 用户选择",
"",
data["install_prompt"],
"",
"如果完整 DOCX 环境不可用,必须先等待用户选择,并记录 `environment` 门禁后再继续。",
"",
"```text" if data.get("requires_user_input") else "",
"STOP_FOR_USER" if data.get("requires_user_input") else "",
f"NEXT_ACTION: {data['next_action']}" if data.get("requires_user_input") else "",
"```" if data.get("requires_user_input") else "",
"",
"## DOCX 环境输出摘要",
"",
"```text",
"\n".join(data["docx_env_output"].splitlines()[:40]),
"```",
"",
]
path.write_text("\n".join(lines), encoding="utf-8")
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--out-dir", default="软件著作权申请资料")
args = parser.parse_args()
skill_dir = Path(__file__).resolve().parents[1]
out_dir = ensure_dir(Path(args.out_dir))
data = check_environment(skill_dir)
write_json(out_dir / "环境检查.json", data)
write_markdown(out_dir / "环境检查.md", data)
print(f"OK environment check: {out_dir}")
print(f"Final DOCX mode: {data['final_docx_mode']}")
print(data["recommendation"])
if data.get("requires_user_input"):
print("STOP_FOR_USER")
print(f"NEXT_ACTION: {data['next_action']}")
if __name__ == "__main__":
main()