mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-31 08:13:11 +03:00
fix(agent): honor selected project workspace
This commit is contained in:
@@ -112,6 +112,14 @@ class ContextBuilder:
|
||||
|
||||
parts.append(render_template("agent/tool_contract.md"))
|
||||
|
||||
project_path = root.expanduser().resolve()
|
||||
if project_path != self.workspace.expanduser().resolve():
|
||||
parts.append(
|
||||
"# Current Project\n\n"
|
||||
f"Working directory: {project_path}\n"
|
||||
"Use it as the default root for project files and relative tool paths."
|
||||
)
|
||||
|
||||
if include_memory:
|
||||
memory = self.memory.read_memory()
|
||||
if memory and not self._is_template_content(memory, "memory/MEMORY.md"):
|
||||
|
||||
@@ -49,6 +49,29 @@ def test_system_prompt_stays_stable_when_clock_changes(tmp_path, monkeypatch) ->
|
||||
assert prompt1 == prompt2
|
||||
|
||||
|
||||
def test_selected_project_path_follows_shared_cache_prefix(tmp_path) -> None:
|
||||
"""Project paths must not invalidate the stable identity and tool contract prefix."""
|
||||
agent_home = tmp_path / "agent-home"
|
||||
project_a = tmp_path / "project-a"
|
||||
project_b = tmp_path / "project-b"
|
||||
agent_home.mkdir()
|
||||
project_a.mkdir()
|
||||
project_b.mkdir()
|
||||
builder = ContextBuilder(agent_home)
|
||||
|
||||
prompt_a = builder.build_system_prompt(workspace=project_a)
|
||||
prompt_b = builder.build_system_prompt(workspace=project_b)
|
||||
marker = "# Current Project"
|
||||
prefix_a = prompt_a[: prompt_a.index(marker)]
|
||||
prefix_b = prompt_b[: prompt_b.index(marker)]
|
||||
|
||||
assert prefix_a == prefix_b
|
||||
assert "# Tool Usage Notes" in prefix_a
|
||||
assert str(project_a.resolve()) not in prefix_a
|
||||
assert str(project_b.resolve()) not in prefix_b
|
||||
assert prompt_a == builder.build_system_prompt(workspace=project_a)
|
||||
|
||||
|
||||
def test_system_prompt_reflects_current_dream_memory_contract(tmp_path) -> None:
|
||||
workspace = _make_workspace(tmp_path)
|
||||
builder = ContextBuilder(workspace)
|
||||
|
||||
@@ -8,6 +8,7 @@ from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from nanobot.agent.context import ContextBuilder
|
||||
from nanobot.agent.tools.cli_apps import CliAppsTool
|
||||
from nanobot.agent.tools.context import RequestContext, ToolContext, request_context
|
||||
from nanobot.agent.tools.filesystem import ReadFileTool, WriteFileTool
|
||||
@@ -21,6 +22,7 @@ from nanobot.config.schema import ImageGenerationToolConfig, ProviderConfig, Too
|
||||
from nanobot.security.workspace_access import (
|
||||
WORKSPACE_SCOPE_METADATA_KEY,
|
||||
WorkspaceScopeError,
|
||||
WorkspaceScopeResolver,
|
||||
bind_workspace_scope,
|
||||
default_workspace_scope,
|
||||
reset_workspace_scope,
|
||||
@@ -101,6 +103,34 @@ def test_workspace_scope_accepts_home_relative_project_path(
|
||||
assert scope.metadata()["project_path"] == str(project.resolve())
|
||||
|
||||
|
||||
@pytest.mark.parametrize("access_mode", ["restricted", "full"])
|
||||
def test_selected_websocket_project_is_visible_to_the_model(
|
||||
tmp_path: Path,
|
||||
access_mode: str,
|
||||
) -> None:
|
||||
agent_home = tmp_path / "agent-home"
|
||||
project = tmp_path / "project"
|
||||
agent_home.mkdir()
|
||||
project.mkdir()
|
||||
resolver = WorkspaceScopeResolver(agent_home, default_restrict_to_workspace=False)
|
||||
|
||||
scope = resolver.for_turn(
|
||||
channel="websocket",
|
||||
message_metadata={
|
||||
WORKSPACE_SCOPE_METADATA_KEY: {
|
||||
"project_path": str(project),
|
||||
"access_mode": access_mode,
|
||||
}
|
||||
},
|
||||
session_metadata=None,
|
||||
)
|
||||
prompt = ContextBuilder(agent_home).build_system_prompt(workspace=scope.project_path)
|
||||
|
||||
assert prompt.index("# Tool Usage Notes") < prompt.index("# Current Project")
|
||||
assert f"Working directory: {project.resolve()}" in prompt
|
||||
assert "Use it as the default root for project files" in prompt
|
||||
|
||||
|
||||
def test_workspace_scope_metadata_falls_back_for_stale_session(tmp_path: Path) -> None:
|
||||
scope = workspace_scope_from_metadata(
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user