[aide] impl: 子计划3: aide flow 流程图集成完成 - PlantUML 校验/构建钩子增强

This commit is contained in:
2025-12-15 18:12:50 +08:00
parent 6a1b230cc9
commit 5f7c91afa1
4 changed files with 83 additions and 11 deletions

View File

@@ -1,7 +1,7 @@
{ {
"task_id": "2025-12-15T17-28-53", "task_id": "2025-12-15T17-28-53",
"current_phase": "impl", "current_phase": "impl",
"current_step": 11, "current_step": 12,
"started_at": "2025-12-15T17:28:53+08:00", "started_at": "2025-12-15T17:28:53+08:00",
"history": [ "history": [
{ {
@@ -90,6 +90,14 @@
"step": 11, "step": 11,
"summary": "子计划1: 配置系统增强完成 - 自文档化配置模板、gitignore配置、plantuml.jar", "summary": "子计划1: 配置系统增强完成 - 自文档化配置模板、gitignore配置、plantuml.jar",
"git_commit": "79facec0a3db9ffcf936772930cc695ca9bf263d" "git_commit": "79facec0a3db9ffcf936772930cc695ca9bf263d"
},
{
"timestamp": "2025-12-15T18:11:39+08:00",
"action": "next-step",
"phase": "impl",
"step": 12,
"summary": "子计划2: aide flow 状态查看功能完成 - status/list/show 子命令",
"git_commit": "6a1b230cc98ff5535fd8cbc1d9490293e2ef6845"
} }
] ]
} }

View File

@@ -1 +1 @@
120170 120815

View File

@@ -5,6 +5,7 @@ from __future__ import annotations
import shutil import shutil
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import Any
from aide.core import output from aide.core import output
from aide.flow.errors import FlowError from aide.flow.errors import FlowError
@@ -20,9 +21,10 @@ def run_pre_commit_hooks(
from_phase: str | None, from_phase: str | None,
to_phase: str, to_phase: str,
action: str, action: str,
config: dict[str, Any] | None = None,
) -> None: ) -> None:
if from_phase == "flow-design" and action in {"next-part", "back-part"}: if from_phase == "flow-design" and action in {"next-part", "back-part"}:
_hook_plantuml(root=root) _hook_plantuml(root=root, config=config)
if from_phase == "docs" and action in {"next-part", "back-part"}: if from_phase == "docs" and action in {"next-part", "back-part"}:
_hook_changelog_on_leave_docs(root=root, git=git, status=status) _hook_changelog_on_leave_docs(root=root, git=git, status=status)
@@ -32,11 +34,49 @@ def run_post_commit_hooks(*, to_phase: str, action: str) -> None:
output.info("请更新 CHANGELOG.md") output.info("请更新 CHANGELOG.md")
def _hook_plantuml(*, root: Path) -> None: def _get_plantuml_command(config: dict[str, Any] | None) -> list[str] | None:
docs_dir = root / "docs" """获取 PlantUML 命令,优先使用配置的 jar 文件。"""
discuss_dir = root / "discuss" if config:
jar_path = config.get("plantuml", {}).get("jar_path")
java_path = config.get("plantuml", {}).get("java_path", "java")
if jar_path:
# 尝试解析 jar 路径
jar_file = Path(jar_path)
if not jar_file.is_absolute():
# 相对路径,相对于 aide-program 目录
aide_program_dir = Path(__file__).parent.parent.parent
jar_file = aide_program_dir / jar_path
if jar_file.exists():
return [java_path, "-jar", str(jar_file)]
# 回退到系统 plantuml 命令
if shutil.which("plantuml"):
return ["plantuml"]
return None
def _hook_plantuml(*, root: Path, config: dict[str, Any] | None = None) -> None:
"""PlantUML 校验和构建钩子。"""
# 获取流程图目录
diagram_path = ".aide/diagrams"
if config:
diagram_path = config.get("flow", {}).get("diagram_path", diagram_path)
diagram_dir = root / diagram_path
# 收集所有 .puml 文件
candidates: list[Path] = [] candidates: list[Path] = []
for base in (docs_dir, discuss_dir):
# 从配置的流程图目录
if diagram_dir.exists():
candidates.extend([p for p in diagram_dir.rglob("*.puml") if p.is_file()])
candidates.extend([p for p in diagram_dir.rglob("*.plantuml") if p.is_file()])
# 也检查 docs 和 discuss 目录(向后兼容)
for base in (root / "docs", root / "discuss"):
if not base.exists(): if not base.exists():
continue continue
candidates.extend([p for p in base.rglob("*.puml") if p.is_file()]) candidates.extend([p for p in base.rglob("*.puml") if p.is_file()])
@@ -45,20 +85,42 @@ def _hook_plantuml(*, root: Path) -> None:
if not candidates: if not candidates:
return return
if shutil.which("plantuml") is None: # 获取 PlantUML 命令
output.warn("未找到 plantuml已跳过 PlantUML 校验/PNG 生成") plantuml_cmd = _get_plantuml_command(config)
if plantuml_cmd is None:
output.warn("未找到 PlantUMLjar 或系统命令),已跳过校验/PNG 生成")
return return
# 先校验所有文件
errors: list[str] = []
for file_path in candidates: for file_path in candidates:
result = subprocess.run( result = subprocess.run(
["plantuml", "-tpng", str(file_path)], plantuml_cmd + ["-checkonly", str(file_path)],
cwd=root, cwd=root,
text=True, text=True,
capture_output=True, capture_output=True,
) )
if result.returncode != 0: if result.returncode != 0:
detail = (result.stderr or "").strip() or (result.stdout or "").strip() detail = (result.stderr or "").strip() or (result.stdout or "").strip()
raise FlowError(f"PlantUML 处理失败: {file_path} {detail}".strip()) errors.append(f"{file_path.name}: {detail}")
if errors:
error_msg = "\n".join(errors)
raise FlowError(f"PlantUML 语法校验失败:\n{error_msg}")
# 校验通过,生成 PNG
for file_path in candidates:
result = subprocess.run(
plantuml_cmd + ["-tpng", str(file_path)],
cwd=root,
text=True,
capture_output=True,
)
if result.returncode != 0:
detail = (result.stderr or "").strip() or (result.stdout or "").strip()
raise FlowError(f"PlantUML PNG 生成失败: {file_path} {detail}".strip())
output.ok(f"PlantUML 处理完成: {len(candidates)} 个文件")
def _hook_changelog_on_leave_docs(*, root: Path, git: GitIntegration, status: FlowStatus | None) -> None: def _hook_changelog_on_leave_docs(*, root: Path, git: GitIntegration, status: FlowStatus | None) -> None:

View File

@@ -144,6 +144,7 @@ class FlowTracker:
else: else:
validator.validate_phase_exists(to_phase) validator.validate_phase_exists(to_phase)
config = self.cfg.load_config()
run_pre_commit_hooks( run_pre_commit_hooks(
root=self.root, root=self.root,
git=self.git, git=self.git,
@@ -151,6 +152,7 @@ class FlowTracker:
from_phase=from_phase, from_phase=from_phase,
to_phase=to_phase, to_phase=to_phase,
action=action, action=action,
config=config,
) )
message = _build_commit_message(action=action, phase=to_phase, text=text) message = _build_commit_message(action=action, phase=to_phase, text=text)