Commit Graph

10 Commits

Author SHA1 Message Date
bvandeusen 38b1ac933e Add settings page, model management, and chat UX improvements
- Settings infrastructure: key-value settings table, GET/PUT API, Pinia store
- Configurable assistant name (default "Fable") in settings and LLM system prompt
- Model catalog with 18 models in 3 categories (General Purpose, Coding,
  Uncensored / Creative Writing) with download/select/remove functionality
- Move Ollama status indicator from chat views to global nav bar
- Chat bubble layout: user messages right-aligned, assistant left-aligned
- Floating dark input bar with auto-focus and circular send button
- Fix HTML entity rendering (' apostrophe issue in marked/DOMPurify pipeline)
- Fix new chat button navigation (fetchConversation before router.push)
- Recent chats section on home page with "New Chat" button
- Update summary.md with Phase 4.5 changes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 21:32:02 -05:00
bvandeusen 834fd80640 Add Ollama health check status indicator to chat views
Adds visibility into whether Ollama is reachable and the configured model
is ready before allowing chat. Prevents silent failures when the model is
still downloading or Ollama is unavailable.

- Backend: GET /api/chat/status endpoint checks Ollama /api/tags (5s timeout)
  Returns ollama availability + model readiness + default model name
- Frontend: OllamaStatus type, chat store polling (30s interval)
- ChatView: status dot + label in header (green/yellow/red), disabled send
- ChatPanel: compact status indicator in panel header, disabled send
- summary.md: updated with new endpoint, store changes, and component descriptions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:33:42 -05:00
bvandeusen e0e1294627 Add non-blocking operations design principle to summary
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:21:18 -05:00
bvandeusen f4c7deba66 Run model pull as background task to avoid startup timeout
ensure_model() can take minutes to pull a multi-GB model, which
exceeds Hypercorn's startup timeout. Now fires as an asyncio
background task so the app starts immediately.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:16:54 -05:00
bvandeusen 8a0b4d77f8 Remove alembic stamp --purge from Dockerfile CMD
Stop wiping Alembic version tracking on every restart. Now
`alembic upgrade head` runs only pending migrations, as intended.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 19:07:31 -05:00
bvandeusen b761db4c44 Fix migrations 0004 and 0005 to be fully idempotent
The Dockerfile runs `alembic stamp --purge base && alembic upgrade head`
on every restart, so all migrations re-run against an existing database.
Migration 0004 used `op.add_column()` which fails on re-run with
"column already exists". Migration 0005 used `op.create_table()` which
would fail similarly.

Both now use raw SQL with idempotency guards:
- 0004: `DO $$ BEGIN ALTER TABLE ADD COLUMN ... EXCEPTION WHEN
  duplicate_column` + `IF EXISTS` check before touching the tasks table
- 0005: `CREATE TABLE IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 18:57:12 -05:00
bvandeusen d2b8ab8fe8 Add LLM chat integration with streaming responses via Ollama
Phase 4: Full chat system with SSE streaming, note-aware context, and
conversation persistence.

Backend:
- Migration 0005: conversations + messages tables with FKs and indexes
- Conversation/Message SQLAlchemy models with relationships
- LLM service: ensure_model (auto-pull on startup), stream_chat (NDJSON),
  generate_completion, fetch_url_content (HTML stripping), build_context
  (keyword extraction, related note search, URL content injection)
- Chat service: conversation CRUD, save_response_as_note,
  summarize_conversation_as_note
- Chat routes blueprint: 9 endpoints including SSE streaming for messages,
  save/summarize as note, Ollama model listing
- Auto-pull llama3.1 model on app startup (non-blocking)

Frontend:
- apiStreamPost: SSE client using fetch + ReadableStream
- Chat Pinia store with streaming state management
- ChatView: dedicated /chat page with conversation sidebar + message thread
- ChatPanel: slide-out panel with contextNoteId from current route
- ChatMessage: markdown-rendered message bubble with "Save as Note" action
- Updated AppHeader with Chat nav link + panel toggle button
- Updated App.vue to mount ChatPanel with route-derived context
- Added /chat and /chat/:id routes

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 18:45:22 -05:00
bvandeusen 807cde30be Merge tasks into notes: a task is just a note with task attributes
A task is now a note with status/priority/due_date columns set (status IS NOT NULL).
This eliminates the separate tasks table, companion note system, cascade deletes,
bidirectional title sync, and _skip_cascade flags.

Migration (0004):
- Add status, priority, due_date columns to notes table
- Migrate task data from companion notes and orphan tasks
- Drop tasks table and old enum types

Backend:
- models/note.py: Add TaskStatus/TaskPriority enums, task columns, is_task property
- models/task.py: Deleted (merged into note.py)
- models/__init__.py: Re-export enums from note.py, remove Task import
- services/notes.py: Remove companion/cascade logic, add is_task filter,
  convert_note_to_task, convert_task_to_note, simplified backlinks
- services/tasks.py: Rewritten as thin wrappers around notes service
- routes/notes.py: Add is_task filter (default false), task fields in CRUD,
  convert-to-note endpoint
- routes/tasks.py: description→body (with fallback), remove note_id filter

Frontend:
- types/note.ts: Add TaskStatus, TaskPriority, task fields to Note interface
- types/task.ts: Task is now a re-export alias for Note
- stores/notes.ts: Simplify convertToTask, add convertToNote
- stores/tasks.ts: description→body in createTask/updateTask
- TaskEditorView: description→body, remove companion note UI
- TaskViewerView: description→body, remove companion note link, add Convert to Note
- NoteViewerView: Remove companion task UI, simplify convert-to-task
- TaskCard: description→body, non-null assertions for status/priority

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 17:56:12 -05:00
bvandeusen e2338918b0 Add idempotent Alembic migrations, auto-migrate on startup, update summary
Rewrite migrations to raw SQL with IF NOT EXISTS/EXCEPTION guards for
full idempotency. Add notes table migration (0001), fix migration chain,
and run alembic upgrade head in Dockerfile CMD on container start.
Update summary.md with Phase 3.5 changes and Alembic instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:55:40 -05:00
bvandeusen 22a3a3c1d1 Initial commit: note-taking/task-tracking app with LLM integration scaffold
Vue 3 + TypeScript frontend with Pinia stores, markdown rendering (marked + DOMPurify),
wikilink/tag linkification, and autocomplete. Quart async backend with SQLAlchemy 2.0,
PostgreSQL ARRAY columns, task-note companion linking, backlinks, and note-to-task
conversion. Docker Compose setup with PostgreSQL 16 and Ollama.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-09 23:35:44 -05:00