Skip to content

Offer Additional AI preferences and update to the latest Gemini models#15400

Merged
calixtus merged 18 commits into
JabRef:mainfrom
ganesh-vk:ai-pref-storekeys
Apr 5, 2026
Merged

Offer Additional AI preferences and update to the latest Gemini models#15400
calixtus merged 18 commits into
JabRef:mainfrom
ganesh-vk:ai-pref-storekeys

Conversation

@ganesh-vk

@ganesh-vk ganesh-vk commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Related issues and pull requests

Closes #15398, #15392

PR Description

Adds a checkbox for viewing AI provider API key, adds a checkbox giving the user the choice to store API key (as done in git). Earlier the API key was stored by default.
While testing I noticed that the Gemini model used was not supported by google anymore. I've updated them to the latest models provided by google.

Steps to test

  • Open the AI preferences in settings and enable AI functionality
  • Set your AI provider and enter your API key
  • Use the checkbox to either hide or view your API key
  • Select "Remember API key", see that the key is stored and persists on restart
  • Unselect "Remember API key", see that the key is no longer stored and is deleted on restart

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • [/] I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • [/] I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • [/] I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository
AI_toggles Gemini_AI_chat Gemini_models

…y for AI models

- Add preference to allow user to view API key for AI models
- Move to latest gemini models and remove deprecated models
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Add API key preferences and update to latest Gemini models

✨ Enhancement 🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Add API key visibility toggle and optional storage preference
• Update deprecated Gemini models to latest versions
• Implement keyring-based API key persistence with user control
• Add credential store availability detection with tooltip feedback
Diagram
flowchart LR
  A["User Preferences"] -->|"Show/Hide Toggle"| B["API Key Display"]
  A -->|"Remember Preference"| C["Keyring Storage"]
  C -->|"If Disabled"| D["Delete Stored Keys"]
  E["Deprecated Gemini Models"] -->|"Replace"| F["Latest Gemini 3.x Models"]
  G["Credential Store"] -->|"Check Availability"| H["Enable/Disable Storage"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTab.java ✨ Enhancement +23/-0

Add API key visibility and storage UI controls

• Add visibleApiKeyTextField and checkboxes for show/remember API key functionality
• Bind visibility properties to toggle between password and visible text fields
• Add tooltip for credential store unavailability
• Disable API key controls when GPT4ALL provider is selected

jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTab.java


2. jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java ✨ Enhancement +15/-0

Add API key storage preference properties

• Add rememberApiKey and passwordPersistAvailable boolean properties
• Initialize properties from preferences and OS keyring availability
• Store remember API key preference in settings
• Add getter methods for new properties

jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTabViewModel.java


3. jablib/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java 🐞 Bug fix +3/-4

Update to latest Gemini 3.x models

• Replace deprecated GEMINI_1_5_FLASH, GEMINI_1_5_PRO, GEMINI_1_0_PRO with GEMINI_3_0_FLASH
 and GEMINI_3_1_PRO
• Update default Gemini chat model to GEMINI_3_0_FLASH
• Maintain context window sizes for new models

jablib/src/main/java/org/jabref/logic/ai/AiDefaultPreferences.java


View more (4)
4. jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java ✨ Enhancement +26/-1

Implement conditional API key storage logic

• Add rememberApiKey boolean property to control API key persistence
• Modify getApiKeyForAiProvider() to return empty string if remember preference is disabled
• Update storeAiApiKeyInKeyring() to skip storage when remember preference is disabled
• Add deleteStoredApiKeys() method to clear all stored API keys
• Add getter/setter methods for remember API key preference

jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java


5. jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java ✨ Enhancement +9/-0

Add API key storage preference to configuration

• Add AI_REMEMBER_API_KEY preference constant with default value false
• Include remember API key preference in getAiPreferences() constructor call
• Add listener to delete stored keys when remember preference is toggled off
• Persist remember API key preference changes to configuration

jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java


6. CHANGELOG.md 📝 Documentation +2/-0

Update changelog with new features and fixes

• Document new API key storage and visibility toggle feature
• Document removal of deprecated Gemini models and replacement with current offerings
• Link both changes to related GitHub issues

CHANGELOG.md


7. jabgui/src/main/resources/org/jabref/gui/preferences/ai/AiTab.fxml ✨ Enhancement +31/-21

Update UI layout with API key controls

• Add StackPane import for layering password and visible text fields
• Restructure grid layout to accommodate new checkboxes
• Add visibleApiKeyTextField and stack it with password field
• Add showApiKeyCheckbox and rememberApiKeyCheckbox UI elements
• Reorganize AI provider and chat model fields in grid layout

jabgui/src/main/resources/org/jabref/gui/preferences/ai/AiTab.fxml


Grey Divider

Qodo Logo

@github-actions github-actions Bot added the good second issue Issues that involve a tour of two or three interweaved components in JabRef label Mar 24, 2026
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (2) 📎 Requirement gaps (0) 🎨 UX Issues (0)

Grey Divider


Action required

1. AI key storage lacks tests 📘 Rule violation ≡ Correctness
Description
Core AI preference behavior was changed (API key retrieval/storage now gated by rememberApiKey and
keys are deleted when toggled off) without any accompanying test updates in this PR. This risks
regressions in preference persistence and keyring interaction behavior.
Code

jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java[R145-151]

+        if (!getRememberApiKey()) {
+            return "";
+        }
+
try (final Keyring keyring = Keyring.create()) {
return keyring.getPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name());
} catch (PasswordAccessException e) {
Evidence
PR Compliance IDs 16 and 19 require updating/adding tests when behavior changes, especially in
org.jabref.logic. This PR modifies AI key storage semantics in AiPreferences and adds
deletion-on-toggle logic in JabRefCliPreferences, but the provided diff contains no test
additions/updates.

AGENTS.md
AGENTS.md
jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java[145-181]
jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[2037-2042]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Behavior changed for AI API key persistence (gated by `rememberApiKey` and deletion on toggle-off), but no tests were added/updated in this PR.
## Issue Context
This affects `org.jabref.logic` preference behavior and persistence wiring via `JabRefCliPreferences`, so regression risk is high without coverage.
## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java[145-181]
- jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[2037-2042]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. AiTab.fxml fixed minWidth 📘 Rule violation ≡ Correctness
Description
The UI layout introduces a hard-coded minWidth="120" column constraint, which can reduce
responsiveness and cause layout issues on different font sizes/translations. Prefer responsive
sizing/layout constraints over fixed pixel widths.
Code

jabgui/src/main/resources/org/jabref/gui/preferences/ai/AiTab.fxml[96]

+            <ColumnConstraints minWidth="120" halignment="LEFT"/>
Evidence
PR Compliance ID 29 requires preferring responsive layouts over hard-coded pixel constraints. The
added ColumnConstraints uses a fixed minWidth value, which is a hard-coded pixel constraint.

jabgui/src/main/resources/org/jabref/gui/preferences/ai/AiTab.fxml[96-96]
Best Practice: Learned patterns

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A fixed pixel `minWidth` was introduced in the preferences UI layout, which may harm responsiveness and localization/translation layout.
## Issue Context
JabRef UI should prefer responsive layout approaches over hard-coded pixel sizing.
## Fix Focus Areas
- jabgui/src/main/resources/org/jabref/gui/preferences/ai/AiTab.fxml[96-96]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Tooltip not initialized/visible🐞 Bug ≡ Correctness
Description
AiTab sets the “Credential store not available.” tooltip on the disabled rememberApiKeyCheckbox, but
disabled controls do not show tooltips and the tooltip may never be set on first load when the
availability property starts false and does not change. Users won’t learn why the checkbox is
disabled.
Code

jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTab.java[R227-235]

+        rememberApiKeyCheckbox.selectedProperty().bindBidirectional(viewModel.rememberApiKeyProperty());
+        rememberApiKeyCheckbox.disableProperty().bind(viewModel.passwordPersistAvailable().not());
+        viewModel.passwordPersistAvailable().addListener((_, _, available) -> {
+            if (available) {
+                rememberApiKeyCheckbox.setTooltip(null);
+            } else {
+                rememberApiKeyCheckbox.setTooltip(new Tooltip(Localization.lang("Credential store not available.")));
+            }
+        });
Evidence
AiTab uses addListener to set the tooltip on the checkbox itself. If passwordPersistAvailable
remains false (default SimpleBooleanProperty is false and setValues may set it to false again), no
change event fires and the tooltip remains null. Even if set, JavaFX disabled controls typically
don’t show tooltips; the codebase already works around this in NetworkTab by placing the tooltip on
a wrapper node explicitly because disabled controls don’t show tooltips.

jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTab.java[219-246]
jabgui/src/main/java/org/jabref/gui/preferences/network/NetworkTab.java[48-51]
jabgui/src/main/java/org/jabref/gui/preferences/network/NetworkTab.java[109-118]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The tooltip explaining why “Remember API key” is disabled is set on a disabled CheckBox and may not be initialized on first load. Users won’t see the explanation.
### Issue Context
Network preferences already solve this with a wrapper node (`persistentTooltipWrapper`) because disabled controls don’t show tooltips.
### Fix Focus Areas
- jabgui/src/main/resources/org/jabref/gui/preferences/ai/AiTab.fxml[121-139]
- Wrap `rememberApiKeyCheckbox` (or a surrounding container) in a node with an `fx:id` (e.g., `rememberApiKeyTooltipWrapper`) used to host the tooltip.
- jabgui/src/main/java/org/jabref/gui/preferences/ai/AiTab.java[227-235]
- Set the tooltip on the wrapper node, not the disabled checkbox.
- Initialize the tooltip immediately based on the current value (not only on change), or use a subscription mechanism that fires once initially (similar to `EasyBind.subscribe` in NetworkTab).
### Acceptance criteria
- When keyring/credential store is unavailable on startup, the user can still hover the disabled area and see “Credential store not available.”

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. Stored keys hidden by default🐞 Bug ≡ Correctness
Description
The new AI_REMEMBER_API_KEY preference defaults to false, and getApiKeyForAiProvider short-circuits
to empty when it’s false, so previously stored keyring credentials will be ignored unless users
discover and enable “Remember API key.” This creates a high-risk upgrade regression where AI
suddenly stops working despite credentials existing in the keyring.
Code

jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[R709-713]

defaults.put(AI_GEMINI_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.GEMINI).getName());
defaults.put(AI_HUGGING_FACE_CHAT_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.HUGGING_FACE).getName());
defaults.put(AI_GPT_4_ALL_MODEL, AiDefaultPreferences.CHAT_MODELS.get(AiProvider.GPT4ALL).getName());
+        defaults.put(AI_REMEMBER_API_KEY, Boolean.FALSE);
defaults.put(AI_CUSTOMIZE_SETTINGS, AiDefaultPreferences.CUSTOMIZE_SETTINGS);
Evidence
JabRefCliPreferences sets the default value of AI_REMEMBER_API_KEY to false for users without that
preference key. AiPreferences.getApiKeyForAiProvider now returns empty when rememberApiKey is false,
so any credentials that are present in the system keyring are not read and AI chat fails its
“missing API key” check.

jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[708-713]
jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[1986-2000]
jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java[144-148]
jablib/src/main/java/org/jabref/logic/ai/chatting/model/JabRefChatLanguageModel.java[49-52]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Users who already have AI keys stored in the OS keyring but don’t yet have the new preference key (`aiRememberApiKey`) will default to `false` and the app will ignore the stored credentials.
### Issue Context
This is caused by the default (`Boolean.FALSE`) combined with retrieval being gated by `rememberApiKey`.
### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[708-713]
- Decide on a backward-compatible default/migration strategy.
- jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java[144-148]
- Ensure retrieval behavior does not unexpectedly hide existing credentials (especially on upgrade).
### Possible acceptance criteria
- Existing installations with keyring-stored AI keys continue to work after upgrade without requiring users to re-enter keys.
- New installations remain secure-by-default if desired (e.g., default unchecked but does not break runtime usage).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@testlens-app

This comment has been minimized.

Comment on lines 145 to 151
if (!getRememberApiKey()) {
return "";
}

try (final Keyring keyring = Keyring.create()) {
return keyring.getPassword(KEYRING_AI_SERVICE, KEYRING_AI_SERVICE_ACCOUNT + "-" + aiProvider.name());
} catch (PasswordAccessException e) {

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.

Action required

1. Ai key storage lacks tests 📘 Rule violation ✓ Correctness

Core AI preference behavior was changed (API key retrieval/storage now gated by rememberApiKey and
keys are deleted when toggled off) without any accompanying test updates in this PR. This risks
regressions in preference persistence and keyring interaction behavior.
Agent Prompt
## Issue description
Behavior changed for AI API key persistence (gated by `rememberApiKey` and deletion on toggle-off), but no tests were added/updated in this PR.

## Issue Context
This affects `org.jabref.logic` preference behavior and persistence wiring via `JabRefCliPreferences`, so regression risk is high without coverage.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/ai/AiPreferences.java[145-181]
- jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[2037-2042]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, it would be good to have tests

@github-actions github-actions Bot added the status: changes-required Pull requests that are not yet complete label Mar 24, 2026
@testlens-app

This comment has been minimized.

@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete status: no-bot-comments labels Mar 24, 2026
@Siedlerchr

Copy link
Copy Markdown
Member

regarding the latest AI models, good thing, this also refs #14197

@testlens-app

This comment has been minimized.

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 24, 2026
@testlens-app

This comment has been minimized.

@ThiloteE

ThiloteE commented Mar 24, 2026

Copy link
Copy Markdown
Member

I think there was a misunderstanding: Issue #15398 was about storing/remembering the API key when switching between providers, not storing/remembering during restarts of JabRef (but that's good too!)

Things I noticed when I tested the PR:

  • At first glance, unticking "Remember API key" does nothing. The API key will still be remembered, when switching providers (which is ok), but it's confusing. We don't need a checkbox there, if the API key is stored permanently anyway. Users also can delete the API key by deleting the characters in the textfield, so no need for the checkbox. Then I realized this checkbox is only for restarts, hence ... either remove the checkbox (I am in favor of that to save screenspace and prevent information overload) or rename "Remember API key" to "Persist API key across restarts". Tooltip should be:
    grafik
  • "Persist API key across restarts" should be on by default, as presently, JabRef does not feature enterprise-ready isolated app centric user-profiles.
  • There are ways to put the toggle directly into the password field, which would be prefered to save screenspace and prevent information overload

@testlens-app

This comment has been minimized.

- Remove view api key toggle and place toggle inside the checkbox
- Rename "Remember API key" to "Persist API key across sessions"
- Change default persist api key preference to true
@testlens-app

This comment has been minimized.

@ganesh-vk

ganesh-vk commented Mar 24, 2026

Copy link
Copy Markdown
Contributor Author

Hi @ThiloteE thanks for the review!

I think there was a misunderstanding: Issue #15398 was about storing/remembering the API key when switching between providers, not storing/remembering during restarts of JabRef (but that's good too!)

I actually tried changing providers after entering keys and the API key is stored in the current upstream. I tried on my main branch just now again to make sure. So I assumed the real issue was to store across restarts. The current code in the dev branch stores the key across restarts regardless i.e. no preference is offered. So I assumed a preference should be offered similar to git where the user chooses if the PAT should persist (as seen in the Network tab)

either remove the checkbox (I am in favor of that to save screenspace and prevent information overload) or rename "Remember API key" to "Persist API key across restarts"

I'm a fan of keeping the checkbox :), I've renamed it to "Persist API key across sessions" and also moved the API key visibility toggle as suggested

@ganesh-vk

Copy link
Copy Markdown
Contributor Author

but to be precise, in the article you linked, it is said that best pracice is to not EXPOSE an API key in a client side application

my bad, you're right I misread that.

So do you suggest we scrap the preference entirely?

@ganesh-vk

Copy link
Copy Markdown
Contributor Author

Here is what I've done:

  1. Open JabRef
  2. Go to settings
  3. Go to AI section
  4. Enable AI features
  5. Enter key
  6. Check "persist key" option
  7. Save preferences
  8. Chat, restart jabref, chat again

Result: everything works

But if on the step 6 I uncheck "persist key" - after saving I can't chat with AI and when I open settings again - the key is empty

I tried it out, this is a bug. Will fix

ganesh-vk and others added 2 commits April 3, 2026 23:05
…o original behaviour.

Add a delete button in the API key field to improve UX.
@ganesh-vk

Copy link
Copy Markdown
Contributor Author

I took a look at Zed and how it stores API keys. It persists across restarts and does not offer a preference (if it does it wasn't in an obvious location). I agree with @ThiloteE, we should store the API key by default. I added a delete icon to the API key field to improve UX (similar to Zed).

We should probably remove the same preference wherever else it is offered as well but I think that should be done in a separate PR.

@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Apr 3, 2026
@ThiloteE

ThiloteE commented Apr 3, 2026

Copy link
Copy Markdown
Member

So do you suggest we scrap the preference entirely?

I am not 100% sure, but yes I would tend to scrap the preference. We have had persistence across restarts for the web-search and nobody has ever complained. The only concern I personally have is about multi-user setups and I don't know how API persistence is handled in virtual machines, but that seems like an edge case. In the unlikely case it causes problems, users can report their workflow and their software setup and we then will be able to fix it with a much clearer understanding of the requirements and we then will be able to test it, because we will be able to reproduce the issues.

@InAnYan

InAnYan commented Apr 4, 2026

Copy link
Copy Markdown
Member

I think it's more simple:

  1. We don't use the same store for secrets as for preferences, thus it's safer.
  2. Jabref needs to know the API key in order for AI chat to work, thus we have to store it in a property.

So I believe the scheme that we worked on is safe enough.

The only problem I see is that it's a plain string and not a secret string like in Rust's secret_string or Python's SecretStr, but there we go into details

@calixtus

calixtus commented Apr 4, 2026

Copy link
Copy Markdown
Member

API keys belong in the keystore, not in the prefs. See proxy preferences

@calixtus

calixtus commented Apr 4, 2026

Copy link
Copy Markdown
Member

Sorry, i meant KeyRing

@github-actions github-actions Bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Apr 5, 2026
@github-actions

github-actions Bot commented Apr 5, 2026

Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@InAnYan InAnYan self-assigned this Apr 5, 2026
InAnYan
InAnYan previously approved these changes Apr 5, 2026

@InAnYan InAnYan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Looks good to me

calixtus
calixtus previously approved these changes Apr 5, 2026
@calixtus calixtus dismissed stale reviews from InAnYan and themself via 70b5678 April 5, 2026 13:35
@calixtus calixtus enabled auto-merge April 5, 2026 13:35
@github-actions github-actions Bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Apr 5, 2026
@calixtus calixtus added this pull request to the merge queue Apr 5, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label Apr 5, 2026
Merged via the queue into JabRef:main with commit 72caef0 Apr 5, 2026
55 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: ai good second issue Issues that involve a tour of two or three interweaved components in JabRef status: no-bot-comments status: to-be-merged PRs which are accepted and should go into the merge-queue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Store API keys for different providers in AI settings

5 participants