feat: Add evaluation hooks, skill adaptation and team pipeline config
- Add EvaluationHook for post-execution agent evaluation - Add SkillAdaptationHook for dynamic skill adaptation - Add team/ directory with team coordination logic - Add TEAM_PIPELINE.yaml for smoke_fullstack pipeline config - Update RuntimeView, TraderView and RuntimeSettingsPanel UI - Add runtimeApi and websocket services - Add runtime_state.json to smoke_fullstack state Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
以及合并Agent特定工具。
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, Iterable, List, Optional
|
||||
from typing import Any, Dict, Iterable, List, Optional, Set
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
@@ -13,6 +13,7 @@ import yaml
|
||||
from backend.agents.agent_workspace import load_agent_workspace_config
|
||||
from backend.agents.skills_manager import SkillsManager
|
||||
from backend.agents.skill_loader import load_skill_from_dir, get_skill_tools
|
||||
from backend.agents.skill_metadata import parse_skill_metadata
|
||||
from backend.config.bootstrap_config import get_bootstrap_config_for_run
|
||||
|
||||
|
||||
@@ -117,6 +118,26 @@ def _register_portfolio_tool_groups(toolkit: Any, pm_agent: Any) -> None:
|
||||
pm_agent._make_decision,
|
||||
group_name="portfolio_ops",
|
||||
)
|
||||
if hasattr(pm_agent, "_add_team_analyst"):
|
||||
toolkit.register_tool_function(
|
||||
pm_agent._add_team_analyst,
|
||||
group_name="portfolio_ops",
|
||||
)
|
||||
if hasattr(pm_agent, "_remove_team_analyst"):
|
||||
toolkit.register_tool_function(
|
||||
pm_agent._remove_team_analyst,
|
||||
group_name="portfolio_ops",
|
||||
)
|
||||
if hasattr(pm_agent, "_set_active_analysts"):
|
||||
toolkit.register_tool_function(
|
||||
pm_agent._set_active_analysts,
|
||||
group_name="portfolio_ops",
|
||||
)
|
||||
if hasattr(pm_agent, "_create_team_analyst"):
|
||||
toolkit.register_tool_function(
|
||||
pm_agent._create_team_analyst,
|
||||
group_name="portfolio_ops",
|
||||
)
|
||||
|
||||
|
||||
def _register_risk_tool_groups(toolkit: Any) -> None:
|
||||
@@ -223,6 +244,8 @@ def create_agent_toolkit(
|
||||
for skill_dir in active_skill_dirs:
|
||||
toolkit.register_agent_skill(str(skill_dir))
|
||||
|
||||
apply_skill_tool_restrictions(toolkit, active_skill_dirs)
|
||||
|
||||
if active_groups:
|
||||
toolkit.update_tool_groups(group_names=active_groups, active=True)
|
||||
|
||||
@@ -309,6 +332,8 @@ def create_toolkit_from_workspace(
|
||||
for skill_dir in skill_dirs:
|
||||
toolkit.register_agent_skill(str(skill_dir))
|
||||
|
||||
apply_skill_tool_restrictions(toolkit, skill_dirs)
|
||||
|
||||
# 激活指定的工具组
|
||||
if active_groups is None:
|
||||
# 从配置中读取
|
||||
@@ -397,3 +422,96 @@ def refresh_toolkit_skills(
|
||||
for skill_dir in sorted(local_root.iterdir()):
|
||||
if skill_dir.is_dir() and (skill_dir / "SKILL.md").exists():
|
||||
toolkit.register_agent_skill(str(skill_dir))
|
||||
|
||||
|
||||
def apply_skill_tool_restrictions(toolkit: Any, skill_dirs: List[Path]) -> None:
|
||||
"""Apply per-skill allowed_tools / denied_tools restrictions to a toolkit.
|
||||
|
||||
If a skill specifies allowed_tools, only those tools are accessible when
|
||||
that skill is active. If a skill specifies denied_tools, those tools are
|
||||
removed regardless of allowed_tools. Denied tools take precedence.
|
||||
|
||||
This function annotates the toolkit with a _skill_tool_restrictions map
|
||||
that downstream code can consult when resolving available tools.
|
||||
|
||||
Args:
|
||||
toolkit: The agentscope Toolkit instance.
|
||||
skill_dirs: List of skill directory paths to inspect.
|
||||
"""
|
||||
restrictions: Dict[str, Dict[str, Set[str]]] = {}
|
||||
for skill_dir in skill_dirs:
|
||||
metadata = parse_skill_metadata(skill_dir, source="active")
|
||||
if not metadata.allowed_tools and not metadata.denied_tools:
|
||||
continue
|
||||
restrictions[skill_dir.name] = {
|
||||
"allowed": set(metadata.allowed_tools),
|
||||
"denied": set(metadata.denied_tools),
|
||||
}
|
||||
if hasattr(toolkit, "agent_skills"):
|
||||
for skill in toolkit.agent_skills:
|
||||
skill_name = getattr(skill, "name", "") or ""
|
||||
if skill_name in restrictions:
|
||||
setattr(
|
||||
skill,
|
||||
"_tool_allowed",
|
||||
restrictions[skill_name]["allowed"],
|
||||
)
|
||||
setattr(
|
||||
skill,
|
||||
"_tool_denied",
|
||||
restrictions[skill_name]["denied"],
|
||||
)
|
||||
|
||||
|
||||
def get_skill_effective_tools(skill: Any) -> Optional[Set[str]]:
|
||||
"""Return the effective tool set for a skill after applying restrictions.
|
||||
|
||||
If the skill has no restrictions (no allowed_tools / denied_tools),
|
||||
returns None to indicate "all tools allowed".
|
||||
|
||||
If allowed_tools is set, returns only those tools minus denied_tools.
|
||||
If only denied_tools is set, returns all tools minus denied_tools.
|
||||
|
||||
Args:
|
||||
skill: A skill object previously registered via register_agent_skill.
|
||||
|
||||
Returns:
|
||||
A set of allowed tool names, or None if unrestricted.
|
||||
"""
|
||||
allowed = getattr(skill, "_tool_allowed", None)
|
||||
denied = getattr(skill, "_tool_denied", set())
|
||||
|
||||
if allowed is None:
|
||||
return None
|
||||
|
||||
effective = allowed - denied
|
||||
return effective
|
||||
|
||||
|
||||
def filter_toolkit_by_skill(
|
||||
toolkit: Any,
|
||||
skill_name: str,
|
||||
) -> Set[str]:
|
||||
"""Return the set of tool names that are accessible for a given skill.
|
||||
|
||||
Args:
|
||||
toolkit: The agentscope Toolkit instance.
|
||||
skill_name: Name of the skill to query.
|
||||
|
||||
Returns:
|
||||
Set of allowed tool names, or all registered tool names if unrestricted.
|
||||
"""
|
||||
if not hasattr(toolkit, "agent_skills"):
|
||||
return set()
|
||||
|
||||
for skill in toolkit.agent_skills:
|
||||
name = getattr(skill, "name", "") or ""
|
||||
if name != skill_name:
|
||||
continue
|
||||
effective = get_skill_effective_tools(skill)
|
||||
if effective is None:
|
||||
return set()
|
||||
return effective
|
||||
|
||||
return set()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user