This repository has been archived on 2026-06-02. You can view files and clone it. You cannot open issues or pull requests or push a commit.
bvandeusen bdaa5210f0 feat(voice): dynamic silence threshold
The previous -40 dBFS static threshold sat right on top of typical
phone mic ambient, so silence detection rarely fired and the user
always had to tap stop manually.

Silence threshold is now dynamic: track the session peak dBFS and
treat "silent" as 15 dB below peak. Auto-calibrates per mic and
environment rather than assuming a fixed ambient level.

- Grace period (1500 ms) at start so the user has time to begin
  speaking before checks arm.
- Static -35 dB fallback until the peak clears -20 dB so a dead-
  silent session doesn't spin forever.
- Silence duration bumped 1500 → 2000 ms for breathing room.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 00:28:04 -04:00
2026-02-28 21:28:53 -05:00

Fabled — Android App

Native Android client for FabledAssistant, a self-hosted AI second-brain and productivity assistant.

Features

  • Daily Briefing — the primary screen; opens on launch. Shows your AI-compiled morning digest (tasks, calendar, weather, RSS) with a full conversation you can reply to inline. Refresh manually or browse past briefings from the overflow menu.
  • Quick Capture — always-visible input bar above all tabs. Type a note or task and submit; multiple captures queue sequentially so the input is never blocked. Falls back to offline persistence when the server is unreachable.
  • Knowledge — unified browsable feed of notes, people, places, lists, and tasks across six filter tabs. Tag filters, inline search (debounced), and two-tier pagination (ID list → batch hydration). Tasks load from /api/tasks directly and are fully integrated with the knowledge feed.
  • Chat — streaming AI conversations with real-time SSE display, including live tool-use status notifications (e.g. "Calling create_note…"). Tap + to start a new conversation or open an existing one.
  • Calendar — month strip + daily agenda view backed by the server's internal event store. Full event CRUD with a modal form: title, all-day toggle, start/end date+time pickers, repeat (None/Daily/Weekly/Monthly/Yearly), description, location, and colour chips. Custom RRULE strings are preserved read-only.
  • News — RSS article feed with per-feed filtering and reactions. Tap "Discuss" to open any article in a new chat conversation.
  • Projects — browse and edit projects; tap a project to see its milestone-grouped task list.
  • Voice I/O — tap the microphone in the capture bar or chat to dictate. Server-side STT transcribes audio; TTS reads assistant replies aloud in voice mode.
  • Note & task editing — full Markdown editor for notes, task editor with due date, priority, project, and milestone assignment.
  • OAuth / SSO — authenticates via your server's OIDC provider; local username/password login also supported if enabled server-side.
  • Session persistence — stays logged in across restarts via a persistent cookie jar.
  • Auto-refresh — data refreshes automatically when the app returns to the foreground (throttled to once per 5 minutes) and when switching between shell tabs.
  • Auto-update — checks your Forgejo releases on launch and prompts to download and install new APKs in-app.

Requirements

  • A running FabledAssistant server (self-hosted)
  • Android 5.0+ (API 21)

Getting Started

Prerequisites

  • Flutter 3.x SDK
  • Android Studio (for Android SDK and emulator)
  • JDK 17

Setup

flutter pub get
flutter run

On first launch, enter your FabledAssistant server URL (e.g. https://fabled.example.com) and sign in.

Architecture

lib/
├── main.dart                        # Entry point; resolves async deps before runApp
├── app.dart                         # GoRouter + auth guards + 3-tab shell + auto-refresh
├── core/
│   ├── constants.dart               # Route name constants
│   ├── exceptions.dart              # AppException hierarchy
│   └── theme.dart                   # Custom slate-indigo ColorScheme + Fraunces typography
├── data/
│   ├── api/                         # Dio HTTP layer (one class per resource)
│   │   ├── chat_api.dart            # SSE streaming; typed ChatStreamEvent (text/status)
│   │   ├── events_api.dart          # Calendar event CRUD
│   │   ├── knowledge_api.dart       # Two-tier paginated knowledge feed
│   │   ├── news_api.dart            # RSS feed + reactions
│   │   └── voice_api.dart           # STT + TTS endpoints
│   ├── models/                      # Plain Dart models with fromJson/toJson
│   │   ├── calendar_event.dart      # CalendarEvent + dateOnly() helper
│   │   ├── knowledge_item.dart      # KnowledgeItem (notes/tasks unified)
│   │   └── message.dart             # Chat message with streaming status
│   └── repositories/                # Thin wrappers over API classes
├── providers/                       # Riverpod providers (state + dependency wiring)
│   ├── briefing_provider.dart       # Today's briefing — optimistic UI, SSE, polling
│   ├── calendar_provider.dart       # CalendarNotifier: month navigation + event CRUD
│   ├── chat_provider.dart           # Conversations + streaming messages + status
│   ├── knowledge_provider.dart      # Two-tier pagination; delegates tasks to TasksApi
│   ├── news_provider.dart           # NewsNotifier + FeedsNotifier
│   └── capture_work_queue_provider.dart  # Sequential in-memory capture queue
├── screens/
│   ├── briefing/                    # BriefingScreen + BriefingHistoryScreen
│   ├── calendar/                    # CalendarScreen (TableCalendar) + EventFormSheet
│   ├── chat/                        # ConversationsTabScreen + ChatScreen
│   ├── knowledge/                   # KnowledgeScreen (6-tab feed + search + tag filters)
│   ├── library/                     # ProjectTasksScreen (milestone-grouped task list)
│   ├── news/                        # NewsScreen (feed filter + reactions + discuss)
│   ├── notes/                       # NoteDetailScreen + NoteEditScreen
│   ├── projects/                    # ProjectsScreen + ProjectEditScreen
│   ├── tasks/                       # TaskEditScreen
│   └── settings/ auth/ setup/ splash/
└── widgets/
    ├── chat_message_bubble.dart     # Shared bubble (Chat + Briefing); shows tool status
    ├── knowledge_item_card.dart     # Card for notes, people, places, lists, tasks
    ├── news_card.dart               # RSS article card with reactions
    └── voice_mic_button.dart        # Animated mic button (capture bar + chat)

Key packages: flutter_riverpod, go_router, dio + cookie_jar, google_fonts, flutter_markdown_plus, table_calendar, record, just_audio

Building a Release APK

flutter build apk --release

The APK will be at build/app/outputs/flutter-apk/app-release.apk.

CI / CD

CI and build are defined in a single workflow (.forgejo/workflows/ci.yml) running on the shared py3.12-node22 act runner with the ghcr.io/cirruslabs/flutter:stable container.

Trigger Analyze + Test Build APK Release
PR
Push dev ✓ (artifact fabledapp-dev-<sha>)
Push main
Tag v* ✓ (artifact fabledapp-<sha>) ✓ Forgejo Release + APK attached

The build job has needs: [analyze] — a failed analyze or test blocks the APK build.

To cut a release:

git tag v26.04.06 && git push origin v26.04.06

Requires a RELEASE_TOKEN secret (Forgejo PAT with write:repository scope) set in repo Settings → Secrets → Actions.

S
Description
mobile app to connect to the fabled assistant
Readme 2.6 MiB
Languages
Dart 87.9%
C++ 5.7%
CMake 4.2%
Swift 0.7%
Shell 0.5%
Other 1%