mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 15:37:55 +08:00
config: [agent] allow_paths static pre-allow
This commit is contained in:
@@ -26,6 +26,7 @@ def test_agent_section_defaults(tmp_path: Path) -> None:
|
||||
assert store.agent_config.parallel_tools is True
|
||||
assert store.agent_config.confirm_destructive is True
|
||||
assert store.agent_config.path_denylist == []
|
||||
assert store.agent_config.allow_paths == {}
|
||||
assert store.agent_config.max_context_tokens == 200_000
|
||||
assert store.plugins_config.enable == []
|
||||
assert store.plugins_config.disable == []
|
||||
@@ -162,6 +163,33 @@ tool_directives = ""
|
||||
)
|
||||
|
||||
|
||||
def test_agent_allow_paths_parse(tmp_path: Path) -> None:
|
||||
path = tmp_path / "c.toml"
|
||||
_ = path.write_text(
|
||||
"""
|
||||
[agent]
|
||||
allow_paths = { "/data/datasets" = "read", "/tmp/build" = "exec" }
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
store = load(path)
|
||||
assert store.agent_config.allow_paths == {"/data/datasets": "read", "/tmp/build": "exec"}
|
||||
|
||||
|
||||
def test_agent_allow_paths_invalid_mode_falls_back(tmp_path: Path) -> None:
|
||||
path = tmp_path / "c.toml"
|
||||
_ = path.write_text(
|
||||
"""
|
||||
[agent]
|
||||
allow_paths = { "/data" = "sudo" }
|
||||
""",
|
||||
encoding="utf-8",
|
||||
)
|
||||
store = load(path)
|
||||
# Invalid field value resets the whole [agent] section to defaults.
|
||||
assert store.agent_config.allow_paths == {}
|
||||
|
||||
|
||||
def test_agent_mcp_instructions_flag(tmp_path: Path) -> None:
|
||||
path = tmp_path / "c.toml"
|
||||
_ = path.write_text(
|
||||
|
||||
@@ -12,11 +12,13 @@ from plyngent.tools import (
|
||||
AccessDecision,
|
||||
AccessMode,
|
||||
SessionState,
|
||||
WorkspaceError,
|
||||
active_workspace_policy,
|
||||
get_directory_access_confirm_hook,
|
||||
grant_session_access,
|
||||
request_directory_access,
|
||||
resolve_path,
|
||||
set_config_access,
|
||||
set_directory_access_confirm_hook,
|
||||
set_path_denylist,
|
||||
)
|
||||
@@ -234,3 +236,28 @@ async def test_grant_cap(
|
||||
assert session.access_grants == {}
|
||||
finally:
|
||||
policy.config_allow.clear()
|
||||
|
||||
|
||||
def test_set_config_access_installs_and_skips(
|
||||
workspace: object,
|
||||
session: SessionState,
|
||||
tmp_path_factory: pytest.TempPathFactory,
|
||||
) -> None:
|
||||
del workspace, session
|
||||
outside = tmp_path_factory.mktemp("config-allow").resolve()
|
||||
target = outside / "data.txt"
|
||||
_ = target.write_text("x", encoding="utf-8")
|
||||
missing = outside / "missing"
|
||||
applied, skipped = set_config_access(
|
||||
{
|
||||
str(outside): "read",
|
||||
str(missing): "read",
|
||||
str(target): "sudo",
|
||||
}
|
||||
)
|
||||
assert applied == [outside]
|
||||
assert sorted(skipped) == sorted([str(missing), str(target)])
|
||||
assert active_workspace_policy().config_allow == {outside: AccessMode.READ}
|
||||
assert resolve_path(str(target), required=AccessMode.READ) == target
|
||||
with pytest.raises(WorkspaceError, match="escapes"):
|
||||
_ = resolve_path(str(target), required=AccessMode.WRITE)
|
||||
|
||||
Reference in New Issue
Block a user