diff --git a/README.md b/README.md index 187826fe0..f6438915a 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,12 @@ embracing modern Python tooling. application services (session, plan, registry, event) - **Permissions screen** — TUI overlay for reviewing tool permission requests with unified, side-by-side, and context diff views; session-scoped allow/reject decisions +- **Inline permission questions** — `PermissionQuestionWidget` renders single-file + permission requests directly in the conversation stream; single-key shortcuts + (`a`/`A`/`r`/`R`) resolve without opening the full overlay +- **Shell danger detection** — TUI shell mode (`!` prefix) scans commands against a + configurable pattern registry before execution; warning overlay surfaces dangerous + patterns (CRITICAL/HIGH/MEDIUM/LOW) and lets the user abort or proceed - **Actor thought blocks** — expandable reasoning trace widgets rendered inline in the conversation stream with muted styling - **UKO runtime** — Universal Knowledge Ontology query interface, inference engine, and @@ -30,6 +36,9 @@ embracing modern Python tooling. PostgreSQL, MySQL, and DuckDB resources - **Estimation lifecycle** — `actor.default.estimation` config key wires an estimation actor into the Strategize-to-Estimate lifecycle hook +- **Plan workflow isolation** — `agents plan` commands detect and reject attempts to + mix legacy plan commands with v3 plan workflows in the same session, surfacing a + clear error with migration guidance - Fast Typer/Click-based interface with parity for help/version behavior - Behavior-driven coverage via Behave and Robot Framework - Nox automation for linting, typing, testing, docs, builds, and benchmarks diff --git a/docs/api/tui.md b/docs/api/tui.md index 7db1f0acc..e1b4d0672 100644 --- a/docs/api/tui.md +++ b/docs/api/tui.md @@ -269,6 +269,159 @@ from cleveragents.tui.screens import PermissionsScreen --- +## Shell Safety + +The TUI shell mode (`!` prefix) passes commands through a configurable +danger-detection layer before execution. A warning overlay is surfaced to +the user when a dangerous pattern is matched; the user can choose to proceed +or abort. + +**Module:** `cleveragents.tui.shell_safety` + +### `ShellDangerLevel` + +```python +from cleveragents.tui.shell_safety import ShellDangerLevel + +class ShellDangerLevel(IntEnum): + LOW = 1 # minor risk, generally recoverable + MEDIUM = 2 # moderate risk — data loss or security exposure possible + HIGH = 3 # significant, hard-to-reverse damage likely + CRITICAL = 4 # system destruction or fork bomb +``` + +Levels are ordered so numeric comparisons work naturally: +`level >= ShellDangerLevel.HIGH`. + +--- + +### `DangerousPattern` + +```python +from cleveragents.tui.shell_safety import DangerousPattern + +pattern = DangerousPattern( + name="rm_rf_root", + pattern=r"rm\s+(-\w*r\w*f|-\w*f\w*r)\s+/\s*$", + level=ShellDangerLevel.CRITICAL, + description="rm -rf / recursively deletes the entire filesystem root.", +) +``` + +A frozen dataclass describing a single dangerous shell pattern. + +| Field | Type | Description | +|-------|------|-------------| +| `name` | `str` | Unique identifier for the pattern | +| `pattern` | `str` | Regular expression matched against the command | +| `level` | `ShellDangerLevel` | Severity classification | +| `description` | `str` | Human-readable explanation shown in the warning overlay | + +--- + +### Built-in Patterns (`DEFAULT_PATTERNS`) + +The default pattern registry covers the following categories: + +| Name | Level | Description | +|------|-------|-------------| +| `rm_rf_root` | CRITICAL | `rm -rf /` — destroys filesystem root | +| `rm_rf_wildcard` | CRITICAL | `rm -rf /*` or similar wildcard paths | +| `fork_bomb` | CRITICAL | `:(){ :|:& };:` — exhausts process table | +| `dd_if_device` | HIGH | `dd if=` — can overwrite disk devices | +| `mkfs` | HIGH | Formats a filesystem, erasing all data | +| `shred_device` | HIGH | `shred` on a device or with `--remove` | +| `chmod_777` | MEDIUM | World-writable permissions | +| `sudo_rm` | MEDIUM | `sudo rm` — elevated-privilege deletion | +| `wget_pipe_sh` | MEDIUM | Remote code execution via `wget \| sh` | +| `curl_pipe_sh` | MEDIUM | Remote code execution via `curl \| sh` | +| `wget_pipe_bash` | MEDIUM | Remote code execution via `wget \| bash` | +| `curl_pipe_bash` | MEDIUM | Remote code execution via `curl \| bash` | +| `git_push_force` | LOW | `git push --force` — overwrites remote history | +| `chmod_recursive_permissive` | LOW | Recursive chmod with permissive modes | + +--- + +### `ShellSafetyService` + +```python +from cleveragents.tui.shell_safety import ShellSafetyService + +service = ShellSafetyService() +result = service.check_command("rm -rf /") +if not result.allowed: + print(result.warning.message) +``` + +Application service that wraps `DangerousPatternDetector` with a higher-level +API. + +```python +ShellSafetyService( + *, + detector: DangerousPatternDetector | None = None, + block_level: ShellDangerLevel = ShellDangerLevel.MEDIUM, + warn_callback: Callable[[DangerousCommandWarning], bool] | None = None, + extra_patterns: list[DangerousPattern] | None = None, +) +``` + +| Parameter | Description | +|-----------|-------------| +| `detector` | Custom detector; defaults to `DangerousPatternDetector()` with `DEFAULT_PATTERNS` | +| `block_level` | Minimum level that triggers automatic blocking when no `warn_callback` is provided (default: `MEDIUM`) | +| `warn_callback` | Optional `(warning) -> bool`; return `True` to allow, `False` to block | +| `extra_patterns` | Additional patterns registered on top of the defaults | + +**Methods:** + +| Method | Returns | Description | +|--------|---------|-------------| +| `check_command(command)` | `SafetyCheckResult` | Full safety check with warning and allow/block decision | +| `is_safe(command)` | `bool` | Convenience wrapper — `True` if command is allowed | + +**Properties:** + +| Property | Type | Description | +|----------|------|-------------| +| `detector` | `DangerousPatternDetector` | The underlying detector instance | +| `block_level` | `ShellDangerLevel` | The configured automatic-block threshold | + +--- + +### `SafetyCheckResult` + +```python +result = service.check_command("sudo rm -rf /var/log") +result.command # "sudo rm -rf /var/log" +result.allowed # False (MEDIUM >= block_level MEDIUM) +result.warning # DangerousCommandWarning(...) +``` + +| Attribute | Type | Description | +|-----------|------|-------------| +| `command` | `str` | The command that was checked | +| `warning` | `DangerousCommandWarning \| None` | Warning if a pattern matched, else `None` | +| `allowed` | `bool` | `True` if the command is permitted to proceed | + +--- + +### `DangerousPatternDetector` + +```python +from cleveragents.tui.shell_safety import DangerousPatternDetector + +detector = DangerousPatternDetector() +detector.add_pattern(my_pattern) +warning = detector.check_first("rm -rf /") +``` + +Low-level detector that scans a command string against all registered patterns +and returns the first (highest-severity) match as a `DangerousCommandWarning`, +or `None` if no pattern matches. + +--- + ## TUI State Persistence The TUI persists minimal state to `~/.config/cleveragents/tui-state.yaml`: