From 69454ada69952908ea41535a6ede66ef5a8563d8 Mon Sep 17 00:00:00 2001 From: xuhd Date: Wed, 3 Jun 2026 16:14:30 +0800 Subject: [PATCH] feat(skill-evolution): add ReviewWorkerConfig to SkillEvolutionConfig Co-Authored-By: Claude Sonnet 4.6 --- .../deerflow/config/skill_evolution_config.py | 69 +++++++++++-------- .../backend/tests/test_skill_review_worker.py | 19 +++++ 2 files changed, 58 insertions(+), 30 deletions(-) create mode 100644 offline-backend-20260512/backend/tests/test_skill_review_worker.py diff --git a/offline-backend-20260512/backend/packages/harness/deerflow/config/skill_evolution_config.py b/offline-backend-20260512/backend/packages/harness/deerflow/config/skill_evolution_config.py index a6813313..45962647 100644 --- a/offline-backend-20260512/backend/packages/harness/deerflow/config/skill_evolution_config.py +++ b/offline-backend-20260512/backend/packages/harness/deerflow/config/skill_evolution_config.py @@ -1,30 +1,39 @@ -from pydantic import BaseModel, Field - - -class CuratorConfig(BaseModel): - """Configuration for the background skill curator.""" - - # 默认关闭:curator 仅在用户显式开启时才运行(配合 SkillEvolutionConfig.enabled - # 总开关,二者均为安全默认 False —— 未显式 opt-in 则整套技能进化不动作)。 - enabled: bool = Field(default=False, description="Whether the curator runs automatically.") - interval_hours: int = Field(default=168, description="Hours between curator runs (default: 7 days).") - stale_after_days: int = Field(default=30, description="Days of inactivity before a skill is marked stale.") - archive_after_days: int = Field(default=90, description="Days of inactivity before a stale skill is archived.") - # LLM 评审整体超时:agent.invoke 内部可能多轮调 LLM,模型层的单次 request_timeout - # 兜不住整体;超过此秒数则中止本次评审,curator 正常收尾并释放运行锁。 - review_timeout_seconds: int = Field(default=600, description="Overall timeout (seconds) for the LLM review pass.") - # curator LLM 评审使用的模型名(对应 config.yaml models[].name);为空则用主模型。 - model_name: str | None = Field(default=None, description="Model name for the curator LLM review pass. Defaults to the primary chat model.") - - -class SkillEvolutionConfig(BaseModel): - """Configuration for agent-managed skill evolution.""" - - enabled: bool = Field( - default=False, - description="Whether the agent can create and modify skills under skills/custom.", - ) - curator: CuratorConfig = Field( - default_factory=CuratorConfig, - description="Configuration for the background skill curator.", - ) +from pydantic import BaseModel, Field + + +class ReviewWorkerConfig(BaseModel): + """Configuration for the post-turn background skill review worker.""" + + enabled: bool = Field(default=False, description="Whether the review worker is active.") + min_tool_calls: int = Field(default=3, description="Minimum tool calls in a turn to trigger review.") + max_messages: int = Field(default=60, description="Max messages passed to the review LLM.") + model_name: str | None = Field(default=None, description="Model to use for review; defaults to primary model.") + timeout_seconds: int = Field(default=120, description="Overall timeout for a single review run.") + + +class CuratorConfig(BaseModel): + """Configuration for the background skill curator.""" + + enabled: bool = Field(default=False, description="Whether the curator runs automatically.") + interval_hours: int = Field(default=168, description="Hours between curator runs (default: 7 days).") + stale_after_days: int = Field(default=30, description="Days of inactivity before a skill is marked stale.") + archive_after_days: int = Field(default=90, description="Days of inactivity before a stale skill is archived.") + review_timeout_seconds: int = Field(default=600, description="Overall timeout (seconds) for the LLM review pass.") + model_name: str | None = Field(default=None, description="Model name for the curator LLM review pass. Defaults to the primary chat model.") + + +class SkillEvolutionConfig(BaseModel): + """Configuration for agent-managed skill evolution.""" + + enabled: bool = Field( + default=False, + description="Whether the agent can create and modify skills under skills/custom.", + ) + curator: CuratorConfig = Field( + default_factory=CuratorConfig, + description="Configuration for the background skill curator.", + ) + review_worker: ReviewWorkerConfig = Field( + default_factory=ReviewWorkerConfig, + description="Configuration for the post-turn background skill review worker.", + ) diff --git a/offline-backend-20260512/backend/tests/test_skill_review_worker.py b/offline-backend-20260512/backend/tests/test_skill_review_worker.py new file mode 100644 index 00000000..436cdae5 --- /dev/null +++ b/offline-backend-20260512/backend/tests/test_skill_review_worker.py @@ -0,0 +1,19 @@ +from deerflow.config.skill_evolution_config import SkillEvolutionConfig, ReviewWorkerConfig + + +def test_review_worker_config_defaults(): + cfg = SkillEvolutionConfig() + assert cfg.review_worker.enabled is False + assert cfg.review_worker.min_tool_calls == 3 + assert cfg.review_worker.timeout_seconds == 120 + assert cfg.review_worker.model_name is None + + +def test_review_worker_config_from_dict(): + cfg = SkillEvolutionConfig.model_validate({ + "enabled": True, + "review_worker": {"enabled": True, "min_tool_calls": 5, "model_name": "my-model"}, + }) + assert cfg.review_worker.enabled is True + assert cfg.review_worker.min_tool_calls == 5 + assert cfg.review_worker.model_name == "my-model"