Skip to content

Fix reset and import of AiPreferences#15843

Merged
calixtus merged 2 commits into
mainfrom
reset-ai-prefs
May 27, 2026
Merged

Fix reset and import of AiPreferences#15843
calixtus merged 2 commits into
mainfrom
reset-ai-prefs

Conversation

@calixtus

Copy link
Copy Markdown
Member

Related issues and pull requests

Follow-up to #15827

PR Description

  • Fix import and reset by usual pattern

  • Very Little enhancements in the AiPreferences class about default

      `jabref-contrib-policy:4.2:reviewed​:ok`
    

Steps to test

Run JabRef
Open Prefs
Reset Prefs
See AI Prefs reset

AI usage

Initial changes done by Claude Code (model claude-sonnet-4-6), heavily redacted by human intelligence

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • If AI tools were used, I disclosed them in the "AI usage" section and reviewed, understood, and take full ownership of all AI-generated code
  • 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

@calixtus calixtus added dev: code-quality Issues related to code or architecture decisions component: preferences labels May 27, 2026
@calixtus calixtus marked this pull request as ready for review May 27, 2026 20:33
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Refactor AI preferences initialization and reset handling

🐞 Bug fix ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Refactor AI preferences initialization to use default factory pattern
• Remove unused AiProviderDefaultChatModels class and consolidate defaults
• Add getDefault() and setAll() methods to AiPreferences for proper reset/import
• Simplify preferences loading by delegating to getAiPreferencesFromBackingStore()
• Remove hardcoded CONTEXT_WINDOW_SIZE constant from AiDefaultExpertSettings
Diagram
flowchart LR
  A["AiPreferences<br/>with defaults"] -->|"getDefault()"| B["Default instance"]
  C["JabRefCliPreferences<br/>clear/import"] -->|"setAll()"| A
  D["AiProviderDefaultChatModels<br/>removed"] -->|"consolidate to"| A
  E["PredefinedChatModelUtil"] -->|"getContextWindowSize()"| F["Dynamic lookup"]

Loading

Grey Divider

File Changes

1. jablib/src/main/java/org/jabref/logic/ai/chatting/PredefinedChatModelUtil.java ✨ Enhancement +1/-2

Remove hardcoded constant dependency

• Remove unused import of AiDefaultExpertSettings
• Replace hardcoded AiDefaultExpertSettings.CONTEXT_WINDOW_SIZE with dynamic lookup via
 PredefinedChatModel.GPT_4.getContextWindowSize()

jablib/src/main/java/org/jabref/logic/ai/chatting/PredefinedChatModelUtil.java


2. jablib/src/main/java/org/jabref/logic/ai/preferences/AiDefaultExpertSettings.java ✨ Enhancement +1/-2

Remove unused context window size constant

• Remove CONTEXT_WINDOW_SIZE constant (value 8192)
• Reorder constants for better organization

jablib/src/main/java/org/jabref/logic/ai/preferences/AiDefaultExpertSettings.java


3. jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java ✨ Enhancement +104/-0

Add default factory and bulk update methods

• Add private no-arg constructor with default values initialization
• Add DEFAULT_AI_PROVIDER constant set to AiProvider.OPEN_AI
• Add DEFAULT_CHAT_MODEL map consolidating default models per provider
• Add getDefault() static factory method returning new instance
• Add setAll(AiPreferences) method to copy all preferences from another instance
• Add import for Map and PredefinedChatModel

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


View more (2)
4. jablib/src/main/java/org/jabref/logic/ai/preferences/AiProviderDefaultChatModels.java Refactoring +0/-19

Remove utility class consolidation

• File completely removed
• Functionality consolidated into AiPreferences class

jablib/src/main/java/org/jabref/logic/ai/preferences/AiProviderDefaultChatModels.java


5. jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java 🐞 Bug fix +42/-85

Simplify AI preferences initialization and reset

• Remove 50+ lines of hardcoded AI preference defaults from constructor
• Remove imports of PredefinedChatModelUtil, AiDefaultExpertSettings, AiDefaultTemplates,
 AiProviderDefaultChatModels
• Add getAiPreferences().setAll(AiPreferences.getDefault()) in clear() method
• Add getAiPreferences().setAll(getAiPreferencesFromBackingStore(...)) in importPreferences()
 method
• Add new getAiPreferencesFromBackingStore(AiPreferences defaults) method using defaults parameter
 for fallback values
• Simplify getAiPreferences() to use
 getAiPreferencesFromBackingStore(AiPreferences.getDefault())

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


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (2)

Grey Divider


Action required

1. setAll loses expert values 🐞 Bug ≡ Correctness
Description
AiPreferences.setAll copies expert settings (e.g., temperature/contextWindow/embeddingModel/RAG
thresholds) via getters that return defaults when customizeExpertSettings is false, so importing
preferences can overwrite and persist non-default expert values even if they were present in the
backing store/XML. This causes silent loss of the user’s previously configured expert settings when
customization is currently disabled (but may be re-enabled later).
Code

jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[R236-254]

Evidence
The new setAll uses derived getters for expert fields; those getters explicitly return defaults when
customization is disabled. Because import/reset now call setAll and JabRefCliPreferences has
listeners that persist property changes back into the backing store, this can permanently overwrite
stored/imported expert values whenever customizeExpertSettings is false.

jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[225-265]
jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[431-437]
jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[495-501]
jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[511-526]
jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[981-999]
jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[1965-2017]

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

### Issue description
`AiPreferences.setAll` currently copies expert settings via getters (`getTemperature()`, `getContextWindowSize()`, `getEmbeddingModel()`, `getRagMinScore()`, etc.). These getters intentionally return defaults when `customizeExpertSettings` is `false`, so `setAll` can overwrite stored custom expert values during import/reset flows.

### Issue Context
This is especially harmful during preference import (`JabRefCliPreferences#importPreferences`) because the imported backing store may contain custom expert values while `AI_CUSTOMIZE_SETTINGS` is `false`. After `setAll`, the `EasyBind.listen(...)` handlers persist the overwritten defaults back into the backing store, losing the imported values.

### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[225-265]

### Implementation guidance
Update `setAll` to copy the *raw stored properties* for expert settings instead of the derived getters, e.g.:
- `this.embeddingModel.set(preferences.embeddingModelProperty().get());`
- `this.temperature.set(preferences.temperatureProperty().get());`
- `this.contextWindowSize.set(preferences.contextWindowSizeProperty().get());`
- `this.documentSplitterChunkSize.set(preferences.documentSplitterChunkSizeProperty().get());`
- `this.documentSplitterOverlapSize.set(preferences.documentSplitterOverlapSizeProperty().get());`
- `this.ragMaxResultsCount.set(preferences.ragMaxResultsCountProperty().get());`
- `this.ragMinScore.set(preferences.ragMinScoreProperty().get());`

(Keep using normal getters for non-derived fields like templates, provider, booleans, etc.)

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



Remediation recommended

2. DEFAULT_CHAT_MODEL misnamed Map 📘 Rule violation ⚙ Maintainability
Description
DEFAULT_CHAT_MODEL is a Map<AiProvider, PredefinedChatModel>, but the identifier is singular,
reducing clarity and violating naming conventions. This can lead to confusion and inconsistent
naming across the codebase.
Code

jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[R40-47]

Evidence
Rule 3 requires meaningful, convention-following identifiers. The newly added constant
DEFAULT_CHAT_MODEL holds multiple chat models in a Map, but its singular name is misleading.

AGENTS.md: Follow naming conventions and use correctly spelled, meaningful identifiers
jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[40-47]

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 `Map` constant was introduced with a singular name (`DEFAULT_CHAT_MODEL`), which is misleading.

## Issue Context
The compliance guideline requires meaningful identifiers and adherence to naming conventions.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[40-47]

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


3. AI prefs changes lack tests 📘 Rule violation ☼ Reliability
Description
AI preference reset/import behavior was changed in JabRefCliPreferences without corresponding test
additions/updates. This risks regressions in preference reset/import behavior going unnoticed.
Code

jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[973]

Evidence
Rule 17 requires updating/adding tests when changing behavior under org.jabref.logic. The diff
adds new AI preference reset/import logic (via setAll(AiPreferences.getDefault()) and
setAll(getAiPreferencesFromBackingStore(...))), but there are no tests in jablib/src/test/java
referencing these new AI preference reset/import behaviors.

AGENTS.md: Model/logic changes require corresponding test updates (excluding import-only changes)
jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[953-999]
jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[981-999]

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 in `org.jabref.logic` was modified for AI preference reset/import, but there are no corresponding tests covering these behavior changes.

## Issue Context
`clear()` now resets AI preferences, and `importPreferences(...)` now reloads them from the backing store; these are logic-layer behavior changes.

## Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[953-999]
- jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[981-999]
- jablib/src/main/java/org/jabref/logic/preferences/JabRefCliPreferences.java[2022-2060]

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


Grey Divider

Qodo Logo

Comment on lines +236 to +254
this.customizeExpertSettings.set(preferences.getCustomizeExpertSettings());

this.openAiApiBaseUrl.set(preferences.getOpenAiApiBaseUrl());
this.mistralAiApiBaseUrl.set(preferences.getMistralAiApiBaseUrl());
this.geminiApiBaseUrl.set(preferences.getGeminiApiBaseUrl());
this.huggingFaceApiBaseUrl.set(preferences.getHuggingFaceApiBaseUrl());

this.summarizatorKind.set(preferences.getSummarizatorKind());
this.tokenEstimatorKind.set(preferences.getTokenEstimatorKind());
this.embeddingModel.set(preferences.getEmbeddingModel());
this.temperature.set(preferences.getTemperature());
this.contextWindowSize.set(preferences.getContextWindowSize());
this.documentSplitterKind.set(preferences.getDocumentSplitterKind());
this.documentSplitterChunkSize.set(preferences.getDocumentSplitterChunkSize());
this.documentSplitterOverlapSize.set(preferences.getDocumentSplitterOverlapSize());
this.answerEngineKind.set(preferences.getAnswerEngineKind());
this.ragMaxResultsCount.set(preferences.getRagMaxResultsCount());
this.ragMinScore.set(preferences.getRagMinScore());
this.chattingSystemMessageTemplate.set(preferences.getChattingSystemMessageTemplate());

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. Setall loses expert values 🐞 Bug ≡ Correctness

AiPreferences.setAll copies expert settings (e.g., temperature/contextWindow/embeddingModel/RAG
thresholds) via getters that return defaults when customizeExpertSettings is false, so importing
preferences can overwrite and persist non-default expert values even if they were present in the
backing store/XML. This causes silent loss of the user’s previously configured expert settings when
customization is currently disabled (but may be re-enabled later).
Agent Prompt
### Issue description
`AiPreferences.setAll` currently copies expert settings via getters (`getTemperature()`, `getContextWindowSize()`, `getEmbeddingModel()`, `getRagMinScore()`, etc.). These getters intentionally return defaults when `customizeExpertSettings` is `false`, so `setAll` can overwrite stored custom expert values during import/reset flows.

### Issue Context
This is especially harmful during preference import (`JabRefCliPreferences#importPreferences`) because the imported backing store may contain custom expert values while `AI_CUSTOMIZE_SETTINGS` is `false`. After `setAll`, the `EasyBind.listen(...)` handlers persist the overwritten defaults back into the backing store, losing the imported values.

### Fix Focus Areas
- jablib/src/main/java/org/jabref/logic/ai/preferences/AiPreferences.java[225-265]

### Implementation guidance
Update `setAll` to copy the *raw stored properties* for expert settings instead of the derived getters, e.g.:
- `this.embeddingModel.set(preferences.embeddingModelProperty().get());`
- `this.temperature.set(preferences.temperatureProperty().get());`
- `this.contextWindowSize.set(preferences.contextWindowSizeProperty().get());`
- `this.documentSplitterChunkSize.set(preferences.documentSplitterChunkSizeProperty().get());`
- `this.documentSplitterOverlapSize.set(preferences.documentSplitterOverlapSizeProperty().get());`
- `this.ragMaxResultsCount.set(preferences.ragMaxResultsCountProperty().get());`
- `this.ragMinScore.set(preferences.ragMinScoreProperty().get());`

(Keep using normal getters for non-derived fields like templates, provider, booleans, etc.)

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

@subhramit subhramit requested a review from InAnYan May 27, 2026 21:17
@calixtus calixtus added this pull request to the merge queue May 27, 2026
@github-actions github-actions Bot added the status: to-be-merged PRs which are accepted and should go into the merge-queue. label May 27, 2026
Merged via the queue into main with commit b92deee May 27, 2026
59 checks passed
@calixtus calixtus deleted the reset-ai-prefs branch May 27, 2026 21:56
Siedlerchr added a commit to InAnYan/jabref that referenced this pull request May 28, 2026
* upstream/main: (29 commits)
  Chore(deps): Bump dev.langchain4j:langchain4j-bom in /versions (JabRef#15853)
  Chore(deps): Bump org.glassfish.jaxb:jaxb-runtime in /versions (JabRef#15854)
  Chore(deps): Bump com.gradleup.shadow:shadow-gradle-plugin (JabRef#15852)
  Chore(deps): Bump com.gradleup.shadow:shadow-gradle-plugin (JabRef#15849)
  Chore(deps): Bump com.autonomousapps:dependency-analysis-gradle-plugin (JabRef#15850)
  Update dependency org.apache.maven.plugins:maven-surefire-plugin to v3.5.6 (JabRef#15844)
  Fix reset and import of AiPreferences (JabRef#15843)
  Fix Comparable Contract Violation in SharedBibEntryData (JabRef#15806) (JabRef#15842)
  Chore(deps): Bump com.dlsc.gemsfx:gemsfx from 4.0.5 to 4.1.0 in /versions (JabRef#15841)
  Chore(deps): Bump jablib/src/main/resources/csl-styles (JabRef#15840)
  New Crowdin updates (JabRef#15839)
  Add group pseudonymization support (fixes JabRef#14117) (JabRef#15258)
  Feature parse MeSH terms in PubMed MEDLINE records (JabRef#15529)
  Fix/non latin author parsed as name prefix (JabRef#15823)
  Fix not on fx thread cleanup (JabRef#15835)
  Fix garbled BibEntry Javadoc example (JabRef#15834)
  Revert "Fix cleanup operationn setFiles not on fx thread causes exceptiosn"
  Revert "changelog"
  changelog
  Fix cleanup operationn setFiles not on fx thread causes exceptiosn
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: preferences dev: code-quality Issues related to code or architecture decisions 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.

2 participants