e2133529a0
- docs/api-reference.md: complete REST API endpoint reference (~60+ routes) - docs/android-app.md: Flutter companion app stack, architecture, feature status - docs/architecture.md: detailed file-by-file reference for all backend services and frontend components - docs/features.md: LLM pipeline internals (intent routing, tool loop, duplicate guards, image search, research pipeline), roadmap - docs/development.md: full migration chain (0001–0026) with naming and caveats - README.md: link to new api-reference and android-app docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
199 lines
12 KiB
Markdown
199 lines
12 KiB
Markdown
# Features
|
||
|
||
## Notes
|
||
|
||
Write in Markdown with a live-preview editor (Tiptap/ProseMirror). Headings, bold, italic, lists, code blocks, and task checklists render inline. A slash-command menu (`/`) inserts common blocks.
|
||
|
||
**Wikilinks** — Link notes with `[[Title]]` or `[[Title|Display Text]]` syntax. Clicking a wikilink navigates to (or auto-creates) the referenced note. The editor suggests existing note titles as candidate links while typing `[[`. Backlinks appear in the note viewer sidebar.
|
||
|
||
**Tags** — First-class `ARRAY[text]` column. Tag autocomplete in the editor sidebar suggests existing tags. Hierarchical tags (`project/webapp`) supported — filtering by `project` matches all `project/*` children. Tags are browsable via the knowledge graph.
|
||
|
||
**Version history** — Every body edit snapshots a version (up to 20 per note). Browse and restore from the editor's History panel. Diff view shows changes against the current body.
|
||
|
||
**AI writing assist** — Select a passage or work on the full document. Give an instruction ("make this more concise", "add examples"). The assistant streams a proposal; a diff view shows changes to accept or reject. Drafts persist across page loads.
|
||
|
||
**Link suggestions** — The editor detects note titles appearing as plain text in the body and suggests converting them to wikilinks.
|
||
|
||
## Tasks
|
||
|
||
Tasks are notes with `status IS NOT NULL`. They carry status (`todo` → `in_progress` → `done`), priority (`none`/`low`/`medium`/`high`), due date, milestone assignment, and a parent task (sub-tasks).
|
||
|
||
**Task work logs** — Append progress log entries to a task with optional duration. Time tracking is visible in the task editor sidebar.
|
||
|
||
**Sub-tasks** — Any task can have child tasks via `parent_id`. The task viewer shows sub-tasks inline.
|
||
|
||
**Convert freely** — Convert a note to a task (sets `status=todo`) or a task back to a note from the viewer toolbar.
|
||
|
||
## Projects and Milestones
|
||
|
||
**Projects** — Group related notes and tasks. Each project has a title, description, goal, status (`active`/`completed`/`archived`), and a colour.
|
||
|
||
**Milestones** — Ordered stages within a project. Tasks are assigned to milestones. Milestone completion percentage shown on the project page.
|
||
|
||
**Kanban view** — `/projects/:id` groups tasks by milestone in a kanban-style column layout with status-advance buttons directly on cards (→ advance, ✓ complete).
|
||
|
||
**Project Workspace** — `/workspace/:projectId` opens a three-panel environment (tasks / chat / notes) locked to a project. The AI assistant creates and updates content directly in the workspace; new notes auto-load in the editor and the task list refreshes automatically after tool calls.
|
||
|
||
## Knowledge Graph
|
||
|
||
`/graph` renders all notes, tasks, and tags as a D3 force-directed graph. Tag nodes cluster notes that share tags; invisible project hub nodes attract project members. Physics controls: repulsion, link distance, link strength, hub pull, gravity. Click any node to open a slide-in peek panel. Click a tag node to filter the notes list.
|
||
|
||
## AI Chat
|
||
|
||
Full conversation history with SSE streaming. Features:
|
||
- **RAG** — Semantically relevant notes (≥ 0.60 cosine similarity) auto-injected as context. Notes 0.45–0.60 shown in sidebar as "Suggested."
|
||
- **Attach notes** — Paperclip icon to include specific notes in context.
|
||
- **Project scope** — Restrict RAG to a single project's notes via the sidebar selector.
|
||
- **Tool calls** — The assistant can create/update notes, tasks, projects, milestones, search the web, check weather, read RSS, query calendar events, and more. Tool calls display inline with confirm/deny for creates.
|
||
- **Thinking mode** — Toggle extended reasoning for complex questions.
|
||
- **Abort** — Stop button cancels in-flight generation.
|
||
- **Message queue** — Messages sent while generation is in progress are queued and drained sequentially.
|
||
- **Save to note** — Save any assistant reply directly as a note.
|
||
- **Bulk delete** — Select and delete multiple conversations.
|
||
- **Retention** — Conversations auto-pruned after configurable days (default 90).
|
||
|
||
## Daily Briefing
|
||
|
||
`/briefing` is a scheduled, dialogue-based morning briefing. The assistant compiles tasks, calendar events, projects, weather forecast, and RSS digest at configurable times, then checks in throughout the day. You can reply interactively.
|
||
|
||
**Schedule** — Configurable slots: morning (default 4am compile), midday (8am check-in), evening (12pm check-in), night (4pm). Scheduler catches up missed slots on startup.
|
||
|
||
**Configuration** — Settings → Briefing: enable toggle, location geocoding, office days, time slot toggles, RSS feed management, push notification toggle.
|
||
|
||
**RSS feeds** — Add feed URLs with optional name and category. Feeds are fetched and cached; the briefing digest includes recent items. Category badges shown in the UI. Feeds can be manually refreshed.
|
||
|
||
**Weather** — Location-based forecast via Open-Meteo. Multiple locations supported (home, work, or any city name). Geocoding via Nominatim.
|
||
|
||
**Profile note** — The assistant maintains a profile note for each user that it updates based on briefing conversations, improving personalisation over time.
|
||
|
||
## Web Research
|
||
|
||
The assistant can search the web (SearXNG) and fetch pages, synthesising findings into notes. A lightweight `search_web` tool answers quick questions inline without saving. Requires `SEARXNG_URL` to be configured.
|
||
|
||
## CalDAV Calendar
|
||
|
||
Connect an external CalDAV server (Nextcloud, Radicale, etc.) and manage calendar events via natural language. Tools: `create_event`, `list_events`, `search_events`, `update_event`, `delete_event`. Activated when user configures CalDAV credentials in Settings → Integrations.
|
||
|
||
## Sharing and Collaboration
|
||
|
||
**Share** — Share any project or note/task with users or groups at `viewer`/`editor`/`admin` permission levels. Share button in the viewer/project toolbar opens a dialog.
|
||
|
||
**Groups** — Admins create platform-wide groups and assign users `member`/`owner` roles. Share a resource with a group in one action.
|
||
|
||
**Shared with me** — `/shared` lists all incoming shared projects and notes with permission badges.
|
||
|
||
**Notifications** — Bell icon in nav shows unread count (60s polling). Notifications generated for: project shared, note shared, added to group. Click navigates to the resource.
|
||
|
||
**Push notifications** — Web Push (VAPID) notifies when AI generation completes, even in another tab. Works over HTTPS only. Configurable per-user.
|
||
|
||
## Quick Capture
|
||
|
||
Quick capture from the Android app routes to the intent classifier. It creates notes, tasks, or projects based on content — using the user's configured model, not the hardcoded default.
|
||
|
||
## Data Export and Backup
|
||
|
||
- **Personal export** — Settings → Data: download all notes/tasks as a Markdown ZIP (with YAML frontmatter) or JSON array.
|
||
- **Admin backup** — Full application backup (version 2): includes projects, milestones, task logs, AI drafts, note versions, push subscriptions. ID remapping on restore for cross-instance migration.
|
||
|
||
## PWA
|
||
|
||
Installable as a desktop or mobile app. Service worker caches the shell. Push notifications handled by `public/sw.js` (suppresses duplicate notifications when the relevant tab is already focused). Works over HTTPS only in Firefox.
|
||
|
||
## Settings
|
||
|
||
Settings are tabbed:
|
||
|
||
| Tab | Contents |
|
||
|-----|----------|
|
||
| General | Assistant name, default model, model management (pull/delete) |
|
||
| Account | Email change, password change, session invalidation |
|
||
| Notifications | Push notification subscription, briefing push toggle |
|
||
| Integrations | CalDAV configuration, SearXNG status |
|
||
| Data | Personal export, backup/restore (admin) |
|
||
| Briefing | Enable, location, office days, slots, RSS feeds, weather |
|
||
| API Keys | Create/revoke API keys, Fable MCP download and install |
|
||
| Config (admin) | Base URL, SMTP, OIDC settings |
|
||
| Users (admin) | User list, invite links, registration toggle |
|
||
| Logs (admin) | Error, audit, and usage logs with search |
|
||
| Groups (admin) | Create/manage groups and membership |
|
||
|
||
## LLM Chat — Internal Pipeline
|
||
|
||
### Intent Routing
|
||
|
||
Before the main model runs, a lightweight intent classifier (`services/intent.py`) runs concurrently with `build_context()`. It makes a fast non-streaming call (~400ms) using a smaller dedicated model (`OLLAMA_INTENT_MODEL`, default `qwen2.5:7b`) to determine if the message requires a tool call.
|
||
|
||
**Skip heuristic** — Intent classification is skipped entirely for short messages (≤10 words) with no action/object keywords, saving 400–800ms on conversational replies.
|
||
|
||
**Prior-work fast-path** — Phrases like "research you did", "note you made", "using your research" skip the LLM call entirely and route to null (chat), preventing `search_web` from firing when the user references existing notes.
|
||
|
||
If a tool is detected, the intent's one-sentence `ack` field is streamed as the first chunk (becoming time-to-first-token), then the tool executes, then the main model generates a follow-up response with the tool result.
|
||
|
||
### Tool Loop
|
||
|
||
Multi-round tool loop (max 5 rounds). All tool implementations are in `services/tools.py` with `execute_tool()` as the dispatcher.
|
||
|
||
**Duplicate protection on create_note / create_task:**
|
||
1. Exact title match (case-insensitive) → hard block, redirect to `update_note`
|
||
2. Fuzzy title match (SequenceMatcher ≥ 82%; punctuation stripped before candidate search) → hard block
|
||
3. Semantic content similarity (`semantic_search_notes` threshold 0.90, body ≥ 200 chars) → soft block with `requires_confirmation: true`
|
||
|
||
**Project resolution** (`_resolve_project`): 4-step lookup — (1) exact DB match, (2) `query in title` substring, (3) `title in query` reverse substring, (4) SequenceMatcher ≥ 0.55.
|
||
|
||
### Model Status
|
||
|
||
Three states returned by `GET /api/chat/status`:
|
||
- `not_found` — model not installed; orange indicator in header
|
||
- `cold` — installed but not loaded in VRAM; yellow pulsing indicator (first request will be slow)
|
||
- `loaded` — hot in VRAM; green indicator
|
||
|
||
After `warmModel()` is called, a 5s polling loop runs for up to 60s until the indicator turns green.
|
||
|
||
### Context Window
|
||
|
||
`OLLAMA_NUM_CTX` (default 16384) controls the context window for all generation calls. Intent classification always uses `num_ctx=4096` to reduce VRAM pressure. History summarisation kicks in at 30 messages, keeps 8 recent, summary max 400 tokens.
|
||
|
||
### Image Search
|
||
|
||
`search_images` tool (SearXNG `categories=images`) fetches images server-side, stores on disk (SHA-256 dedup, 5 MB cap), and serves from `/api/images/<id>` — the user's browser never contacts the original image host. Requires `SEARXNG_URL`.
|
||
|
||
### Web Research Pipeline
|
||
|
||
Triggered by "research X and make a note" or the Research button in ChatView:
|
||
1. Intent model generates 5 focused sub-queries as a JSON array
|
||
2. All 5 SearXNG queries run in parallel (200ms stagger)
|
||
3. Up to 15 unique URLs fetched in parallel
|
||
4. Up to 12 sources passed to synthesis LLM (`num_ctx=16384`, `num_predict=8192`)
|
||
5. Note created with `tags=["research"]`
|
||
|
||
SearXNG tip: add the app server IP to `botdetection.ip_lists.pass_ip` in SearXNG `settings.yml` to bypass the rate limiter for backend requests.
|
||
|
||
## Roadmap
|
||
|
||
- Calendar/timeline view for tasks with due dates
|
||
- Email integration (read/send via IMAP/SMTP tools in chat)
|
||
- Session invalidation on user deletion
|
||
- Flutter push notifications (requires FCM/APNs — separate from web VAPID)
|
||
- Flutter milestone support in project view
|
||
|
||
## Keyboard Shortcuts
|
||
|
||
| Key | Action |
|
||
|-----|--------|
|
||
| `g` + `h` | Go to Home |
|
||
| `g` + `n` | Go to Notes |
|
||
| `g` + `t` | Go to Tasks |
|
||
| `g` + `p` | Go to Projects |
|
||
| `g` + `c` | Go to Chat |
|
||
| `g` (bare) | Go to Graph |
|
||
| `n` | New note |
|
||
| `t` | New task |
|
||
| `c` | Focus chat input |
|
||
| `e` | Edit current item |
|
||
| `/` | Search |
|
||
| `?` | Show shortcuts panel |
|
||
| `j` / `k` | Navigate list items |
|
||
| `Enter` | Open selected item |
|
||
| `Escape` | Close panel / blur / go home (progressive) |
|
||
| `Ctrl+S` | Save in editor |
|