项目文件夹

文件
2026-07-13 12:29:52 +08:00

151 行
5.9 KiB
Python

此文件含有模棱两可的 Unicode 字符
此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。
#!/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()