# TUI — Actor Thought Blocks

Actor thought blocks display the reasoning traces produced by actors that
support extended thinking (e.g. Claude's extended thinking mode). Thought
blocks are rendered in the conversation stream with muted styling and can
be expanded or collapsed by the user.

Introduced in v3.7.0 (issue #1001). See also [`tui.md`](tui.md) for the
overall TUI architecture.

---

## Overview

When an actor emits a reasoning trace, the TUI wraps it in a
`ThoughtBlockWidget`. By default the widget shows at most 10 lines with a
truncation indicator; pressing `Space` expands it to show the full content.

```
▶ [Thinking — 3 more lines hidden]
  I need to consider the edge cases for the validation logic.
  First, let me check whether the input can be None...
  The schema requires a non-empty string, so...
  [Space to expand]
```

After expanding:

```
▼ [Thinking]
  I need to consider the edge cases for the validation logic.
  First, let me check whether the input can be None...
  The schema requires a non-empty string, so...
  I should also handle the case where the string is whitespace-only.
  The validator strips whitespace before checking length.
  ...
```

---

## ThoughtBlock Domain Model

**Module**: `cleveragents.domain.models.thought.thought_block`

`ThoughtBlock` is a plain Python dataclass that holds the content and
display state of a single reasoning trace.

### Fields

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `content` | `str` | — | Full text content of the thought |
| `max_lines` | `int` | `10` | Maximum lines shown when collapsed |
| `expanded` | `bool` | `False` | Whether the block is currently expanded |

### Methods

| Method | Returns | Description |
|--------|---------|-------------|
| `lines()` | `list[str]` | All content lines |
| `visible_lines()` | `list[str]` | Lines visible in the current state (up to `max_lines` when collapsed) |
| `is_truncated()` | `bool` | `True` when content is truncated in collapsed state |
| `hidden_line_count()` | `int` | Number of lines hidden when collapsed |
| `toggle()` | `None` | Toggle expanded/collapsed state |
| `expand()` | `None` | Expand to show full content |
| `collapse()` | `None` | Collapse to `max_lines` |

### Usage Example

```python
from cleveragents.domain.models.thought.thought_block import ThoughtBlock

block = ThoughtBlock(
    content="Line 1\nLine 2\nLine 3\n...\nLine 15",
    max_lines=10,
)

print(block.is_truncated())       # True (15 lines > 10)
print(block.hidden_line_count())  # 5
print(len(block.visible_lines())) # 10

block.toggle()
print(block.expanded)             # True
print(len(block.visible_lines())) # 15 (all lines)
```

---

## ThoughtBlockWidget

**Module**: `cleveragents.tui.widgets.thought_block`

`ThoughtBlockWidget` is a Textual `Static` subclass that renders a
`ThoughtBlock` domain model with muted styling.

### CSS Classes

| Class | Applied when |
|-------|-------------|
| `thought-block` | Always (base muted styling) |
| `thought-block--collapsed` | Block is collapsed |
| `thought-block--expanded` | Block is expanded |

### Indicators

| Indicator | Meaning |
|-----------|---------|
| `▶` | Block is collapsed; press `Space` to expand |
| `▼` | Block is expanded; press `Space` to collapse |

### Methods

| Method | Returns | Description |
|--------|---------|-------------|
| `toggle()` | `None` | Toggle expanded/collapsed state and re-render |
| `expand()` | `None` | Expand the block |
| `collapse()` | `None` | Collapse the block |

### Keyboard Binding

The `Space` key is bound to `toggle()` when the widget is focused within
the conversation stream.

### Usage Example

```python
from cleveragents.domain.models.thought.thought_block import ThoughtBlock
from cleveragents.tui.widgets.thought_block import ThoughtBlockWidget

block = ThoughtBlock(content="I need to think about this...\n" * 20)
widget = ThoughtBlockWidget(block)

# Programmatically expand
widget.expand()
```

---

## Integration with the Conversation Stream

The main TUI conversation widget creates a `ThoughtBlockWidget` whenever
an actor message contains a reasoning trace. Thought blocks appear inline
in the conversation, visually distinguished from regular message content
by the `thought-block` CSS class (rendered in a muted/dimmed colour).

---

## Related Documentation

- [TUI Reference](tui.md) — overall TUI architecture
- [Actor Runtime](actor_runtime.md) — actor execution model
- [Async Architecture](async_architecture.md) — how actor responses are streamed
