deerflow-code/offline-backend-20260512/backend/app/gateway/routers/_template_builder_seed.py
2026-09-07 18:24:55 +08:00

64 lines
2.7 KiB
Python

"""内置「模板数据转换器」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/<id>/``,seeder 只在
``.deer-flow/agents/<id>/`` 目录**缺失**时字节级复制(绝不覆盖线上手改)。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