Skip to content

AI thinking state

ai-ui specs/ai-ui/thinking-state.kmd

Collapsible "Thinking..." block for reasoning models (Claude extended thinking, DeepSeek R1, OpenAI o-family). Separates chain-of-thought from final response. Hosted by chat-message-bubble (#105) and agent-step-trace (#108).

When this spec applies

Primary triggers

All triggers

Specification body

Spec — AI thinking state

Hosted by chat-message-bubble.kmd e agent-step-trace.kmd. Streams via streaming-text.kmd (separate stream channel reasoning).

Princípios

  1. Provider abstraction — gateway expõe reasoning_content separated from content; SDK detecta provider.
  2. Collapsed by default — pra reduzir noise; user expande quando quer detalhes.
  3. Auto-close on stream end — opcional, configurable; default close.
  4. Preserve manual expand — user expandeu → não auto-close.

R1 — Anatomia

┌───────────────────────────────────────────┐
│ 💭 Thinking · 4.2s            [▼]         │  ← collapsed (default)
└───────────────────────────────────────────┘

┌───────────────────────────────────────────┐
│ 💭 Thinking · 4.2s · 234 words   [▲]      │  ← expanded
│ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━        │
│ "I need to find recent docs about         │
│ Koder Stack architecture. The user is    │
│ asking about the Foundation layer..."    │
│                                           │
│ [reasoning trace continues...]            │
└───────────────────────────────────────────┘

Slots:

SlotContent
Icon💭 (thinking) or ⚙ (running animated)
Label"Thinking..." (streaming) → "Thought for {duration}" (complete)
Durationlive timer during stream; final on complete
Word countwhen complete (optional)
Toggleexpand/collapse chevron
Bodyfull reasoning text (when expanded)

R2 — States

StateVisual
streaming"Thinking..." + breathing dot + live timer
complete"Thought for 4.2s" + chevron + word count
collapsedheader only
expandedheader + body

R3 — Provider abstraction

Gateway response includes optional reasoning_content:

{
  "content": [{"type": "text", "text": "..."}],
  "reasoning_content": "I need to think about this...",
  "reasoning_meta": {
    "model_supports": true,
    "duration_ms": 4200,
    "tokens": 234
  }
}

If reasoning_content is null/missing: do NOT render thinking block.

Provider support:

ProviderNative reasoning_content?
Anthropic (Claude extended thinking)Yes
OpenAI (o-family)Yes (different field, gateway translates)
DeepSeek (R1)Yes
Google (Gemini reasoning)Yes
Self-hosted Koder LLMOptional

Gateway translates provider-specific to canonical shape above.

R4 — Auto-close

On done event of reasoning stream:

  • If auto_close: true (default): collapse animated (smooth).
  • If user already expanded manually: preserve expanded state.

User preference: stored per (koder_user_id, workspace_id).

R5 — Multiple thinking blocks (accordion)

Agent runs with reasoning per step (cross-link #108):

[Step 1] ▼ Thinking · 2s
[Step 2] ▶ Thinking · 1.5s
[Step 3] ▼ Thinking · 3s

Independent collapse/expand state per block.

R6 — Surface bindings

SurfaceAPI
FlutterKoderThinkingBlock({required content, duration, autoClose}) em koder_kit/lib/src/ai/thinking_block.dart
Web<koder-thinking-block>
Compose/SwiftUIfuturo
CLI / TUIPlain: prefix [think] ... indented; toggle via key shortcut

R7 — Acessibilidade

  • Block: <details><summary> semantically (Web); equivalente Flutter.
  • Toggle: keyboard Enter/Space.
  • aria-live="polite" during streaming.
  • Reduced-motion: no smooth collapse; instant.

R8 — i18n

Keyen-USpt-BR
ai.thinking.streaming"Thinking...""Pensando..."
ai.thinking.complete"Thought for {duration}""Pensou por {duration}"
ai.thinking.words"{n} words""{n} palavras"

T-suite

  • T1 Mount streaming: response has reasoning_content streaming → block visible with "Thinking..." + breathing dot.
  • T2 Done: stream complete → label becomes "Thought for 4.2s"; collapse animated.
  • T3 No reasoning_content: response without field → block NOT rendered.
  • T4 Manual expand: user clicks → expand; subsequent done does NOT collapse.
  • T5 Multiple blocks (agent steps): each independent.
  • T6 Reduced-motion: collapse instant.
  • T7 Provider abstraction: OpenAI o-family + Claude responses both render correctly.

References