feat(desktop): add persistent full chat conversations #99

Merged
lost-rob0t merged 14 commits from feature/conversation-full-chat into master 2026-08-12 17:32:25 +00:00
lost-rob0t commented 2026-08-12 17:23:19 +00:00 (Migrated from github.com)

Closes #85.

Summary

Adds the first durable native full-chat surface on top of the RuntimeHost/event boundary from #82/#83 and the canonical desktop shell from #84.

  • add Qt-neutral conversation/message records keyed by stable conversation + turn IDs
  • persist desktop conversations/messages through the existing DatabaseManager migration registry (migration v2), not a second database/config store
  • add durable history, rename, title derivation, and title/message search hooks
  • add a ConversationService that reduces provider-neutral runtime events into durable conversation state
  • append real AssistantDelta events incrementally into the existing message record/widget
  • represent current buffered ResponseText behavior honestly as one complete content update; no fake token streaming
  • add structured assistant failure, cancellation, and compact tool-placeholder states
  • make the canonical desktop window a PySide6 FullChatWindow
  • route submit/cancel exclusively through SubmitTurn / CancelTurn on QtRuntimeBridge
  • add Enter-to-submit and Shift+Enter newline behavior
  • add native Markdown rendering plus fenced code blocks with copy actions, without WebEngine
  • show runtime/provider status while preserving tray/restart/diagnostics/close-to-hide lifecycle from #84

Persistence

Uses the existing shared SQLite database:

  • desktop_conversations
  • desktop_messages
  • schema migration version 2

The migration is compatible with the existing lazy todo migration registration: DatabaseManager applies missing versions in sorted order even if v2 registered first.

Streaming contract

Two paths are deliberately distinct:

  1. AssistantStarted / AssistantDelta / AssistantComplete update one assistant message incrementally.
  2. Current RuntimeHost buffered ResponseText is rendered once as complete text. It is not animated into fake token chunks.

Real provider streaming remains #28.

UI architecture

FullChatWindow owns only Qt projection/interaction. It does not instantiate an LLM, AgentManager, Prolog engine, or tool runtime. Assistant execution remains behind RuntimeHost.

Message delta updates call set_message() on the one affected message widget rather than rebuilding the entire conversation widget tree. Switching conversations intentionally rebuilds the visible conversation.

Tests

Adds coverage for:

  • shared-database migration and migration ordering
  • conversation/message round-trip persistence
  • rename/history/message search
  • incremental assistant deltas and final text persistence
  • buffered-response non-streaming fallback
  • structured failures/cancellation/tool placeholders/provider state
  • RuntimeHost deterministic buffered backend integration
  • Enter / Shift+Enter / Stop behavior
  • fake streaming updating one existing message widget
  • Markdown fenced-code copy
  • failure rendering
  • history rename/search/reload

The user's local /home/unseen/Documents/Projects/ checkout is not mounted here, so GitHub Actions is the authoritative full Nix/repository test gate.

Closes #85. ## Summary Adds the first durable native full-chat surface on top of the RuntimeHost/event boundary from #82/#83 and the canonical desktop shell from #84. - add Qt-neutral conversation/message records keyed by stable conversation + turn IDs - persist desktop conversations/messages through the existing `DatabaseManager` migration registry (migration v2), not a second database/config store - add durable history, rename, title derivation, and title/message search hooks - add a `ConversationService` that reduces provider-neutral runtime events into durable conversation state - append real `AssistantDelta` events incrementally into the existing message record/widget - represent current buffered `ResponseText` behavior honestly as one complete content update; no fake token streaming - add structured assistant failure, cancellation, and compact tool-placeholder states - make the canonical desktop window a PySide6 `FullChatWindow` - route submit/cancel exclusively through `SubmitTurn` / `CancelTurn` on `QtRuntimeBridge` - add Enter-to-submit and Shift+Enter newline behavior - add native Markdown rendering plus fenced code blocks with copy actions, without WebEngine - show runtime/provider status while preserving tray/restart/diagnostics/close-to-hide lifecycle from #84 ## Persistence Uses the existing shared SQLite database: - `desktop_conversations` - `desktop_messages` - schema migration version `2` The migration is compatible with the existing lazy todo migration registration: `DatabaseManager` applies missing versions in sorted order even if v2 registered first. ## Streaming contract Two paths are deliberately distinct: 1. `AssistantStarted` / `AssistantDelta` / `AssistantComplete` update one assistant message incrementally. 2. Current RuntimeHost buffered `ResponseText` is rendered once as complete text. It is **not** animated into fake token chunks. Real provider streaming remains #28. ## UI architecture `FullChatWindow` owns only Qt projection/interaction. It does not instantiate an LLM, AgentManager, Prolog engine, or tool runtime. Assistant execution remains behind RuntimeHost. Message delta updates call `set_message()` on the one affected message widget rather than rebuilding the entire conversation widget tree. Switching conversations intentionally rebuilds the visible conversation. ## Tests Adds coverage for: - shared-database migration and migration ordering - conversation/message round-trip persistence - rename/history/message search - incremental assistant deltas and final text persistence - buffered-response non-streaming fallback - structured failures/cancellation/tool placeholders/provider state - RuntimeHost deterministic buffered backend integration - Enter / Shift+Enter / Stop behavior - fake streaming updating one existing message widget - Markdown fenced-code copy - failure rendering - history rename/search/reload The user's local `/home/unseen/Documents/Projects/` checkout is not mounted here, so GitHub Actions is the authoritative full Nix/repository test gate.
Sign in to join this conversation.
No description provided.