Coverage for /home/admin/Documents/AI/applications/lexigram-dev/lexigram/experimental/ai/lexigram-ai-guard/src/lexigram/ai/guard/input/length.py: 56%
18 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 07:19 +0800
1"""Input length guard.
3Rejects or warns on inputs that exceed a configured character or token
4budget. This prevents prompt stuffing attacks and controls API costs.
5"""
7from __future__ import annotations
9from typing import TYPE_CHECKING, Any
11from lexigram.ai.guard.input.base import AbstractInputGuard
12from lexigram.ai.guard.pipeline.result import GuardCheckResult
13from lexigram.contracts.ai.guards import GuardResultProtocol
14from lexigram.result import Ok, Result
16if TYPE_CHECKING:
17 from lexigram.contracts.ai.exceptions import GuardError
20class InputLengthGuard(AbstractInputGuard):
21 """GuardProtocol that enforces a maximum input length.
23 Length is measured in character count. For a rough token
24 estimate divide by 4 (GPT tokenizer average).
26 Args:
27 max_chars: Maximum allowed character count.
28 action: Action when the limit is exceeded — ``"block"`` (default)
29 or ``"warn"``.
31 Example::
33 guard = InputLengthGuard(max_chars=8000, action="block")
34 result = await guard.check(user_input)
35 if not result.passed:
36 return Err(InputTooLongError(len(user_input)))
37 """
39 def __init__(self, max_chars: int, action: str = "block") -> None:
40 """Initialise the length guard.
42 Args:
43 max_chars: Maximum allowed character count.
44 action: ``"block"`` or ``"warn"``.
45 """
46 super().__init__(action=action)
47 self._max_chars = max_chars
49 async def check(
50 self,
51 content: str,
52 *,
53 messages: list[Any] | None = None,
54 metadata: dict[str, Any] | None = None,
55 ) -> Result[GuardResultProtocol, GuardError]:
56 """Check whether content exceeds the configured length limit.
58 Args:
59 content: Input text to measure.
60 messages: Unused — present for protocol compatibility.
61 metadata: Optional metadata.
63 Returns:
64 PASS if within limit; BLOCK or WARN if exceeded.
65 """
66 length = len(content)
67 if length <= self._max_chars:
68 return Ok(GuardCheckResult.allow(self.name, char_count=length))
70 if self._action == "warn":
71 return Ok(
72 GuardCheckResult.warn(
73 self.name,
74 reason=f"Input length {length} chars exceeds soft limit {self._max_chars}",
75 char_count=length,
76 max_chars=self._max_chars,
77 )
78 )
80 return Ok(
81 GuardCheckResult.block(
82 self.name,
83 reason=f"Input length {length} chars exceeds maximum {self._max_chars}",
84 char_count=length,
85 max_chars=self._max_chars,
86 )
87 )
90__all__ = ["InputLengthGuard"]