"""Pinterest 并发生成流水线节点 3/3:收尾(pinterest_finalize)。 分析循环结束后:排空简报池、等待后台全部产品完成(设计→三合一→OSS→种草图), 合并产品到 state,补写 compose 简报报告与 products.json,再交给 template_export。 """ from pathlib import Path from typing import Any, Dict from graph.validate import with_fallback @with_fallback("pinterest_finalize") def pinterest_finalize_node(state: Dict[str, Any]) -> Dict[str, Any]: pipe = state.get("pinterest_pipeline") products: list = [] perr: list = [] if pipe is not None: products, perr = pipe.finish() # 合并后台产出的产品(与已存在的合并,避免覆盖) state_products = list(state.get("product") or []) state_products.extend(products) # 补写 compose 简报报告(design_briefs / composite_prompts / report.md) try: from graph.nodes.compose_node import write_compose_reports write_compose_reports(state, state.get("briefs") or []) except Exception as e: # noqa: BLE001 print(f"[pinterest_finalize] 简报报告写入失败: {e}") # 写 products.json(product 节点原职责) try: from graph.nodes.product_node import _write_products prod_dir = Path(state["output_dir"]) / "product" prod_dir.mkdir(parents=True, exist_ok=True) _write_products(prod_dir, state_products) except Exception as e: # noqa: BLE001 print(f"[pinterest_finalize] products.json 写入失败: {e}") stats = dict(state.get("stats") or {}) stats["pinterest_pipeline"] = {"products": len(products), "errors": len(perr)} errors = list(state.get("errors") or []) + perr oss_seq = getattr(pipe, "oss_seq", state.get("oss_seq", 0)) if pipe is not None \ else state.get("oss_seq", 0) print(f"[pinterest_finalize] 收尾完成:合并 {len(state_products)} 个产品," f"后台错误 {len(perr)},oss_seq={oss_seq}") return {"product": state_products, "oss_seq": oss_seq, "errors": errors, "stats": stats}