docs(tui): document PermissionQuestionWidget and add CHANGELOG entry #2181

Merged
freemo merged 1 commits from docs/update-tui-permission-question-widget into master 2026-04-03 06:41:25 +00:00
2 changed files with 55 additions and 0 deletions
+7
View File
@@ -13,6 +13,13 @@ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
warning overlay before proceeding. Patterns cover destructive filesystem
operations, privilege escalation, network exfiltration, and more. (#1003)
- **TUI — Permission Question Widget**: A new inline `PermissionQuestionWidget`
renders permission requests directly in the conversation stream for single-file
operations. Users can allow/reject with single-key shortcuts (`a`/`A`/`r`/`R`),
navigate with arrow keys, confirm with `Enter`, or press `v` to open the full
`PermissionsScreen` with diff view. `PermissionDecisionEvent` is emitted on
resolution. (#997)
- **TUI — First-run experience with actor selection overlay**: On first launch
(no personas configured), a centred `ActorSelectionOverlay` widget guides the
user to select an actor from a curated list (`anthropic/claude-4-sonnet`,
+48
View File
@@ -203,6 +203,54 @@ from cleveragents.tui.widgets import ThoughtBlockWidget
- Muted styling distinguishes thought blocks from regular messages
- Backed by `ThoughtBlock` domain model with configurable `max_lines` (default: 10)
### `PermissionQuestionWidget`
Inline permission question widget rendered directly in the conversation stream
for single-file permission requests. For multi-file operations the full
`PermissionsScreen` is pushed instead.
```python
from cleveragents.tui.widgets import PermissionQuestionWidget
from cleveragents.domain.models.core.inline_permission_question import (
InlinePermissionQuestion,
PermissionDecision,
)
widget = PermissionQuestionWidget(question)
event = widget.handle_key("a") # returns PermissionDecisionEvent or None
```
| Method | Description |
|--------|-------------|
| `move_up()` | Move selection cursor up (wraps) |
| `move_down()` | Move selection cursor down (wraps) |
| `handle_key(key: str) → PermissionDecisionEvent \| None` | Process a key press; returns a decision event when resolved |
**Key bindings:**
| Key | Action |
|-----|--------|
| `a` | Allow once |
| `A` | Allow always (this session) |
| `r` | Reject once |
| `R` | Reject always (this session) |
| `↑` / `↓` | Navigate options |
| `Enter` | Confirm highlighted option |
| `v` | Open full `PermissionsScreen` with diff view |
**`PermissionDecisionEvent`** — emitted when the user makes a decision:
```python
@dataclass
class PermissionDecisionEvent:
question: InlinePermissionQuestion
decision: PermissionDecision
```
**`render_permission_question(question, selected_index=0, *, show_diff=False) → str`** — pure rendering helper (testable without Textual).
---
### `PermissionsScreen`
Full-screen overlay for tool permission requests.