feat(search): first-run model-download progress UX (11.3)#89
Merged
Conversation
The ~130 MB `bge-small-en-v1.5` embedding model downloads on first semantic-search use inside the native-embed addon — until now silently, so a fresh install spent a minute fetching weights with zero feedback. Surface a live status in Settings → Search: Idle → Downloading (byte %) → Ready, plus Failed (retryable) and Absent (lexical-only) states. - native-embed: `embedderInit(cacheDir, onProgress?)` — the download now streams in chunks and emits per-file byte progress via a NonBlocking ThreadsafeFunction (CalleeHandled=false → clean `(progress)` callback), coalesced to ~1 MB steps. SHA256 pinning + the size cap are unchanged (still verified before ORT sees a byte). Backward-compatible: an older `.node` without the param just omits ticks (indeterminate bar). - pure `embedder-status.ts` reducer (phase + clamped percent) folds the ticks; `FastembedEmbedder` emits status through an onStatus sink. - `search:stats` carries the status; Settings → Search renders a card and polls (1 s) only while downloading. Bar is decorative (aria-hidden) — the "Downloading … X%" text is the assistive-tech source (matches the coverage bar's a11y pattern). +29 tests (status reducer 10 · seam progress/status 4 · handler semantic field 3 · card render 6, others). Native addon rebuilt + smoke-checked; the live download tick path needs a real HF fetch (same verification posture as the packaging tail). tsc + lint + size clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The on-device semantic-search model (
bge-small-en-v1.5, ~130 MB) downloads on first use inside the@brainstorm/native-embedaddon. Until now that happened silently — a fresh install spent ~a minute fetching weights with zero feedback, indistinguishable from "semantic search is broken". This surfaces a live status in Settings → Search:Idle(will download on first use) →Downloading(live byte %) →Ready, plusFailed(retryable) andAbsent(native addon unavailable → lexical-only).How (vertical slice)
embedderInit(cacheDir, onProgress?). The download now streams in chunks and emits per-file byte progress via a NonBlockingThreadsafeFunction(CalleeHandled=false→ clean(progress)callback), coalesced to ~1 MB steps (~130 events for the model file, not thousands). The SHA256 pinning + size cap are unchanged — bytes are still verified before ONNX Runtime sees them. Backward-compatible: an older.nodewithout the param simply omits ticks (the bar shows indeterminate).embedder-status.ts— a pure reducer (phase + clamped/rounded percent) that folds the ticks. Fully unit-tested, no native/vault/network needed.FastembedEmbedderemits status through anonStatussink as init starts / progresses / resolves / fails.search:statscarries the status; the panel renders a status card and polls (1 s) only while downloading.a11y
The progress bar is decorative (
aria-hidden) — the "Downloading … X%" detail text is the assistive-tech source, matching the existing coverage-bar pattern in the same panel. Keyboard/SR path unchanged (read-only diagnostic surface).Tests
+29: status reducer (10) · seam progress/status forwarding (4) · handler
semanticfield (3) · card render across all phases (6) · plus the existing embed/degrade suite updated for the new init arg.tsc(packages + apps) +lint+sizeclean; shell renderer + main bundle clean.Native addon rebuilt + smoke-checked (
embedDim/exports intact, generated.d.tsmatches the seam). The live download tick path needs a real HuggingFace fetch to exercise end-to-end — same verification posture as the 11.3 packaging tail (#84): compile + signature-match + smoke, with the tick-folding + rendering covered by fakes.Remaining 11.3 tails
Real-Electron ANN latency/recall + on-disk bench.
🤖 Generated with Claude Code