feat: whisper context lifecycle, constrained generation, and a home slot - #626
feat: whisper context lifecycle, constrained generation, and a home slot#626dishit-wednesday wants to merge 19 commits into
Conversation
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 reviews are paused because your trial has ended. Ask your workspace admin to add credits to resume reviews. Manage billing |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
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. Comment |
| // vision. Without this, a background load that skipped the projector to save memory would leave | ||
| // chat unable to see images and no path back: the id matches, so every later load short-circuits | ||
| // and the projector is never initialised. | ||
| return !(needsVision && model?.mmProjPath && !llmService.getMultimodalSupport()?.vision); |
There was a problem hiding this comment.
Same-model vision upgrade is skipped
When a model is first loaded with skipVision and later requested for vision, this check correctly rejects the text-only context, but the same-ID load retains that context and llmService.loadModel returns early for the unchanged model path. The load therefore reports success without initializing the projector, leaving image attachments unavailable until an explicit unload.
| // decode: unloading cancels the native job and whisper.rn returns an empty result, so | ||
| // the clip reads as transcribed-to-nothing rather than as interrupted. This veto is how | ||
| // the owner is told "not right now" instead of the caller second-guessing the policy. | ||
| canEvict: () => !whisperService.isFileTranscribing(), |
There was a problem hiding this comment.
Eviction veto has a startup race
If a file transcription starts after residency evaluates canEvict as true but before the selected resident is unloaded, transcription startup occurs outside the residency lock and the context is released during native decoding. Whisper then returns an empty transcription that is treated as legitimate clip output.
|



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:
maxThreadsis also passed throughtranscribeFile, 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.skipVisioncould poison a later vision request.Constrained generation
llmConstraintscollects grammar, repeat-penalty and thinking overrides into one module, accepted bygenerateWithMaxTokensasConstrainedCompletionOpts. Each override was previously threaded through separately.Slots
A
home.recorderslot, 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.jsandreact-native.config.jsmove 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.