Files
xuhdandClaude Opus 4.7 f80a00e211 feat(skills): curator 面板加 pinned 计数 + 运行时输出技能名日志
- get_curator_status 的 agent_created_skills 增加 pinned 计数,与
  active/stale/archived 正交;前端技能进化面板同步展示「被钉住」一项
  (curator/types.ts、skill-evolution-panel.tsx、zh-CN/en-US/types i18n)。
- run_curator_review 每次运行时把涉及的技能名输出到日志:新增
  _log_scanned_skills(扫描到的技能名)与 _candidate_skill_names
  (候选技能名),logger 与 curator_log 双写。

新增 test_curator_status_counts.py、test_curator_skill_logging.py。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 15:25:13 +08:00

60 lines
2.4 KiB
Python

"""get_curator_status 的技能计数 —— 含与生命周期正交的 pinned 计数。"""
from __future__ import annotations
from deerflow.config.skill_evolution_config import CuratorConfig
from deerflow.skills import curator
def _patch(monkeypatch, entries: dict) -> None:
"""注入受控依赖:固定 curator 状态/配置,owned 用 legacy 全量,entries 由测试给定。"""
monkeypatch.setattr(curator, "_read_curator_state", lambda uid: {})
monkeypatch.setattr(curator, "_list_user_owned_skill_names", lambda uid: None)
monkeypatch.setattr(curator, "_get_curator_config", lambda uid: CuratorConfig(enabled=True))
monkeypatch.setattr(
"deerflow.skills.usage.agent_created_entries",
lambda: entries,
)
def test_counts_by_state(monkeypatch):
entries = {
"a": {"source": "agent", "state": "active"},
"b": {"source": "agent", "state": "active"},
"c": {"source": "agent", "state": "stale"},
"d": {"source": "agent", "state": "archived"},
}
_patch(monkeypatch, entries)
counts = curator.get_curator_status("u1")["agent_created_skills"]
assert counts == {"total": 4, "active": 2, "stale": 1, "archived": 1, "pinned": 0}
def test_pinned_count_is_orthogonal_to_state(monkeypatch):
# pinned 与 active/stale/archived 正交:一个 active+pinned、一个 archived+pinned
entries = {
"a": {"source": "agent", "state": "active", "pinned": True},
"b": {"source": "agent", "state": "active"},
"c": {"source": "agent", "state": "archived", "pinned": True},
"d": {"source": "agent", "state": "stale"},
}
_patch(monkeypatch, entries)
counts = curator.get_curator_status("u1")["agent_created_skills"]
assert counts["total"] == 4
assert counts["active"] == 2
assert counts["stale"] == 1
assert counts["archived"] == 1
# pinned 单独统计,不受状态影响,也不计入上面三者之和
assert counts["pinned"] == 2
def test_pinned_zero_when_none_pinned(monkeypatch):
_patch(monkeypatch, {"a": {"source": "agent", "state": "active"}})
counts = curator.get_curator_status("u1")["agent_created_skills"]
assert counts["pinned"] == 0
def test_empty_skills(monkeypatch):
_patch(monkeypatch, {})
counts = curator.get_curator_status("u1")["agent_created_skills"]
assert counts == {"total": 0, "active": 0, "stale": 0, "archived": 0, "pinned": 0}