mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-09-04 02:01:48 +03:00
fix(agent): keep default prompt paths relative
This commit is contained in:
@@ -84,7 +84,10 @@ def test_plugin_skill_lifecycle_and_precedence(tmp_path: Path) -> None:
|
||||
assert loader.get_explicitly_invoked_skills("Use $shared") == ["shared"]
|
||||
assert loader.get_always_skills() == ["shared"]
|
||||
assert "Plugin body" in (loader.load_skill("shared") or "")
|
||||
assert "`demo/skills/shared/SKILL.md`" in loader.build_skills_summary()
|
||||
summary = loader.build_skills_summary()
|
||||
assert "### Agent Plugin skills (`plugins`)" in summary
|
||||
assert "`demo/skills/shared/SKILL.md`" in summary
|
||||
assert str(tmp_path.resolve()) not in summary
|
||||
|
||||
set_agent_plugin_enabled(tmp_path, "demo", False)
|
||||
assert [entry["source"] for entry in loader.list_skills()] == ["builtin"]
|
||||
|
||||
@@ -309,6 +309,14 @@ class TestBuildSystemPrompt:
|
||||
result = builder.build_system_prompt()
|
||||
assert "workspace" in result.lower() or "python" in result.lower()
|
||||
|
||||
def test_default_identity_uses_relative_agent_paths(self, tmp_path):
|
||||
result = ContextBuilder(tmp_path)._get_identity()
|
||||
|
||||
assert str(tmp_path.resolve()) not in result
|
||||
assert "Agent profile: SOUL.md and USER.md" in result
|
||||
assert "History log: memory/history.jsonl" in result
|
||||
assert "Custom skills: skills/{skill-name}/SKILL.md" in result
|
||||
|
||||
def test_selected_project_identity_keeps_agent_data_in_agent_workspace(self, tmp_path):
|
||||
agent_home = tmp_path / "agent-home"
|
||||
project = tmp_path / "project"
|
||||
@@ -317,7 +325,7 @@ class TestBuildSystemPrompt:
|
||||
|
||||
result = ContextBuilder(agent_home)._get_identity(workspace=project)
|
||||
|
||||
assert f"current project workspace is at: {project.resolve()}" in result
|
||||
assert str(project.resolve()) not in result
|
||||
assert f"agent workspace is at: {agent_home.resolve()}" in result
|
||||
assert f"{agent_home.resolve()}/SOUL.md" in result
|
||||
assert f"{project.resolve()}/SOUL.md" not in result
|
||||
|
||||
@@ -298,7 +298,7 @@ def test_disabled_skills_excluded_from_build_skills_summary(tmp_path: Path) -> N
|
||||
assert "beta" in summary
|
||||
|
||||
|
||||
def test_build_skills_summary_groups_paths_by_root(tmp_path: Path) -> None:
|
||||
def test_build_skills_summary_uses_relative_roots_in_agent_workspace(tmp_path: Path) -> None:
|
||||
workspace = tmp_path / "ws"
|
||||
workspace_skills = workspace / "skills"
|
||||
workspace_skills.mkdir(parents=True)
|
||||
@@ -308,14 +308,34 @@ def test_build_skills_summary_groups_paths_by_root(tmp_path: Path) -> None:
|
||||
|
||||
summary = SkillsLoader(workspace, builtin_skills_dir=builtin).build_skills_summary()
|
||||
|
||||
assert summary.count(str(workspace_skills)) == 1
|
||||
assert summary.count(str(builtin)) == 1
|
||||
assert str(workspace_skills) not in summary
|
||||
assert str(builtin) not in summary
|
||||
assert str(workspace_path) not in summary
|
||||
assert str(builtin_path) not in summary
|
||||
assert summary.count("(`skills`)") == 2
|
||||
assert "`alpha/SKILL.md`" in summary
|
||||
assert "`beta/SKILL.md`" in summary
|
||||
|
||||
|
||||
def test_build_skills_summary_keeps_absolute_roots_for_selected_project(tmp_path: Path) -> None:
|
||||
workspace = tmp_path / "ws"
|
||||
workspace_skills = workspace / "skills"
|
||||
workspace_skills.mkdir(parents=True)
|
||||
_write_skill(workspace_skills, "alpha", body="# Alpha")
|
||||
builtin = tmp_path / "builtin"
|
||||
_write_skill(builtin, "beta", body="# Beta")
|
||||
project = tmp_path / "project"
|
||||
project.mkdir()
|
||||
|
||||
summary = SkillsLoader(workspace, builtin_skills_dir=builtin).build_skills_summary(
|
||||
workspace=project,
|
||||
)
|
||||
|
||||
assert summary.count(str(workspace_skills.resolve())) == 1
|
||||
assert summary.count(str(builtin.resolve())) == 1
|
||||
assert str(project.resolve()) not in summary
|
||||
|
||||
|
||||
def test_bundled_update_setup_description_is_valid_yaml(tmp_path: Path) -> None:
|
||||
metadata = SkillsLoader(tmp_path).get_skill_metadata("update-setup")
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ def test_subagent_respects_file_tool_toggle(tmp_path):
|
||||
assert file_tools.isdisjoint(tools.tool_names)
|
||||
|
||||
|
||||
def test_subagent_prompt_explains_grouped_skill_paths(tmp_path):
|
||||
def test_subagent_prompt_keeps_agent_paths_for_selected_project(tmp_path):
|
||||
agent_workspace = tmp_path / "agent"
|
||||
project = tmp_path / "project"
|
||||
global_skill = agent_workspace / "skills" / "global-custom" / "SKILL.md"
|
||||
@@ -100,15 +100,32 @@ def test_subagent_prompt_explains_grouped_skill_paths(tmp_path):
|
||||
|
||||
prompt = manager._build_subagent_prompt(workspace=project)
|
||||
|
||||
assert "one absolute root and relative SKILL.md paths" in prompt
|
||||
assert "one root and relative SKILL.md paths" in prompt
|
||||
assert "Join them when using `read_file`" in prompt
|
||||
assert f"Current project workspace: {project.resolve()}" in prompt
|
||||
assert str(project.resolve()) not in prompt
|
||||
assert f"Nanobot's agent workspace: {agent_workspace.resolve()}" in prompt
|
||||
assert f"History log: {agent_workspace.resolve() / 'memory' / 'history.jsonl'}" in prompt
|
||||
assert "global-custom" in prompt
|
||||
assert "project-custom" not in prompt
|
||||
|
||||
|
||||
def test_subagent_prompt_uses_relative_paths_in_agent_workspace(tmp_path):
|
||||
skill = tmp_path / "skills" / "custom" / "SKILL.md"
|
||||
skill.parent.mkdir(parents=True)
|
||||
skill.write_text("---\ndescription: custom skill\n---\nCustom", encoding="utf-8")
|
||||
manager = SubagentManager(
|
||||
workspace=tmp_path,
|
||||
bus=MessageBus(),
|
||||
max_tool_result_chars=16_000,
|
||||
)
|
||||
|
||||
prompt = manager._build_subagent_prompt()
|
||||
|
||||
assert str(tmp_path.resolve()) not in prompt
|
||||
assert "History log: memory/history.jsonl" in prompt
|
||||
assert "### Workspace skills (`skills`)" in prompt
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_subagent_keeps_project_runtime_scope_with_agent_owned_tools(tmp_path):
|
||||
agent_workspace = tmp_path / "agent"
|
||||
|
||||
Reference in New Issue
Block a user