diff --git a/astrbot/core/astr_main_agent.py b/astrbot/core/astr_main_agent.py index b28959aa62..1a8f68a8c1 100644 --- a/astrbot/core/astr_main_agent.py +++ b/astrbot/core/astr_main_agent.py @@ -11,6 +11,7 @@ from typing import Any, TypeGuard, cast from astrbot import logger +from astrbot.core.agent.btw.loop_routes import route_is_available_in_loop from astrbot.core.agent.btw.runtime_policy import resolve_computer_runtime from astrbot.core.agent.chat_model import ChatModel from astrbot.core.agent.handoff import HandoffTool @@ -560,6 +561,11 @@ def _append_skills_prompt( plugin_context: CoreExecutionContext, ) -> SkillSnapshot: runtime = str(cfg.get("computer_use_runtime", "none") or "none") + profile = plugin_context.get_config(umo=event.unified_msg_origin) + btw_config = profile.get("btw", {}) + btw_config = btw_config if isinstance(btw_config, dict) else {} + btw_enabled = bool(btw_config.get("enabled", False)) + loop_mode = "work" if event.get_extra("btw_loop") == "work" else "conversation" skill_manager = plugin_context.skill_manager or SkillManager( builtin_skill_catalog=plugin_context.catalogs.builtin_skills, ) @@ -568,11 +574,22 @@ def _append_skills_prompt( cfg, plugin_context.catalogs.plugins, ) + if btw_enabled: + skills = [ + skill + for skill in skills + if route_is_available_in_loop( + btw_config.get("skill_routes"), + route_key="skill_name", + route_id=skill.name, + loop_mode=loop_mode, + ) + ] workspace_skills = ( skill_manager.list_workspace_skills( _get_workspace_path_for_umo(event.unified_msg_origin) ) - if runtime == "local" + if runtime == "local" and (not btw_enabled or loop_mode == "work") else [] ) if persona and persona.get("skills") is not None: diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index 7fb4da990a..e8116a8314 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -200,6 +200,7 @@ "work_session": {"max_age_seconds": 3600}, "plugin_routes": [], "mcp_routes": [], + "skill_routes": [], }, "provider_stt_settings": { "enable": False, @@ -4760,6 +4761,13 @@ "_special": "select_mcp_loop_routes", "condition": {"btw.enabled": True}, }, + "btw.skill_routes": { + "description": "Skills 循环分配", + "type": "list", + "hint": "普通 Skill 默认注入两个循环,可显式限制到单一循环;工作区 Skill 仅在本地工作循环可用。", + "_special": "select_skill_loop_routes", + "condition": {"btw.enabled": True}, + }, }, } diff --git a/dashboard/src/components/shared/CapabilityLoopSelector.vue b/dashboard/src/components/shared/CapabilityLoopSelector.vue index 09c20e69ec..7474638534 100644 --- a/dashboard/src/components/shared/CapabilityLoopSelector.vue +++ b/dashboard/src/components/shared/CapabilityLoopSelector.vue @@ -40,15 +40,16 @@