"""深度研究「收集员」内置 agent 的启动补建 seeder。 与 ``_ai_writing_seed.py`` / ``_roundtable_seed.py`` 完全同构:资源文件 (``_deep_research_seed_assets/deep-research-collector/``)是发布默认值的 唯一可信源,seeder 只在 ``.deer-flow/agents/deep-research-collector/`` 目录缺失时字节级复制,**绝不覆盖**已存在目录(尊重 admin 在智能体管理页 的现场修改)。线上调优 SOUL 后请把改动写回资源文件,否则新机器补建出来 的还是旧版。 调用点:启动 lifespan(``app/gateway/app.py``),必须在 ``_sync_legacy_agents`` **之前**——后者会把目录 upsert 进 agents 表(`user_id IS NULL` 的内置 agent),所有用户即可在深度研究页使用。 """ from __future__ import annotations import logging from pathlib import Path from deerflow.config.paths import get_paths logger = logging.getLogger(__name__) DEEP_RESEARCH_COLLECTOR_AGENT_ID = "deep-research-collector" _ASSETS_DIR = Path(__file__).parent / "_deep_research_seed_assets" _SEED_FILES: tuple[str, ...] = ("config.yaml", "SOUL.md") def _ensure_one(agent_id: str) -> bool: """Copy the verified SOUL.md + config.yaml into ``.deer-flow/agents//`` if that directory is missing. Returns True if the files were just created, False if the directory already existed (never overwrite — respect local edits) or the seed assets are missing. """ agent_dir = get_paths().agent_dir(agent_id) if agent_dir.exists(): return False src_dir = _ASSETS_DIR / agent_id if not src_dir.is_dir(): logger.error( "Missing seed assets for deep-research agent '%s' (expected at %s)", 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()) return True def ensure_deep_research_collector_agent() -> list[str]: """Seed the deep-research collector agent if its on-disk directory is missing. Idempotent — fast no-op when it exists. Returns the list of agent ids just created (empty when nothing needed seeding). Errors are logged but never raised — a seed failure must not block startup. """ created: list[str] = [] try: if _ensure_one(DEEP_RESEARCH_COLLECTOR_AGENT_ID): created.append(DEEP_RESEARCH_COLLECTOR_AGENT_ID) except Exception: logger.exception("Failed to seed deep-research collector agent") if created: logger.info("Seeded missing deep-research collector agent: %s", ", ".join(created)) return created __all__ = ["DEEP_RESEARCH_COLLECTOR_AGENT_ID", "ensure_deep_research_collector_agent"]