Skip to content

feat: whisper context lifecycle, constrained generation, and a home slot - #626

Open
dishit-wednesday wants to merge 22 commits into
devfrom
feat/sidecar-pipeline
Open

feat: whisper context lifecycle, constrained generation, and a home slot#626
dishit-wednesday wants to merge 22 commits into
devfrom
feat/sidecar-pipeline

Conversation

@dishit-wednesday

@dishit-wednesday dishit-wednesday commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Core capabilities plus a submodule pointer bump. No product code here - the changes are to whisper's context lifecycle, model loading, constrained generation, and the home slot registry.

Whisper context lifecycle

The transcription context is now safe under a second, long-running consumer. Three ways it could be lost or corrupted underneath a caller:

  • One shared in-flight load. Two callers racing to load the model each got their own context; one was leaked. They now share the single in-flight promise.
  • Eviction is vetoed during a file transcribe. Memory pressure could evict the context out from under a decode that was still running.
  • The context resets after a wedged transcribe, so one hung call cannot hold it indefinitely. Previously the only recovery was restarting the app.

maxThreads is also passed through transcribeFile, where it was being silently dropped.

Model loading

  • skipVision - a text-only load that leaves the projector on disk, for callers that will never send an image.
  • Paired with a fix so a text-only load no longer satisfies a caller that asked for vision. That was the bug that made the flag safe to add rather than dangerous: without it, skipVision could poison a later vision request.

Constrained generation

llmConstraints collects grammar, repeat-penalty and thinking overrides into one module, accepted by generateWithMaxTokens as ConstrainedCompletionOpts. Each override was previously threaded through separately.

Slots

A home.recorder slot, rendered above recent conversations. Core declares the slot; anything may fill it or not. A build without the submodule renders nothing and behaves exactly as before.

Build and test config

ios/Podfile.lock, jest.config.js and react-native.config.js move so the submodule autolinks by root only, declares its own platforms, and runs its suite from the root config.

Reviewing this

19 commits, 14 files, +233/-45. Three are submodule pointer bumps; the rest are the changes above, from a lineage that had no open PR - so this is the first time they are proposed for dev.

Not device-verified. The whisper changes in particular are reasoned and unit-tested, not observed on hardware under real memory pressure.

Greptile Summary

The PR adds Whisper context-lifecycle coordination, text-only model loading, consolidated constrained-generation options, and a home-screen extension slot. It also updates the Pro submodule integration and associated iOS, React Native, and Jest configuration.

  • Shares concurrent Whisper loads and tracks file transcription for residency decisions.
  • Adds skipVision loading and vision-aware active-model compatibility checks.
  • Consolidates grammar, repetition, and thinking overrides into constrained completion options.
  • Registers and renders the optional home.recorder slot.
  • Updates native dependencies, autolinking, and root-level test configuration.

Confidence Score: 3/5

The PR is not yet safe to merge because vision upgrades can falsely succeed and Whisper eviction can still release a context during file-transcription startup.

A same-path model load returns before attaching the requested projector, while Whisper marks file transcription active only after starting native decoding, leaving both previously reported runtime failures outstanding.

Files Needing Attention: src/services/llm.ts, src/services/activeModelService/index.ts, src/services/whisperService.ts, src/stores/whisperStore.ts

Important Files Changed

Filename Overview
src/services/whisperService.ts Adds shared context-load handling, file-transcription lifecycle tracking, timeout recovery, and maxThreads forwarding.
src/stores/whisperStore.ts Integrates Whisper residency with an eviction veto while file transcription is active.
src/services/activeModelService/index.ts Adds vision-aware model compatibility checks and propagates text-only loading options.
src/services/llm.ts Accepts consolidated constrained-completion options and manages multimodal context metadata.
src/services/llmConstraints.ts Centralizes grammar, repeat-penalty, and thinking-option application.
src/bootstrap/slotRegistry.ts Declares the optional home recorder extension slot.
src/screens/HomeScreen/index.tsx Renders the optional recorder slot above recent conversations.
ios/Podfile Adds modular ONNX Runtime headers required by the Pro Swift pod.
jest.config.js Extends root test discovery and configuration for the checked-out Pro submodule.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Model request] --> B{Whisper or text model?}
  B -->|Whisper| C[Residency coordination]
  C --> D[Shared context load]
  D --> E[File transcription]
  B -->|Text model| F{skipVision?}
  F -->|Yes| G[Load text context only]
  F -->|No| H[Load text context and projector]
  G --> I[Constrained generation]
  H --> I
  J[Home screen] --> K[home.recorder slot]
  K --> L[Optional Pro implementation]
Loading

Reviews (2): Last reviewed commit: "chore(ios): background audio and the pod..." | Re-trigger Greptile

dishit-wednesday and others added 19 commits August 7, 2026 10:13
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
…on disk

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
…sion

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
…eak contexts

Observed on device: 4 native contexts at 406MB each, none releasable, kernel killed the foreground app at 1.85GB swap.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Unloading mid-decode cancels the native job and whisper.rn returns empty, so the clip reads as transcribed-to-nothing rather than as interrupted.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
…babel config

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
… platforms

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
pro/ has its own package.json, so a test living inside it resolved no Babel
config at all. Naming the config crosses that boundary - scoped to pro's own
tests, because setting it globally disables per-package .babelrc lookup inside
node_modules, which several React Native libraries rely on.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
… forever

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Pointer only. Everything the bump carries is private to the pro submodule - the
native VAD sidecar, the logical conversation projection, and the conversation-first
worker that finishes the oldest ended conversation before touching anything newer.

Nothing in core changes: locket is still reached through the same feature registry
entry it was before, which is what makes a change of this size a one-line commit
here.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
… doc

Carries the todo source-playback fixes - per-clip ranges for a conversation that
crossed a file roll, and resolving a recording's stored `.wav` name to the `.m4a`
that replaced it - plus the pipeline architecture document.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
@qodo-code-review

Copy link
Copy Markdown

ⓘ Qodo reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: abb2f7d6-7f28-4fbd-b05f-21eb114872c0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/services/activeModelService/index.ts
Comment thread src/stores/whisperStore.ts
@dishit-wednesday dishit-wednesday changed the title feat: whisper residency, LLM constraints, and the recorder slot feat: whisper context lifecycle, constrained generation, and a home slot Aug 10, 2026
dishit-wednesday and others added 3 commits August 10, 2026 13:00
A local notification has to be scheduled with the OS to arrive while the app is
closed, and nothing in this repo could do that - there was no notification library at
all.

THE SMALLEST CHOICE THAT WORKS ON BOTH PLATFORMS. The alternative considered was a
small native module over AlarmManager, reusing the notification channel and
PendingIntent patterns the recorder already has: no dependency, but Android only.
This is cross-platform and is what recorder-v3 used, so the shape is already known to
fit.

It is used by exactly one file in the pro submodule and nothing in core.

REQUIRES A NATIVE BUILD. Android needs a gradle sync and iOS needs `pod install`;
neither has been run, and neither platform has been built against it.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Pointer only. Everything it carries is private to the pro submodule: speaker
labelling corrected across every clip of a conversation, the detail screen showing
who spoke and what the conversation is made of, a line saying which older
conversation the loop is working on, a deadline on native calls that never answer,
and meeting reminders.

Nothing in core changes beyond the notifee dependency the reminders need - locket is
still reached through the same feature registry entry it always was.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
Two app-level requirements for the ambient recorder on iOS, plus the pro pointer.

UIBackgroundModes audio. Without it iOS suspends the audio session the moment the
app leaves the foreground, so the recorder stops the instant the screen locks -
which is most of when an ambient recorder is meant to work. It does not survive a
force-quit or an OS termination; that is a platform limit, not a setting.

onnxruntime-objc with modular_headers. It ships no module map, and OffgridPro is a
Swift pod that imports it for the recorder's Silero VAD, so without this line pod
install fails outright: "The Swift pod `OffgridPro` depends upon
`onnxruntime-objc`, which does not define modules". This is what makes the recorder
buildable on iOS at all, not a tuning preference. Podfile.lock follows.

No pro source or docs in this commit - the pro submodule pointer only.

Co-Authored-By: Dishit Karia <hanmadishit74@gmail.com>
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant