88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
"""深度研究内置 agent 的启动补建 seeder。
|
|
|
|
与 ``_ai_writing_seed.py`` / ``_roundtable_seed.py`` 完全同构:资源文件
|
|
(``_deep_research_seed_assets/<agent-id>/``)是发布默认值的唯一可信源,
|
|
seeder 只在 ``.deer-flow/agents/<agent-id>/`` 目录缺失时字节级复制,
|
|
**绝不覆盖**已存在目录(尊重 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"
|
|
DEEP_RESEARCH_PLANNER_AGENT_ID = "deep-research-planner"
|
|
_DEEP_RESEARCH_AGENT_IDS = (
|
|
DEEP_RESEARCH_COLLECTOR_AGENT_ID,
|
|
DEEP_RESEARCH_PLANNER_AGENT_ID,
|
|
)
|
|
|
|
_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/<id>/``
|
|
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 built-in deep-research agents if their on-disk directories are
|
|
missing. Idempotent — fast no-op when they exist.
|
|
|
|
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:
|
|
for agent_id in _DEEP_RESEARCH_AGENT_IDS:
|
|
if _ensure_one(agent_id):
|
|
created.append(agent_id)
|
|
except Exception:
|
|
logger.exception("Failed to seed deep-research agents")
|
|
if created:
|
|
logger.info("Seeded missing deep-research agents: %s", ", ".join(created))
|
|
return created
|
|
|
|
|
|
__all__ = [
|
|
"DEEP_RESEARCH_COLLECTOR_AGENT_ID",
|
|
"DEEP_RESEARCH_PLANNER_AGENT_ID",
|
|
"ensure_deep_research_collector_agent",
|
|
]
|