Pular para o conteúdo

AI chat message bubble

ai-ui specs/ai-ui/chat-message-bubble.kmd

Baseline message bubble for any AI chat surface in Koder Stack: user vs assistant variants, mandatory AI disclaimer chip on assistant messages, copy/edit/regenerate/branch actions, multi-modal content hosting (text, code, image, citations, tool invocations).

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — AI chat message bubble

Baseline component consumido por todo produto AI Koder. Hosts streaming text (cross-link streaming-text.kmd), tool invocations (cross-link mcp-tool-invocation.kmd), code blocks, citations, e disclaimer (cross-link ai-disclaimer.kmd).

Princípios

  1. Two-role taxonomy — user vs assistant. Sem variantes "system" ou "tool" no bubble visual (tool calls são inline content do assistant bubble, não bubbles próprios).
  2. Disclaimer is non-negotiable — todo assistant bubble carrega disclaimer chip per #119. Sem exceção em produto distribuído.
  3. Composable content — bubble é container; renderers de text/code/image/citation/tool são plug-ins.
  4. Actions where the user expects them — toolbar inline (hover desktop / always-visible mobile) com Copy / Edit / Regenerate / Branch.

R1 — Anatomia

R1.1 — User bubble

                          ┌──────────────────────┐
                          │ "What's the weather?"│
                          └──────────────────────┘
                                        14:32 · ✎
  • Alignment: right (LTR) / left (RTL per i18n/contract.kmd).
  • Tint: primary-container (per themes/color-roles.kmd).
  • Shape: shape-corner-large exceto trailing-bottom corner (shape-corner-small) — tail.
  • Avatar: opcional (off by default; product configurável).
  • Footer chips: timestamp · edit pencil (R3.2).

R1.2 — Assistant bubble

[avatar] ┌──────────────────────────────────────────┐
         │ "It's 22°C in São Paulo right now."      │
         │                                          │
         │ [mcp-tool-card if any]                   │
         │ [code-block if any]                      │
         │ [citation[1]] inline                     │
         │                                          │
         │ — Sources                                │
         │ [1] weather.com/sp                       │
         └──────────────────────────────────────────┘
         🤖 Generated by AI — verify  ·  14:32 · ⎘ ✎ ↻ ⑂
  • Alignment: left (LTR) / right (RTL).
  • Tint: surface (per themes/color-roles.kmd).
  • Shape: shape-corner-large exceto leading-bottom corner.
  • Avatar: assistant icon (configurável: model logo OR product logo OR generic ✨).
  • Disclaimer chip: SEMPRE presente (cross-link ai-disclaimer.kmd per tier).
  • Footer chips: timestamp · Copy ⎘ · Edit ✎ · Regenerate ↻ · Branch ⑂.

R2 — Mandatory disclaimer chip

ai-disclaimer.kmd R1 define 3 tiers (label / label+modal / label+banner+confirmation). Bubble hosts o label form:

Risk tierChip placementCopy key
low (default)Footer chip; subtle (text-muted)ai.disclaimer.label.low
mediumFooter chip; emphasized (warning)ai.disclaimer.label.medium
highBanner ACIMA do bubble (não chip footer)ai.disclaimer.label.high

Chip clickable → expand modal explicativo (#119 R1 tier 2 behavior; tier 1 = chip-only).

Per feedback_kds_owner_curated_content: copy editorial não editável por IA autonomamente.

R3 — Actions

R3.1 — User actions

ActionBehavior
Edit ✎Re-opens composer pré-preenchido com prompt original; submit substitui esta mensagem + invalida cascata downstream (assistant responses subsequentes).

R3.2 — Assistant actions

ActionBehavior
Copy ⎘Copia content como markdown (preservando code blocks, citations footnotes per citations.kmd R4).
Edit ✎Permite override do assistant message (rare; admin/debug surfaces only — default OFF).
Regenerate ↻Re-invoke gateway com same context; nova resposta substitui esta.
Branch ⑂Forka conversa daqui; cria nova conversation history entry com same prefix (cross-link conversation-history.kmd #115).

Hover surface: actions reveal on desktop hover; mobile: actions always visible (touch).

R4 — States

StateVisual
streamingCursor visible (streaming-text.kmd R2); footer disabled exceto Stop button
completeFooter actions enabled; disclaimer rendered
errorRed border + error icon + "Retry" button (replaces Regenerate); error message in body
edited"✎ Edited" badge no footer + edit history accessible via long-press/right-click

R5 — Multi-modal content hosting

Bubble body é container que renderiza array de content items (mesma estrutura do MCP tools/call content). Renderers:

Content typeRendererSpec
textMarkdown incremental + citation inlinestreaming-text.kmd, citations.kmd
codeSyntax highlight + actionscode-block.kmd
imageKoderImage (tap-fullscreen)media/image.kmd
mcp_tool_callTool card collapsiblemcp-tool-invocation.kmd
citation_listSidebar/footer footnotescitations.kmd
kvgKoder Vector Graphics (declarative)kvg/ spec (existente)

Render order = array order from gateway response. Streaming: content items appear progressivamente.

R6 — Surface bindings

SurfaceAPI
FlutterKoderAIMessageBubble({required role, required content, onAction}) em koder_kit/lib/src/ai/ai_message_bubble.dart
Web<koder-ai-message-bubble role="..." content="..."> em koder_web_kit
Compose AndroidKoderAIMessageBubble em koder-design-compose (futuro)
SwiftUI iOSKoderAIMessageBubble em koder-design-swift (futuro)
CLI / TUITexto plain: prefix > user, < assistant; disclaimer linha separada

API consistent: role: "user" | "assistant", content: List<ContentItem>, state: streaming|complete|error, onAction: callback(action_id).

R7 — Acessibilidade

  • Bubble é <article role="region" aria-label="Message from {role}">.
  • Avatar tem aria-hidden="true" (role já anunciado).
  • Disclaimer chip lido por screen reader como part of bubble: aria-describedby.
  • Actions: keyboard-accessible via Tab; aria-label per action.
  • Streaming state: aria-live="polite" announces "Generating…" → silent during stream → "Done" at end.
  • Edited state: aria-label includes "edited".
  • Reduced-motion: no entrance animation.
  • Touch targets ≥48dp.

R8 — i18n

Keyen-USpt-BR
ai.bubble.role.user"You""Você"
ai.bubble.role.assistant"Assistant""Assistente"
ai.bubble.action.copy"Copy""Copiar"
ai.bubble.action.edit"Edit""Editar"
ai.bubble.action.regenerate"Regenerate""Gerar de novo"
ai.bubble.action.branch"Branch""Ramificar"
ai.bubble.action.retry"Retry""Tentar novamente"
ai.bubble.state.streaming"Generating…""Gerando…"
ai.bubble.state.edited"Edited""Editado"
ai.bubble.action.copy.confirm"Copied to clipboard""Copiado"

(Disclaimer copy lives em ai-disclaimer.kmd R7.)

R9 — Multi-tenant + persistência

Message stored per policies/multi-tenant-by-default.kmd:

  • Key: (koder_user_id, workspace_id, conversation_id, message_id).
  • Edit history mantém versions (linear); rollback via long-press menu.
  • Cross-tenant lookup 404 per multi-tenancy contract.
  • Delete: cascata per policies/identity-data-retention.kmd R5 (24h grace + cascade).

R10 — Per-preset variation

PresetBubble style
material3 / material_expressiveDefaults; shape-corner-large; spring entrance
material2shape-corner-medium
terminal_classicNo bubbles — > prompt / < response prefix; monospace
brutalistSharp corners; 2px border; no shadow
cyberpunk_neonGlow outline; gradient backdrop
glassmorphismBackdrop blur 20%; transparent tint
minimalist_monoMono font; horizontal divider entre roles em vez de bubbles

T-suite

  • T1 Mount user: render user bubble com text content; alignment right (LTR).
  • T2 Mount assistant: render assistant bubble com text + disclaimer chip visible.
  • T3 Multi-modal: render assistant com text + code-block + tool-call + citation; ordem preserved.
  • T4 Action Copy: tap copy → clipboard content includes citations as markdown footnotes.
  • T5 Action Regenerate: tap → bubble enters streaming state; new content replaces.
  • T6 Action Branch: tap → new conversation created with prefix up to this message.
  • T7 Action Edit (user): tap → composer pre-filled; submit invalidates downstream cascade.
  • T8 Error state: simulate gateway error → red border + Retry button visible.
  • T9 RTL: render em locale rtl-* → alignment flips.
  • T10 A11y: screen reader announces role + content + disclaimer + actions list.
  • T11 Disclaimer always present: render assistant bubble without disclaimer prop → spec validation FAILS (compile-time or runtime error).
  • N1 Cross-tenant access: try to load message from another workspace → 404.

Referências