v0.9.2 — Library browser & ingestion reliability
v0.9.2 makes ingestion reliable and visible. A beta tester reported that their photos, videos and PDFs “weren’t being understood” by the app. Investigation revealed that about half of their image chunks were silently failing during ingestion — hitting Gemini’s free-tier rate limit, throwing an error, and being dropped. Users saw no indication anything had gone wrong; the files just didn’t show up in search or Ask AI.
This release surfaces those failures, automatically recovers from rate limits, and gives you a real Library browser to inspect every file, chunk, and error.
What’s new
Section titled “What’s new”Three-pane Library browser
Section titled “Three-pane Library browser”The Library tab is now a full content browser:
- Folders → Files → File detail. Click a folder to see a table of every file, click a file to see its preview, chunks, and status.
- Library Overview mode shows KPI tiles, per-format progress, pipeline state, and a Health panel that surfaces alerts.
- Inline previews — images, audio, video, PDFs and documents all render directly in the detail pane using native macOS controls.
- Open and Reveal in Finder buttons on every file detail.
- Retry buttons at both library-level (all failures) and per-file level.
Full walkthrough: The Library browser.
Silent ingestion failures are now visible
Section titled “Silent ingestion failures are now visible”Previously, when Gemini returned an error mid-batch, the Media Description service would swallow the exception and return empty. The chunk was silently skipped with no error persisted — invisible to the user.
Now every failure path writes the error to the database. Failed chunks show up with red status badges in the Library browser, the actual error message (“API key not valid”, “Rate limited”, “Cannot write output file”) is kept verbatim, and clicking Retry resets the state and re-runs the pipeline.
Rate-limit handling with Retry-After
Section titled “Rate-limit handling with Retry-After”Both the embedding service and the media-description service now honour the Retry-After header Google returns with a 429 response. Worst-case retry budget increased from ~15 seconds to several minutes so free-tier quota has a real chance to reset before we give up.
A new shared IngestionPacing coordinator means when one service hits 429, the other pauses too — they no longer burn each other’s quota in parallel.
Quota-reached banner
Section titled “Quota-reached banner”When Gemini’s rate limit triggers, a banner appears at the top of the Library tab with a live countdown. Two buttons:
- Upgrade plan — opens the right Google surface for your auth mode (AI Studio for Gemini API key, Cloud Console quotas for Vertex AI).
- Retry now — clears the throttle early if the reset has already happened.
Settings cleanup
Section titled “Settings cleanup”The “Library” sub-tab in Settings is gone. Watched Folders and Pipeline Status were duplicated between Settings and the Library tab, which was confusing. Settings is now preferences only (Cloud, Preferences, Advanced, Diagnostics); content management lives in the Library tab.
Ask AI three-pane layout
Section titled “Ask AI three-pane layout”The Ask tab has the same layout pattern as Library now:
- Left — conversation history with New Chat button (unchanged).
- Middle — the Q&A thread with streaming answers and inline citations.
- Right — sources list (Cited / Also retrieved) with an inline preview of the selected source, using the same image / player / Quick Look components as Library.
Beta 2 updates
Section titled “Beta 2 updates”Pipeline timeline banner
Section titled “Pipeline timeline banner”A full-width status bar now sits above the Library browser whenever ingestion, embedding, upload, or any retry is active — no matter which trigger started it. It shows a stepper of the six pipeline stages (scan → ingest → extract → describe → upload → embed), a live progress bar, a throttle indicator when Gemini free-tier pacing kicks in, and a Cancel button that stops the run cleanly. When a run finishes, the banner summarises the result (success, completed with errors, or failed) until you dismiss it.
Failed Chunks drilldown
Section titled “Failed Chunks drilldown”The “Failed” KPI tile and the “N chunks failed ingestion” health alert are now clickable. They open a dedicated Failed Chunks pane that lists every failed chunk with its file, location, and the exact error text — with a Retry All button that resets the failed state and re-runs the pipeline while the banner tracks progress.
Polish
Section titled “Polish”- Hover states on Library overview quick-action rows (Add Folder, Retry Failed, Rescan All) so you can see which row you’re targeting.
- Ask AI: clicking a
[N]citation in the streamed answer now highlights the source row in the right pane and updates the preview (#144).
- Transcription “Cannot write output file” on MP3 ingest — the segment was being written with the source file extension (e.g.
.mp3) while exporting as AppleM4A, whichAVAssetExportSessionrejects. Now always writes.m4a(#139).
Known issues (tracked for v0.9.3 or later)
Section titled “Known issues (tracked for v0.9.3 or later)”- Italian / non-English audio transcribes as nonsense — Speech Recognition still uses en-US by default. Auto-detect language per file is planned for v0.9.3. Tracked as #140.
- Ask AI middle pane feels dense — redesign scheduled. Tracked as #141.
- RAG citation hallucination on contextless follow-ups — the LLM can cite an irrelevant source when retrieval gets poor signal from a short follow-up question. Tracked as #142.
Under the hood
Section titled “Under the hood”- New
ke_chunks.errorcolumn population across description, transcription and embedding paths. No migration — column has existed since v1, it’s just populated consistently now. - New
DatabaseQueriesmethods for per-file / per-folder / library health rollups. - New
RateLimitBackoffutility shared between embedding and description services. - New
IngestionPacingactor as a single source of truth for rate-limit state. MediaDescriptionService.generateDescriptionnow returns aDescriptionOutcomewith both a description and an error, so the pipeline can persist the error when every description path fails.- Added
MediaPlayerView(AVPlayerView wrapper) alongsideQuickLookPreviewViewinSearchDetailView.swift— both Library and Ask use them for inline media playback.