mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-09 00:47:54 +08:00
core/agent: danger classification overrides YOLO tag in confirm pipeline
This commit is contained in:
@@ -392,14 +392,15 @@ class ToolRegistry:
|
|||||||
*,
|
*,
|
||||||
tags: ToolTag,
|
tags: ToolTag,
|
||||||
) -> str | None:
|
) -> str | None:
|
||||||
"""Soft-confirm gate driven by danger reason + tags + grants + YOLO.
|
"""Soft-confirm gate driven by danger reason + tags + grants.
|
||||||
|
|
||||||
Pipeline (soft gate only; hard denylists stay in tool handlers)::
|
Pipeline (soft gate only; hard denylists stay in tool handlers)::
|
||||||
|
|
||||||
no soft reason → run
|
no soft reason → run
|
||||||
YOLO mode and (tags & YOLO) → allow
|
|
||||||
(tags & TRUSTABLE) and grant exists → allow
|
(tags & TRUSTABLE) and grant exists → allow
|
||||||
else on_confirm; on approve + TRUSTABLE → store grant
|
else → on_confirm (decorator YOLO tag does not override
|
||||||
|
dangerous invocations — internal danger classification
|
||||||
|
always takes precedence)
|
||||||
"""
|
"""
|
||||||
if self._danger is None:
|
if self._danger is None:
|
||||||
return None
|
return None
|
||||||
@@ -408,11 +409,6 @@ class ToolRegistry:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
async with self._confirm_lock:
|
async with self._confirm_lock:
|
||||||
reason = self._danger(name, args)
|
|
||||||
if reason is None:
|
|
||||||
return None
|
|
||||||
if self._yolo and (tags & ToolTag.YOLO):
|
|
||||||
return None
|
|
||||||
if self._grant_allows(name, tags=tags):
|
if self._grant_allows(name, tags=tags):
|
||||||
return None
|
return None
|
||||||
return await self._prompt_soft_confirm(name, args, reason, tags=tags)
|
return await self._prompt_soft_confirm(name, args, reason, tags=tags)
|
||||||
|
|||||||
@@ -446,7 +446,8 @@ async def test_yolo_rebuilds_tool_registry(tmp_path: Path) -> None:
|
|||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
assert st.agent.tools is not None
|
assert st.agent.tools is not None
|
||||||
# Soft-confirm hooks stay installed; YOLO only auto-allows YOLO-tagged tools.
|
# Soft-confirm hooks stay installed; YOLO mode does not bypass
|
||||||
|
# dangerous invocations — internal danger classification takes precedence.
|
||||||
assert st.agent.tools.soft_confirm is True
|
assert st.agent.tools.soft_confirm is True
|
||||||
assert st.agent.tools.yolo is False
|
assert st.agent.tools.yolo is False
|
||||||
st.set_yolo("on")
|
st.set_yolo("on")
|
||||||
|
|||||||
@@ -8,11 +8,12 @@ from plyngent.tools.grants import clear_grants, has_grant, hydrate_grants, persi
|
|||||||
from plyngent.tools.view import MemoryViewStore, session_data_view
|
from plyngent.tools.view import MemoryViewStore, session_data_view
|
||||||
|
|
||||||
|
|
||||||
async def test_yolo_only_skips_yolo_tagged_tools() -> None:
|
async def test_danger_overrides_yolo_tag() -> None:
|
||||||
|
"""Decorator YOLO tag does not bypass confirm when danger flags the call."""
|
||||||
calls: list[str] = []
|
calls: list[str] = []
|
||||||
|
|
||||||
@tool(tags=ToolTag.LOCAL | ToolTag.YOLO, register=False)
|
@tool(tags=ToolTag.LOCAL | ToolTag.YOLO, register=False)
|
||||||
async def yolo_ok() -> str:
|
async def yolo_tool() -> str:
|
||||||
return "y"
|
return "y"
|
||||||
|
|
||||||
@tool(tags=ToolTag.LOCAL, register=False)
|
@tool(tags=ToolTag.LOCAL, register=False)
|
||||||
@@ -27,15 +28,15 @@ async def test_yolo_only_skips_yolo_tagged_tools() -> None:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
reg = ToolRegistry(
|
reg = ToolRegistry(
|
||||||
[yolo_ok, no_yolo],
|
[yolo_tool, no_yolo],
|
||||||
danger=danger,
|
danger=danger,
|
||||||
on_confirm=confirm,
|
on_confirm=confirm,
|
||||||
yolo=True,
|
yolo=True,
|
||||||
)
|
)
|
||||||
assert await reg.execute("yolo_ok", "{}") == "y"
|
assert await reg.execute("yolo_tool", "{}") == "y"
|
||||||
assert calls == []
|
assert calls == ["yolo_tool"]
|
||||||
assert await reg.execute("no_yolo", "{}") == "n"
|
assert await reg.execute("no_yolo", "{}") == "n"
|
||||||
assert calls == ["no_yolo"]
|
assert calls == ["yolo_tool", "no_yolo"]
|
||||||
|
|
||||||
|
|
||||||
async def test_trustable_grant_once() -> None:
|
async def test_trustable_grant_once() -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user