fix(local_ai): hard-override to disabled until explicit opt-in (#573)#637
Conversation
Local AI now defaults to disabled whenever the user has not explicitly picked a tier, regardless of device RAM. The onboarding flow and Settings panel remain the only ways to turn it on. Previously the bootstrap only disabled local AI on <8 GB devices and auto-applied a recommended preset on larger hosts; this flip completes the MVP goal of cloud-first defaults with a single, opt-in local model. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…inyhumansai#573) Flips the LocalAIStep sufficient-RAM screen so the primary button is "Continue with Cloud" and local AI appears as an explicit opt-in ("Use local AI instead"). This aligns onboarding with the new opt-in bootstrap: every device now starts on cloud unless the user chooses local AI. The low-RAM cloud-fallback screen is unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…yhumansai#573) Updates the sufficient-RAM path tests to match the cloud-primary UI: the default "Continue with Cloud" click advances without triggering local AI bootstrap, and the secondary "Use local AI instead" opt-in still starts the recommended-preset bootstrap and propagates errors. Low-RAM cloud-fallback tests are unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…umansai#573) Bootstrap will hard-override `enabled=false` unless this marker is true, ensuring existing installs with a stale `selected_tier` from the pre-MVP default-on era fall back to cloud until the user explicitly re-opts in. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…in (tinyhumansai#573) Every bootstrap path now returns `enabled=false` unless `opt_in_confirmed` is true, regardless of device RAM or `selected_tier`. This closes the regression where upgrading users with a persisted `selected_tier` bypassed the onboarding opt-in and started local AI without consent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…MVP tier only (tinyhumansai#573) `apply_preset` is the single source of truth for the opt-in marker: any non-disabled tier flips it true, `disabled` clears it. The preset RPC now returns `mvp_presets()` so the Settings UI exposes only the allowlisted `ram_2_4gb` tier, matching the MVP scope already enforced on the onboarding path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 28 minutes and 25 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
…ai#573) Revert the `mvp_presets()` swap in `handle_local_ai_presets`. PR tinyhumansai#588 already renders all 5 tier cards in Settings with non-MVP tiers shown as "Coming soon" / non-selectable, and that roadmap visibility is the intended UX. Returning only the MVP tier from the RPC hid the other 4 cards entirely and broke that signal. The opt-in gate still holds: `apply_preset` remains the single writer of `opt_in_confirmed`, the RPC guard continues to reject non-MVP apply_preset calls, and the bootstrap hard-override still clamps stale configs. This commit only rolls back the UI catalog surface. Fixes failing `json_rpc_local_ai_device_profile_and_presets` integration test which expects 5 presets. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…umansai#573) (tinyhumansai#637) * refactor(local_ai): default to opt-in on all devices (tinyhumansai#573) Local AI now defaults to disabled whenever the user has not explicitly picked a tier, regardless of device RAM. The onboarding flow and Settings panel remain the only ways to turn it on. Previously the bootstrap only disabled local AI on <8 GB devices and auto-applied a recommended preset on larger hosts; this flip completes the MVP goal of cloud-first defaults with a single, opt-in local model. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * style(local_ai): apply cargo fmt to bootstrap tests (tinyhumansai#573) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(onboarding): present cloud AI as default on sufficient-RAM path (tinyhumansai#573) Flips the LocalAIStep sufficient-RAM screen so the primary button is "Continue with Cloud" and local AI appears as an explicit opt-in ("Use local AI instead"). This aligns onboarding with the new opt-in bootstrap: every device now starts on cloud unless the user chooses local AI. The low-RAM cloud-fallback screen is unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(onboarding): cover opt-in local AI semantics in LocalAIStep (tinyhumansai#573) Updates the sufficient-RAM path tests to match the cloud-primary UI: the default "Continue with Cloud" click advances without triggering local AI bootstrap, and the secondary "Use local AI instead" opt-in still starts the recommended-preset bootstrap and propagates errors. Low-RAM cloud-fallback tests are unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(local_ai): add opt_in_confirmed marker to local AI config (tinyhumansai#573) Bootstrap will hard-override `enabled=false` unless this marker is true, ensuring existing installs with a stale `selected_tier` from the pre-MVP default-on era fall back to cloud until the user explicitly re-opts in. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(local_ai): hard-override local AI to disabled until explicit opt-in (tinyhumansai#573) Every bootstrap path now returns `enabled=false` unless `opt_in_confirmed` is true, regardless of device RAM or `selected_tier`. This closes the regression where upgrading users with a persisted `selected_tier` bypassed the onboarding opt-in and started local AI without consent. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(local_ai): set opt_in_confirmed on apply_preset and surface MVP tier only (tinyhumansai#573) `apply_preset` is the single source of truth for the opt-in marker: any non-disabled tier flips it true, `disabled` clears it. The preset RPC now returns `mvp_presets()` so the Settings UI exposes only the allowlisted `ram_2_4gb` tier, matching the MVP scope already enforced on the onboarding path. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * revert(local_ai): keep full preset catalog in presets RPC (tinyhumansai#573) Revert the `mvp_presets()` swap in `handle_local_ai_presets`. PR tinyhumansai#588 already renders all 5 tier cards in Settings with non-MVP tiers shown as "Coming soon" / non-selectable, and that roadmap visibility is the intended UX. Returning only the MVP tier from the RPC hid the other 4 cards entirely and broke that signal. The opt-in gate still holds: `apply_preset` remains the single writer of `opt_in_confirmed`, the RPC guard continues to reject non-MVP apply_preset calls, and the bootstrap hard-override still clamps stale configs. This commit only rolls back the UI catalog surface. Fixes failing `json_rpc_local_ai_device_profile_and_presets` integration test which expects 5 presets. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Summary
opt_in_confirmedmarker to local AI config; bootstrap hard-overridesenabled=falseunless it istrue.apply_presetsets the marker on any non-disabled tier (user's explicit choice) and clears it ondisabled.Problem
PR #588 (MVP model lockdown) clamped
selected_tierto the allowlisted range but did not gate enablement. On upgrade, users who already hadlocal_ai.enabled = truewith a savedselected_tier(from the pre-MVP default-on era) would still boot with local AI running, bypassing the explicit opt-in the MVP expects.Reported behaviour: "onboarding flow didn't come for me, but the model selected was for 2-4 GB one, which shouldn't be the case — it should be default cloud, with only a single model available to opt in."
Closes #573
Solution
Close the enablement gap with a config-schema marker + bootstrap gate, defense-in-depth against stale configs and manual edits:
src/openhuman/config/schema/local_ai.rs): Addopt_in_confirmed: boolwith#[serde(default)]→ defaults tofalsefor any existing config missing the field.src/openhuman/local_ai/service/bootstrap.rs):config_with_recommended_tier_if_unselectedhard-overridesenabled = falsewheneveropt_in_confirmed == false, regardless of device RAM orselected_tier. Every pre-MVP upgrade path therefore lands on cloud fallback.src/openhuman/local_ai/schemas.rs):apply_presetis the single source of truth for the marker — any non-disabled tier flips it totrue;disabledclears it. Onboarding and Settings already callapply_preset, so no frontend changes are required.The Settings preset catalog continues to return
all_presets()so non-MVP tiers render as "Coming soon" cards (UX established in PR #588), while the existing RPC guard rejects anyapply_presetfor a non-MVP tier.Submission Checklist
cargo test --lib -- local_ai::service::bootstrap(6/6 pass, including newbootstrap_overrides_stale_selected_tier_without_opt_inand renamedbootstrap_honors_opt_in_on_*cases);yarn test:unit LocalAIStep(6/6 pass);yarn test:unit localAiBootstrap(2/2 pass)cargo test --test json_rpc_e2e json_rpc_local_ai_device_profile_and_presetsasserts the full 5-preset catalog shape; this PR keeps that contract.///on the newopt_in_confirmedfield explaining migration semantics; module-level rationale on the bootstrap gateselected_tier, manual config edit) is overridden;apply_presetexplains the marker flip as the single source of truthImpact
opt_in_confirmed(pre-feat(local_ai): MVP model lockdown — lock selection to 2-4 GB tier (#573) #588 and post-feat(local_ai): MVP model lockdown — lock selection to 2-4 GB tier (#573) #588 upgrades) deserialise the field asfalse→ next boot lands on cloud fallback withenabled = false.selected_tieris preserved on disk for UX display; nothing is destructively rewritten.ram_2_4gbis selectable (per PR feat(local_ai): MVP model lockdown — lock selection to 2-4 GB tier (#573) #588's "Coming soon" lockdown).Related
🤖 Generated with Claude Code