Skip to content

fix: seed inference profiles only for configured providers#3440

Merged
matthiasn merged 2 commits into
mainfrom
fix/gated-profile-seeding
Jul 12, 2026
Merged

fix: seed inference profiles only for configured providers#3440
matthiasn merged 2 commits into
mainfrom
fix/gated-profile-seeding

Conversation

@matthiasn

@matthiasn matthiasn commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

Default inference profiles were seeded unconditionally at startup, so the profile picker filled up with entries for providers that were never set up (Chinese AI Profile, Mistral (EU), etc.). This PR gates seeding on provider setup and cleans up the leftovers:

  • Gated seeding: ProfileSeedingService.seedDefaults() now maps every default profile template to a provider type (providerTypeByProfileId) and only seeds a profile once a usable provider of that type exists (non-blank API key, or non-blank base URL for keyless local providers). A fresh install starts with zero profiles; connecting Melious.ai seeds exactly the one Melious profile.
  • Immediate seeding on setup: seeding re-runs after provider create (addConfig), update (updateConfig, e.g. pasting an API key into a draft), and FTUE setup (runFtueSetupForType) — onboarding binds its categories to the profile right after the key step, so the profile must exist by then.
  • Retroactive cleanup: a new removeOrphanedDefaultSeeds() startup pass (after upgradeExisting()) deletes default seeds whose provider type has no usable provider — existing installs shed the never-configured profiles, and deleting a provider retires its untouched profile on next launch. Deliberately conservative: only rows still recognizable as untouched seeds (template name/flags, no description, no pinned host) with no model slot resolving to a usable provider's model row are removed; anything renamed, described, pinned, or rewired survives.

Docs updated (AI + onboarding feature READMEs, stale FTUE doc comment), CHANGELOG + flatpak metainfo entry under 0.9.1037.

Test plan

  • New tests: provider-gated seeding (no providers → nothing; one provider → exactly its profiles; drafts don't open the gate; keyless local providers do), orphaned-seed cleanup (removal, all keep-guards, legacy Local Power name), form-controller seeding on add/update, initialization wiring incl. error isolation.
  • dart analyze clean on lib/features/ai, lib/features/onboarding, and their tests.
  • Full affected suites pass: test/features/ai/util, test/features/ai/state, test/features/ai/ui/settings (841), test/features/onboarding (~250), test/features/agents/state/agent_providers_test.dart.
  • Local patch-coverage check: every changed, instrumented line in lib/ is hit by the test suite.

Summary by CodeRabbit

  • New Features
    • AI profile pickers now list bundled default inference profiles only when a usable provider of the matching type is already available.
    • Default profile seeding also happens during provider setup/editing when the provider becomes usable.
    • Orphaned, untouched default profiles are cleaned up automatically on next launch when their provider type is no longer usable.
    • User-customized profiles are preserved.
  • Bug Fixes
    • Startup/config initialization no longer fails if seeding or orphan cleanup encounters errors (continues safely).
  • Documentation
    • Updated release notes and onboarding/AI docs to reflect provider-gated seeding behavior.

Default inference profiles were seeded unconditionally at startup, filling
the profile picker with entries for providers that were never set up.

- gate ProfileSeedingService.seedDefaults() per provider type: a default
  profile is only created once a usable provider of its type exists
  (non-blank API key, or non-blank base URL for keyless local providers)
- re-run seeding after provider create/update and after FTUE setup so the
  profile appears the moment a provider becomes usable, including during
  onboarding where categories bind to the profile right after the key step
- add removeOrphanedDefaultSeeds() startup pass that deletes untouched
  default seeds whose provider type has no usable provider; renamed,
  described, pinned, or rewired profiles are always preserved
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d0e7c243-4973-41fa-bc05-0a2d3925983e

📥 Commits

Reviewing files that changed from the base of the PR and between 87a80a7 and 207abe3.

📒 Files selected for processing (3)
  • lib/features/ai/state/settings/inference_provider_form_controller.dart
  • lib/features/ai/util/profile_seeding_service.dart
  • test/features/ai/state/settings/inference_provider_form_controller_test.dart
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/features/ai/state/settings/inference_provider_form_controller.dart
  • lib/features/ai/util/profile_seeding_service.dart

📝 Walkthrough

Walkthrough

AI inference profiles are now seeded only when matching providers are usable. Startup removes untouched orphaned defaults, while provider saves, updates, and FTUE setup trigger seeding and upgrades. Tests and documentation cover the new lifecycle.

Changes

AI profile seeding lifecycle

Layer / File(s) Summary
Provider-gated seeding and orphan cleanup
lib/features/ai/util/profile_seeding_service.dart
Default profiles are mapped to provider types, created only for usable providers, and conservatively removed when untouched seeds become orphaned.
Startup and provider-change integration
lib/features/ai/state/ai_config_initialization.dart, lib/features/ai/state/settings/inference_provider_form_controller.dart, lib/features/ai/ui/settings/inference_provider_edit_page.dart, lib/features/ai/ui/settings/services/alibaba_ftue_setup.dart
Startup, provider saves, updates, and FTUE setup run gated seeding and profile upgrades; failures are logged without stopping the surrounding flow.
Behavioral test coverage
test/features/ai/state/ai_config_initialization_test.dart, test/features/ai/state/settings/inference_provider_form_controller_test.dart, test/features/ai/util/profile_seeding_service_test.dart
Tests cover provider gating, provider changes, startup resilience, orphan cleanup, and preservation of modified or user-created profiles.
Documentation and release notes
lib/features/ai/README.md, lib/features/onboarding/README.md, CHANGELOG.md, flatpak/com.matthiasn.lotti.metainfo.xml
Documentation and release notes describe usable-provider gating, FTUE seeding, and orphan cleanup, including the updated startup flow.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant App as App startup
  participant ProviderForm as Provider configuration
  participant FTUE as FTUE setup
  participant Seeding as ProfileSeedingService
  participant Repository as Config repository
  App->>Seeding: seedDefaults()
  Seeding->>Repository: Read provider and model rows
  Seeding->>Repository: Save eligible profiles
  App->>Seeding: removeOrphanedDefaultSeeds()
  Seeding->>Repository: Delete untouched orphaned seeds
  ProviderForm->>Seeding: seedDefaults() after save/update
  FTUE->>Seeding: seedDefaults() after setup
  Seeding->>Repository: Upgrade existing profiles
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: inference profiles are seeded only for configured providers.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/gated-profile-seeding

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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request gates the seeding of default AI inference profiles so they only appear once a usable provider of the matching type is configured. It also introduces a cleanup routine to retroactively remove untouched default profiles whose providers are no longer present or usable. The review feedback suggests optimizing the orphaned seed cleanup pass by pre-building a set of usable model IDs, which reduces the lookup complexity from $O(P \times M)$ to $O(P + M)$ and simplifies the validation logic.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread lib/features/ai/util/profile_seeding_service.dart
Comment thread lib/features/ai/util/profile_seeding_service.dart
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.26%. Comparing base (c247ff1) to head (207abe3).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3440   +/-   ##
=======================================
  Coverage   99.26%   99.26%           
=======================================
  Files        1732     1732           
  Lines      124600   124661   +61     
=======================================
+ Hits       123685   123746   +61     
  Misses        915      915           
Flag Coverage Δ
glados 14.88% <0.00%> (-0.01%) ⬇️
standard 99.01% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/features/ai/util/profile_seeding_service_test.dart (1)

528-571: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover whitespace-only credentials in the provider gate tests.

The contract requires non-blank values, but empty-string cases would still pass if usability incorrectly used isNotEmpty without trimming.

Proposed regression test
+    test('whitespace-only credentials do not open provider gates', () async {
+      when(
+        () => mockRepo.getConfigsByType(AiConfigType.inferenceProvider),
+      ).thenAnswer(
+        (_) async => [
+          AiTestDataFactory.createTestProvider(
+            id: 'melious-blank',
+            type: InferenceProviderType.melious,
+            apiKey: '   ',
+          ),
+          AiTestDataFactory.createTestProvider(
+            id: 'ollama-blank',
+            type: InferenceProviderType.ollama,
+            apiKey: '',
+            baseUrl: '   ',
+          ),
+        ],
+      );
+
+      await service.seedDefaults();
+
+      verifyNever(() => mockRepo.saveConfig(any()));
+    });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/features/ai/util/profile_seeding_service_test.dart` around lines 528 -
571, Extend the provider gate tests around service.seedDefaults to include
whitespace-only API credentials, especially the draft provider case and any
local-provider credential checks. Assert that whitespace-only values are treated
as blank and do not open the gate, preserving the existing behavior for
genuinely usable providers.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/ai/state/settings/inference_provider_form_controller.dart`:
- Around line 280-287: Update handleSave() so seedDefaults() and
upgradeExisting() are each wrapped in local best-effort error handling after the
provider save succeeds. Catch and log failures for both calls without
rethrowing, allowing successful addConfig()/updateConfig() saves to continue to
navigation instead of triggering the generic error toast.

---

Nitpick comments:
In `@test/features/ai/util/profile_seeding_service_test.dart`:
- Around line 528-571: Extend the provider gate tests around
service.seedDefaults to include whitespace-only API credentials, especially the
draft provider case and any local-provider credential checks. Assert that
whitespace-only values are treated as blank and do not open the gate, preserving
the existing behavior for genuinely usable providers.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 02bbf202-3536-488a-8887-15dbd8db7e55

📥 Commits

Reviewing files that changed from the base of the PR and between c247ff1 and 87a80a7.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • flatpak/com.matthiasn.lotti.metainfo.xml
  • lib/features/ai/README.md
  • lib/features/ai/state/ai_config_initialization.dart
  • lib/features/ai/state/settings/inference_provider_form_controller.dart
  • lib/features/ai/ui/settings/inference_provider_edit_page.dart
  • lib/features/ai/ui/settings/services/alibaba_ftue_setup.dart
  • lib/features/ai/util/profile_seeding_service.dart
  • lib/features/onboarding/README.md
  • test/features/ai/state/ai_config_initialization_test.dart
  • test/features/ai/state/settings/inference_provider_form_controller_test.dart
  • test/features/ai/util/profile_seeding_service_test.dart

Comment thread lib/features/ai/state/settings/inference_provider_form_controller.dart Outdated
- build the set of usable model slot values once in
  removeOrphanedDefaultSeeds() instead of scanning all model rows per
  profile slot, and drop the per-slot helper (Gemini review)
- make post-save profile seeding best-effort in the provider form
  controller: the provider row is already persisted, so a seeding failure
  must not surface an error toast for a successful save (CodeRabbit)
@matthiasn
matthiasn merged commit 483d2f9 into main Jul 12, 2026
28 checks passed
@matthiasn
matthiasn deleted the fix/gated-profile-seeding branch July 12, 2026 15:59
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