mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-23 00:41:40 +00:00
chore: ruff format for conduct guardrail
Fixes lint check on the upstream PR.
This commit is contained in:
parent
c4064125f5
commit
474d9a9b43
2 changed files with 13 additions and 30 deletions
|
|
@ -93,7 +93,7 @@ class GuardDecision:
|
|||
|
||||
|
||||
def _strip_prefix(text: str, prefix: str) -> str | None:
|
||||
remainder = text[len(prefix):].strip()
|
||||
remainder = text[len(prefix) :].strip()
|
||||
return remainder.lstrip(":—- ").strip() or None
|
||||
|
||||
|
||||
|
|
@ -102,7 +102,7 @@ def _extract_rule_id(text: str) -> str | None:
|
|||
idx = text.find(marker)
|
||||
if idx < 0:
|
||||
return None
|
||||
tail = text[idx + len(marker):]
|
||||
tail = text[idx + len(marker) :]
|
||||
end = tail.find("]")
|
||||
return tail[:end].strip() if end >= 0 else None
|
||||
|
||||
|
|
@ -145,9 +145,7 @@ class ConductGuardrail(CustomGuardrail):
|
|||
kwargs.setdefault("supported_event_hooks", list(self.get_supported_event_hooks()))
|
||||
super().__init__(**kwargs)
|
||||
|
||||
self._api_url = (
|
||||
api_base or os.environ.get("CONDUCT_API_URL", "https://api.conductai.ai")
|
||||
).rstrip("/")
|
||||
self._api_url = (api_base or os.environ.get("CONDUCT_API_URL", "https://api.conductai.ai")).rstrip("/")
|
||||
token = api_key or os.environ.get("CONDUCT_AGENT_TOKEN")
|
||||
if not token:
|
||||
raise ValueError(
|
||||
|
|
@ -232,9 +230,7 @@ class ConductGuardrail(CustomGuardrail):
|
|||
|
||||
if "error" in body:
|
||||
err = body["error"]
|
||||
verbose_proxy_logger.warning(
|
||||
"conduct_guard: eval error %s — applying %s", err, self._fail_mode
|
||||
)
|
||||
verbose_proxy_logger.warning("conduct_guard: eval error %s — applying %s", err, self._fail_mode)
|
||||
if self._fail_mode == "fail_closed":
|
||||
return GuardDecision(
|
||||
verdict="block",
|
||||
|
|
@ -249,9 +245,7 @@ class ConductGuardrail(CustomGuardrail):
|
|||
return GuardDecision.parse(item.get("text", ""))
|
||||
return GuardDecision(verdict="allow", raw="")
|
||||
except Exception as e:
|
||||
verbose_proxy_logger.warning(
|
||||
"conduct_guard: transport error %s — applying %s", e, self._fail_mode
|
||||
)
|
||||
verbose_proxy_logger.warning("conduct_guard: transport error %s — applying %s", e, self._fail_mode)
|
||||
if self._fail_mode == "fail_closed":
|
||||
return GuardDecision(
|
||||
verdict="block",
|
||||
|
|
@ -290,10 +284,7 @@ def _extract_prompt_text(data: dict[str, Any]) -> str | None:
|
|||
if isinstance(content, str):
|
||||
return content[:4000]
|
||||
if isinstance(content, list):
|
||||
parts = [
|
||||
p.get("text", "") for p in content
|
||||
if isinstance(p, dict) and p.get("type") == "text"
|
||||
]
|
||||
parts = [p.get("text", "") for p in content if isinstance(p, dict) and p.get("type") == "text"]
|
||||
return " ".join(parts)[:4000] or None
|
||||
return None
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ Mocked transport — no real network. Verifies the response-envelope
|
|||
parser, pre-call hook behavior (allow / block / approval), fail-mode
|
||||
handling, and session-ID resolution chain.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
|
|
@ -27,16 +28,12 @@ class TestGuardDecisionParse:
|
|||
assert GuardDecision.parse(raw).verdict == "allow"
|
||||
|
||||
def test_blocked_extracts_rule_id(self) -> None:
|
||||
d = GuardDecision.parse(
|
||||
"BLOCKED — command touches /etc/passwd [rule: no-etc-passwd]"
|
||||
)
|
||||
d = GuardDecision.parse("BLOCKED — command touches /etc/passwd [rule: no-etc-passwd]")
|
||||
assert d.verdict == "block"
|
||||
assert d.rule_id == "no-etc-passwd"
|
||||
|
||||
def test_pending_approval_treated_as_block(self) -> None:
|
||||
d = GuardDecision.parse(
|
||||
"PENDING approval — HITL required [rule: prod-deploy-gate]"
|
||||
)
|
||||
d = GuardDecision.parse("PENDING approval — HITL required [rule: prod-deploy-gate]")
|
||||
assert d.verdict == "approval"
|
||||
assert d.rule_id == "prod-deploy-gate"
|
||||
|
||||
|
|
@ -89,24 +86,18 @@ class TestPreCallHook:
|
|||
|
||||
async def test_pending_approval_also_raises(self) -> None:
|
||||
g = _guard()
|
||||
g._check = AsyncMock(
|
||||
return_value=GuardDecision(verdict="approval", raw="PENDING approval — review")
|
||||
)
|
||||
g._check = AsyncMock(return_value=GuardDecision(verdict="approval", raw="PENDING approval — review"))
|
||||
with pytest.raises(ConductGuardrailBlocked):
|
||||
await g.async_pre_call_hook(None, None, {}, "completion")
|
||||
|
||||
|
||||
class TestConfig:
|
||||
def test_missing_token_raises_at_construction(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
def test_missing_token_raises_at_construction(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delenv("CONDUCT_AGENT_TOKEN", raising=False)
|
||||
with pytest.raises(ValueError, match="agent token"):
|
||||
ConductGuardrail()
|
||||
|
||||
def test_config_api_key_wins_over_env(
|
||||
self, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
def test_config_api_key_wins_over_env(self, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv("CONDUCT_AGENT_TOKEN", "env-token")
|
||||
g = ConductGuardrail(api_key="config-token")
|
||||
assert g._agent_token == "config-token"
|
||||
|
|
@ -119,4 +110,5 @@ class TestConfig:
|
|||
if __name__ == "__main__":
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
raise SystemExit(subprocess.call([sys.executable, "-m", "pytest", __file__, "-v"]))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue