Skip to content

Chat-first layout with formal-ai UX, all engines, and Links Notation storage (issue #15)#16

Merged
konard merged 6 commits into
mainfrom
issue-15-b719f182c4e9
Jun 11, 2026
Merged

Chat-first layout with formal-ai UX, all engines, and Links Notation storage (issue #15)#16
konard merged 6 commits into
mainfrom
issue-15-b719f182c4e9

Conversation

@konard

@konard konard commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #15. Selecting a chat engine + model only downloaded the model — there was no way to actually chat. Root cause: the model catalogue rendered as a full-width grid that filled the viewport and pushed the chat composer off-screen. For the reachat engine the shared column additionally squeezed the model selector narrow.

This PR makes the app chat-first with a persistent three-panel layout and brings the chat experience to parity with formal-ai: a conversations panel, Links Notation storage, export/import, and every react-chat-ui engine selectable.

Requirements

ID Requirement Status
R1 There must be a way to actually chat with a model, not just download it ✅ Chat-first three-panel layout; composer always visible
R2 Default to the formal-ai chat UI/UX FormalAiProvider default — avatars, copy, markdown, auto-growing composer
R3 All react-chat-ui engines selectable ✅ formal-ai, chatscope, deep-chat, react-chat-elements, assistant-ui, reachat
R4 Message/input features, conversations panel, browser storage, export/import ✅ Conversations sidebar; localStorage; .lino export/import
R5 Links Notation for all data storage model_in_browser_bundle .lino document
R6 E2E test guaranteeing send→response e2e/inference.spec.ts + e2e/chat-ux.spec.ts
R7 Fix the narrow model selector for reachat ✅ Selector in its own column + defensive CSS
R8 Deep case study in docs/case-studies/issue-15 README
R9 One PR, everything fully addressed ✅ This PR

Root cause

The pre-fix App.tsx rendered a single vertical column with the ModelSelector grid (~18 cards) at the top. The grid is taller than the viewport, so the chat surface below it scrolled out of view — selecting a model "did nothing" visible except download. Because chat and catalogue shared one column, reachat's horizontal flex layout also stole width from the selector.

The fix

  • Three-panel layout (App.tsx, index.css): a fixed 320px sidebar (brand, New chat, conversations list, engine picker, model catalogue, export/import) beside an always-visible .chat-main column (status bar + active provider + composer). The catalogue grid is confined to the sidebar and forced to one column.
  • Formal-AI default UX (FormalAiProvider): avatars, per-message copy, markdown + code, "Thinking…" indicator, auto-growing composer (Enter to send, Shift+Enter newline).
  • All 6 engines registered in types/chat.ts and switchable from the sidebar.
  • Links Notation storage (storage/links-notation.ts, storage/conversations.ts): conversations persisted to localStorage (mib_conversations_lino) as a model_in_browser_bundle; Export downloads model-in-browser-chats.lino; Import restores from a .lino bundle.
  • R7: the selector lives in its own column (structurally immune to the engine width) with min-width/width backstops on .reachat-container and .chat-main.

Verification

  • tsc --noEmit clean; vitest 37/37 pass; vite build succeeds; scripts/check-file-size.mjs passes.
  • e2e/chat-ux.spec.ts — 6/6 pass: composer reachable beside the catalogue (R1), every engine selectable without narrowing the selector (R3/R7), conversation create/switch/delete, Links Notation persistence across reload, and .lino export/import round-trips.
  • e2e/inference.spec.ts — 6/6 pass: pins SmolLM2 135M Instruct (q8), auto-loads, sends real messages, and asserts streamed replies (R6).
After — default (formal-ai) chat-first layout After — reachat keeps the selector full-width
default layout reachat width

Case study

Full analysis (timeline, root cause, solution plans, library/online research, citations) in docs/case-studies/issue-15/README.md.

Closes #15

Adding .gitkeep for PR creation (default mode).
This file will be removed when the task is complete.

Issue: #15
@konard konard self-assigned this Jun 10, 2026
konard and others added 5 commits June 10, 2026 23:40
…stence

Add a dependency-free Links Notation parser/serializer and a conversation
data model that persists all chat data to localStorage as a portable .lino
bundle (mirroring formal-ai's storage format), with export/import support.
Includes 11 unit tests covering round-trips, escaping and forgiving imports.
…es, and Links Notation storage (issue #15)

- Replace the catalogue-first single column (which pushed chat off-screen)
  with a three-panel shell: fixed sidebar (brand, conversations, engine
  picker, model catalogue, export/import) beside an always-visible chat column.
- Add FormalAiProvider as the default chat engine, mirroring formal-ai UX.
- Wire all six chat engines from react-chat-ui (formal-ai, chatscope,
  deep-chat, react-chat-elements, assistant-ui, reachat) as selectable.
- Persist conversations to localStorage as a Links Notation (.lino) bundle
  with sidebar export/import.
- Fix the reachat narrow-selector bug structurally (selector in its own
  column) plus defensive min-width/width CSS.
@konard konard changed the title [WIP] Selecting chat and the model does nothing except from downloading model Chat-first layout with formal-ai UX, all engines, and Links Notation storage (issue #15) Jun 11, 2026
@konard konard marked this pull request as ready for review June 11, 2026 00:19
@konard

konard commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Working session summary

Everything is complete. Here's the final summary.

Issue #15 — Done ✅

The bug: Selecting a chat engine + model only downloaded the model — there was no way to actually chat. Root cause was purely layout: the model catalogue rendered as a full-width grid that filled the viewport and pushed the chat composer off-screen. For reachat, the shared column also squeezed the model selector narrow.

The fix (PR #16, now marked ready):

Req What was done
R1 Chat-first three-panel layout — fixed 320px sidebar (brand, conversations, engine picker, catalogue, export/import) beside an always-visible chat column
R2 FormalAiProvider is the default engine — avatars, per-message copy, markdown, "Thinking…", auto-growing composer (Enter / Shift+Enter), mirroring formal-ai
R3 All 6 react-chat-ui engines selectable: formal-ai, chatscope, deep-chat, react-chat-elements, assistant-ui, reachat
R4 Conversations panel; localStorage persistence; .lino export/import
R5 Links Notation storage (model_in_browser_bundle document)
R6 E2E guarantee: inference.spec.ts (real send→streamed reply) + chat-ux.spec.ts (shell/engines/storage)
R7 Selector isolated in its own column + defensive min-width/width CSS
R8 Deep case study at docs/case-studies/issue-15/README.md
R9 All in this single PR

Verification (all green):

  • tsc --noEmit clean · vitest 37/37 · vite build succeeds · file-size check passes
  • chat-ux.spec.ts 6/6 · inference.spec.ts 6/6
  • CI on the final commit (7b42339): CI/CD Pipeline ✅, Build & Deploy ✅, E2E Tests ✅

Housekeeping: changelog fragment added (bump: minor), .gitkeep placeholder removed, main merged (already up to date), working tree clean, all work pushed to issue-15-b719f182c4e9.

PR: #16


This summary was automatically extracted from the AI working session output.

@konard

konard commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Solution Draft Log

This log file contains the complete execution trace of the AI solution draft process.

💰 Cost: $14.742046

📊 Context and tokens usage:

Claude Opus 4.8: (4 sub-sessions)

  1. 112.6K / 1M (11%) input tokens, 23.8K / 128K (19%) output tokens
  2. 112.2K / 1M (11%) input tokens, 41.1K / 128K (32%) output tokens
  3. 116.6K / 1M (12%) input tokens, 27.6K / 128K (22%) output tokens
  4. 70.6K / 1M (7%) input tokens, 18.3K / 128K (14%) output tokens

Total: (52.9K new + 525.5K cache writes + 14.1M cache reads) input tokens, 148.2K output tokens, $14.304322 cost

Claude Haiku 4.5:

  • 150.7K / 200K (75%) input tokens, 16.5K / 64K (26%) output tokens

Total: (38.5K new + 112.2K cache writes + 1.8M cache reads) input tokens, 16.5K output tokens, $0.437724 cost

🤖 Models used:

  • Tool: Anthropic Claude Code
  • Requested: opus
  • Main model: Claude Opus 4.8 (claude-opus-4-8)
  • Additional models:
    • Claude Haiku 4.5 (claude-haiku-4-5-20251001)

📎 Log file uploaded as Gist (8064KB)


Now working session is ended, feel free to review and add any feedback on the solution draft.

@konard konard merged commit 657a1ba into main Jun 11, 2026
11 checks passed
@konard

konard commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

🎉 Auto-merged

This pull request has been automatically merged by hive-mind.

  • All CI checks have passed

Auto-merged by hive-mind with --auto-merge flag

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Selecting chat and the model does nothing except from downloading model

1 participant