"""内置「模板数据转换器」agent 的「缺失自动补建」工具。 ``template-json-builder`` 是定时任务「JSON → HTML 模板填充」功能的执行大脑:当用户在 定时任务表单里选中它、再选一个 HTML 模板时,到点执行会用它的 ``SOUL.md`` 把源 JSON 智能映射成模板需要的 ``DATA`` 结构(详见 :mod:`deerflow.runtime.scheduler.template_fill` 与调度器 ``service.py``)。 与 ``_ai_writing_seed.py`` / ``_roundtable_seed.py`` 完全同构:验证版 ``SOUL.md`` + ``config.yaml`` 随 git 发布于 ``_template_builder_seed_assets//``,seeder 只在 ``.deer-flow/agents//`` 目录**缺失**时字节级复制(绝不覆盖线上手改)。lifespan 在 ``_sync_legacy_agents`` 之前调用本 seeder,后者扫描 agents 目录把它 upsert 进 agents 表 (``user_id IS NULL`` 内置、``published=True``),于是 ``/api/agents`` 列表、进而定时任务 「执行智能体」下拉框里第一次启动就有它,admin 也能在智能体管理页编辑 SOUL/模型。 """ from __future__ import annotations import logging from pathlib import Path from deerflow.config.paths import get_paths logger = logging.getLogger(__name__) TEMPLATE_BUILDER_AGENT_ID = "template-json-builder" # 验证版 SOUL.md + config.yaml 的源码资源目录(随 git 发布)。子目录名即 agent id。 _ASSETS_DIR = Path(__file__).parent / "_template_builder_seed_assets" # seeder 复制的文件(存在即复制,缺失则跳过)。 _SEED_FILES: tuple[str, ...] = ("config.yaml", "SOUL.md") def ensure_template_builder_agent() -> bool: """若 ``.deer-flow/agents/template-json-builder/`` 缺失,从资源补建。 返回 True 表示本次刚创建;目录已存在(尊重本地手改)或资源缺失则返回 False。 错误只记日志、绝不抛出——seeding 失败不能拖垮启动。 """ try: agent_dir = get_paths().agent_dir(TEMPLATE_BUILDER_AGENT_ID) if agent_dir.exists(): return False src_dir = _ASSETS_DIR / TEMPLATE_BUILDER_AGENT_ID if not src_dir.is_dir(): logger.error( "Missing seed assets for agent '%s' (expected at %s)", TEMPLATE_BUILDER_AGENT_ID, src_dir, ) return False agent_dir.mkdir(parents=True, exist_ok=True) for fname in _SEED_FILES: src = src_dir / fname if src.exists(): (agent_dir / fname).write_bytes(src.read_bytes()) logger.info("Seeded built-in agent '%s'", TEMPLATE_BUILDER_AGENT_ID) return True except Exception: logger.exception("Failed to seed built-in agent '%s'", TEMPLATE_BUILDER_AGENT_ID) return False