AI conversation history

mandatory

Sidebar of past AI conversations: date-grouped (Today / Yesterday / Last 7 days / Older), search (literal + semantic), pin/archive/delete, auto-titulation, cross-device sync. Standard pattern in ChatGPT/Claude/ Gemini desktop apps.

Spec — AI conversation history

Companion: memory-drawer.kmd (#117) — sibling persistence surface. Cascadedelete contract per [`identitydataretention.kmd`](....policies/identitydata-retention.kmd) R5.

Princípios

  1. *ate-grouped natural*— Today / Yesterday / Last 7 days / Older.
  2. *earch dual mode*— literal + semantic (via services/ai/memory ou rag).
  3. *ctions standard*— pin / archive / delete / rename / export.
  4. *utotitulation*— AIgenerated title from first messages; user can override.
  5. *ulti-tenant scope*— sidebar shows only current workspace conversations.

R1 — Anatomia

┌────────────────────────────────────┐
│ [🔍 Search]               [+ New]  │
├────────────────────────────────────┤
│ Pinned                             │
│ ⭐ Stack architecture (...)        │
├────────────────────────────────────┤
│ Today                              │
│ • Kortex deploy review (12:30)    │
│ • Quick math question (10:15)     │
├────────────────────────────────────┤
│ Yesterday                          │
│ • Spec review session (...)       │
├────────────────────────────────────┤
│ Last 7 days                        │
│ • ...                              │
├────────────────────────────────────┤
│ Older                              │
│ • ...                              │
└────────────────────────────────────┘

Slots:

Slot Content
Search bar live filter; semantic toggle
New button start new conversation
Groups Pinned / Today / Yesterday / Last 7 days / Older (collapsible)
Item title + relative timestamp + last assistant snippet (optional)

Item context menu: pin / archive / delete / rename / export markdown.

R2 — Auto-titulation

When conversation has ≥ 2 messages, gateway emits auto-title via small/fast model:

gateway.complete({
  prompt: "Title this conversation in <= 6 words: ${first_user_msg} | ${first_assistant_msg}",
  model: "haiku-fast",  // cheap fast model
})

User can override (longpress → rename). Override persisted; regeneration NOT auto unless user explicitly requests.

R3 — Search modes

Mode Trigger
Literal Default; substring match on title + message content
Semantic Toggle button; query services/ai/memory embedding similarity

Search debounce: 250ms.

Semantic results ranked by similarity; show score badge optional.

R4 — Pin / archive / delete

  • *in* max 5 pinned per workspace; sticky top group.
  • *rchive* removes from main list; available in "Archived" filter.
  • *elete* softdelete with 24h grace (per `identitydataretention.kmd` R5); during grace, "Undo" toast visible; after grace, harddelete cascade (messages + memory items referenced + uploads).

R5 — Export

Export as markdown bundle:

# Conversation: Stack architecture review
- Created: 2026-05-14 09:00
- Last activity: 2026-05-14 12:30
- Messages: 24

## Messages

### User · 09:00
...

### Assistant · 09:01
...

Download .md or share via Hub (private/public).

R6 — Sync cross-device

Backed by Koder ID session; conversation list syncs across devices via:

  • Conversation index table (kdb-kv) scoped per (koder_user_id, workspace_id).
  • Realtime updates via WebSocket from `servicesaichatadapter`.
  • Conflict resolution: lastwritewins per item field; new conversation always wins (no merge).

R7 — Surface bindings

Surface API
Flutter KoderConversationList({onSelect, onArchive, onDelete, onPin, onRename}) em koder_kit/lib/src/ai/conversation_list.dart
Web <koder-conversation-list>
Compose/SwiftUI futuro
CLI / TUI koder conv list + koder conv switch <id> + koder conv pin/archive/delete <id>

R8 — Acessibilidade

  • Sidebar: role="navigation" aria-label="Conversation history".
  • Groups: role="group" aria-labelledby="<date-header>".
  • Items: <button> with aria-label "Conversation: title, last activity time".
  • Search: role="searchbox".
  • Context menu: keyboard accessible.

R9 — i18n

Key en-US pt-BR
ai.history.group.pinned "Pinned" "Fixadas"
ai.history.group.today "Today" "Hoje"
ai.history.group.yesterday "Yesterday" "Ontem"
ai.history.group.last7days "Last 7 days" "Últimos 7 dias"
ai.history.group.older "Older" "Mais antigas"
ai.history.action.pin "Pin" "Fixar"
ai.history.action.archive "Archive" "Arquivar"
ai.history.action.delete "Delete" "Excluir"
ai.history.action.rename "Rename" "Renomear"
ai.history.action.export "Export markdown" "Exportar markdown"
ai.history.action.new "New conversation" "Nova conversa"
ai.history.search.placeholder "Search conversations..." "Buscar conversas..."
ai.history.search.semantic_toggle "Semantic search" "Busca semântica"
ai.history.delete.confirm "Delete this conversation?" "Excluir esta conversa?"
ai.history.delete.undo_toast "Conversation deleted · Undo" "Conversa excluída · Desfazer"

R10 — Multi-tenant

  • Conversation index scope per (koder_user_id, workspace_id).
  • Crossworkspace: each workspace has own sidebar; no crossworkspace search by default.
  • Shared workspace (multiuser): admincontrolled visibility — default own-only.

T-suite

  • *1*Mount: render groups with conversations populated.
  • *2*Date grouping correct: timestamps map to right group.
  • *3*Pin: max 5 enforced.
  • *4*Archive: removes from main; visible in archive filter.
  • *5*Delete + undo: tap delete → toast 24h undo; tap undo → restored.
  • *6*Harddelete after grace: advance clock 25h → conversation gone; messages cascadedeleted.
  • *7*Autotitle: after 2 messages → title autoset.
  • *8*Rename overrides: user renames → persisted; auto-title NOT triggered again.
  • *9*Search literal: type "deploy" → filters list.
  • *10*Search semantic: toggle → query embedding; results ranked.
  • *11*Sync cross-device: edit on device A → visible on device B after WebSocket roundtrip.
  • *12*Multi-tenant: workspace switch → list reloads with new scope.
  • *13*A11y: keyboard nav full; aria announce group transitions.
  • *1*Cross-tenant access: workspace B tries to load conversation A → 404.
  • Companion: memory-drawer.kmd (#117 — sibling persistence)
  • Backend: services/ai/chat-adapter/, services/ai/memory/
  • Policies: multi-tenant-by-default.kmd, identity-data-retention.kmd R5
  • Refs: ChatGPT sidebar, Claude conversations, Gemini sidebar

Source: ../home/koder/dev/koder/meta/docs/stack/specs/ai-ui/conversation-history.kmd