Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion astrbot/core/astr_main_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,9 @@ async def _apply_workspace_extra_prompt(
req: ProviderRequest,
plugin_context: Context,
) -> None:
if event.get_group_id():
return

workspace_root = await _get_workspace_path_for_umo(
event.unified_msg_origin,
plugin_context,
Expand Down Expand Up @@ -569,7 +572,7 @@ async def _ensure_persona_and_skills(
skills = skill_manager.list_skills(active_only=True, runtime=runtime)
skills = _filter_skills_for_current_config(skills, cfg)
workspace_skills: list[SkillInfo] = []
if runtime == "local":
if runtime == "local" and not event.get_group_id():
workspace_root = await _get_workspace_path_for_umo(
event.unified_msg_origin,
plugin_context,
Expand Down
126 changes: 117 additions & 9 deletions tests/unit/test_astr_main_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,12 @@ def now(cls, tz=None):


def test_local_mode_prompt_uses_windows_powershell_51():
with patch("astrbot.core.astr_main_agent.platform.system", return_value="Windows"), patch(
"astrbot.core.astr_main_agent.resolve_windows_shell",
return_value="powershell.exe",
with (
patch("astrbot.core.astr_main_agent.platform.system", return_value="Windows"),
patch(
"astrbot.core.astr_main_agent.resolve_windows_shell",
return_value="powershell.exe",
),
):
prompt = ama._build_local_mode_prompt()

Expand All @@ -188,9 +191,12 @@ def test_local_mode_prompt_uses_windows_powershell_51():


def test_local_mode_prompt_hints_pwsh_when_resolved():
with patch("astrbot.core.astr_main_agent.platform.system", return_value="Windows"), patch(
"astrbot.core.astr_main_agent.resolve_windows_shell",
return_value="pwsh.exe",
with (
patch("astrbot.core.astr_main_agent.platform.system", return_value="Windows"),
patch(
"astrbot.core.astr_main_agent.resolve_windows_shell",
return_value="pwsh.exe",
),
):
prompt = ama._build_local_mode_prompt()

Expand All @@ -200,9 +206,12 @@ def test_local_mode_prompt_hints_pwsh_when_resolved():


def test_local_mode_prompt_ignores_pwsh_on_non_windows():
with patch("astrbot.core.astr_main_agent.platform.system", return_value="Linux"), patch(
"astrbot.core.astr_main_agent.resolve_windows_shell",
return_value="pwsh.exe",
with (
patch("astrbot.core.astr_main_agent.platform.system", return_value="Linux"),
patch(
"astrbot.core.astr_main_agent.resolve_windows_shell",
return_value="pwsh.exe",
),
):
prompt = ama._build_local_mode_prompt()

Expand Down Expand Up @@ -1016,6 +1025,70 @@ async def test_ensure_skills_includes_workspace_skills(
in req.system_prompt
)

@pytest.mark.asyncio
async def test_ensure_skills_skips_workspace_skills_for_group_sessions(
self,
monkeypatch,
tmp_path,
mock_event,
mock_context,
):
module = ama
data_dir = tmp_path / "data"
global_skills_dir = tmp_path / "global_skills"
plugins_dir = tmp_path / "plugins"
workspaces_dir = tmp_path / "workspaces"
for path in (data_dir, global_skills_dir, plugins_dir):
path.mkdir(parents=True, exist_ok=True)

global_skill_dir = global_skills_dir / "workspace-skill"
global_skill_dir.mkdir(parents=True)
global_skill_dir.joinpath("SKILL.md").write_text(
"---\ndescription: Global scoped skill.\n---\n",
encoding="utf-8",
)

mock_event.get_group_id.return_value = "group123"
mock_event.message_obj.group_id = "group123"
mock_event.unified_msg_origin = "test_platform:GroupMessage:group123"
workspace_root = workspaces_dir / module.normalize_umo_for_workspace(
mock_event.unified_msg_origin
)
workspace_skill_dir = workspace_root / "skills" / "workspace-skill"
workspace_skill_dir.mkdir(parents=True)
workspace_skill_dir.joinpath("SKILL.md").write_text(
"---\ndescription: Workspace scoped skill.\n---\n",
encoding="utf-8",
)

monkeypatch.setattr(
module,
"get_astrbot_workspaces_path",
lambda: str(workspaces_dir),
)
monkeypatch.setattr(
"astrbot.core.skills.skill_manager.get_astrbot_data_path",
lambda: str(data_dir),
)
monkeypatch.setattr(
"astrbot.core.skills.skill_manager.get_astrbot_skills_path",
lambda: str(global_skills_dir),
)
monkeypatch.setattr(
"astrbot.core.skills.skill_manager.get_astrbot_plugin_path",
lambda: str(plugins_dir),
)

req = ProviderRequest()
req.conversation = MagicMock(persona_id=None)

await module._ensure_persona_and_skills(
req, {"computer_use_runtime": "local"}, mock_context, mock_event
)

assert "Global scoped skill." in req.system_prompt
assert "Workspace scoped skill." not in req.system_prompt

@pytest.mark.asyncio
async def test_ensure_skills_respects_empty_persona_skills_for_workspace(
self,
Expand Down Expand Up @@ -1379,6 +1452,41 @@ async def test_decorate_llm_request_no_conversation(self, mock_event, mock_conte

assert req.prompt == "Hello"

@pytest.mark.asyncio
async def test_decorate_llm_request_skips_workspace_extra_prompt_for_group(
self,
monkeypatch,
tmp_path,
mock_event,
mock_context,
sample_config,
):
"""Test group sessions do not load workspace extra prompts."""
module = ama
workspaces_dir = tmp_path / "workspaces"
mock_event.get_group_id.return_value = "group123"
mock_event.message_obj.group_id = "group123"
mock_event.unified_msg_origin = "test_platform:GroupMessage:group123"
workspace_root = workspaces_dir / module.normalize_umo_for_workspace(
mock_event.unified_msg_origin
)
workspace_root.mkdir(parents=True)
workspace_root.joinpath("EXTRA_PROMPT.md").write_text(
"Group workspace injected prompt.",
encoding="utf-8",
)
monkeypatch.setattr(
module,
"get_astrbot_workspaces_path",
lambda: str(workspaces_dir),
)
req = ProviderRequest(prompt="Hello", system_prompt="System")
req.conversation = None

await module._decorate_llm_request(mock_event, req, mock_context, sample_config)

assert req.system_prompt == "System"


class TestPluginToolFix:
"""Tests for _plugin_tool_fix function."""
Expand Down
Loading