diff --git a/src/main/java/org/jabref/gui/JabRefGUI.java b/src/main/java/org/jabref/gui/JabRefGUI.java index b0c0e1c83f0..820e4468c34 100644 --- a/src/main/java/org/jabref/gui/JabRefGUI.java +++ b/src/main/java/org/jabref/gui/JabRefGUI.java @@ -14,7 +14,6 @@ import javafx.stage.Stage; import javafx.stage.WindowEvent; -import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.frame.JabRefFrame; import org.jabref.gui.help.VersionWorker; import org.jabref.gui.icon.IconTheme; @@ -61,7 +60,6 @@ public class JabRefGUI extends Application { // AI Service handles chat messages etc. Therefore, it is tightly coupled to the GUI. private static AiService aiService; - private static ChatHistoryService chatHistoryService; private static StateManager stateManager; private static ThemeManager themeManager; @@ -102,7 +100,6 @@ public void start(Stage stage) { fileUpdateMonitor, preferences, aiService, - chatHistoryService, stateManager, countingUndoManager, Injector.instantiateModelOrService(BibEntryTypesManager.class), @@ -168,14 +165,10 @@ public void initialize() { JabRefGUI.aiService = new AiService( preferences.getAiPreferences(), preferences.getFilePreferences(), + preferences.getCitationKeyPatternPreferences(), dialogService, taskExecutor); Injector.setModelOrService(AiService.class, aiService); - - JabRefGUI.chatHistoryService = new ChatHistoryService( - preferences.getCitationKeyPatternPreferences(), - dialogService); - Injector.setModelOrService(ChatHistoryService.class, chatHistoryService); } private void setupProxy() { @@ -375,8 +368,6 @@ public void stop() { } catch (Exception e) { LOGGER.error("Unable to close AI service", e); } - LOGGER.trace("Closing chat history service"); - chatHistoryService.close(); LOGGER.trace("Closing OpenOffice connection"); OOBibBaseConnect.closeOfficeConnection(); LOGGER.trace("Stopping background tasks"); diff --git a/src/main/java/org/jabref/gui/LibraryTab.java b/src/main/java/org/jabref/gui/LibraryTab.java index 93901045848..b95bdc12e67 100644 --- a/src/main/java/org/jabref/gui/LibraryTab.java +++ b/src/main/java/org/jabref/gui/LibraryTab.java @@ -64,6 +64,7 @@ import org.jabref.gui.undo.UndoableRemoveEntries; import org.jabref.gui.util.OptionalObjectProperty; import org.jabref.gui.util.UiTaskExecutor; +import org.jabref.logic.ai.AiService; import org.jabref.logic.citationstyle.CitationStyleCache; import org.jabref.logic.importer.FetcherClientException; import org.jabref.logic.importer.FetcherException; @@ -169,6 +170,8 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private ImportHandler importHandler; private LuceneManager luceneManager; + private final AiService aiService; + /** * @param isDummyContext Indicates whether the database context is a dummy. A dummy context is used to display a progress indicator while parsing the database. * If the context is a dummy, the Lucene index should not be created, as both the dummy context and the actual context share the same index path {@link BibDatabaseContext#getFulltextIndexPath()}. @@ -178,6 +181,7 @@ private enum PanelMode { MAIN_TABLE, MAIN_TABLE_AND_ENTRY_EDITOR } private LibraryTab(BibDatabaseContext bibDatabaseContext, LibraryTabContainer tabContainer, DialogService dialogService, + AiService aiService, GuiPreferences preferences, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, @@ -197,6 +201,7 @@ private LibraryTab(BibDatabaseContext bibDatabaseContext, this.clipBoardManager = clipBoardManager; this.taskExecutor = taskExecutor; this.directoryMonitorManager = new DirectoryMonitorManager(Injector.instantiateModelOrService(DirectoryMonitor.class)); + this.aiService = aiService; initializeComponentsAndListeners(isDummyContext); @@ -249,6 +254,8 @@ private void initializeComponentsAndListeners(boolean isDummyContext) { this.entryEditor = createEntryEditor(); + aiService.setupDatabase(bibDatabaseContext); + Platform.runLater(() -> { EasyBind.subscribe(changedProperty, this::updateTabTitle); stateManager.getOpenDatabases().addListener((ListChangeListener) c -> @@ -1052,6 +1059,7 @@ public void resetChangedProperties() { public static LibraryTab createLibraryTab(BackgroundTask dataLoadingTask, Path file, DialogService dialogService, + AiService aiService, GuiPreferences preferences, StateManager stateManager, LibraryTabContainer tabContainer, @@ -1067,6 +1075,7 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi context, tabContainer, dialogService, + aiService, preferences, stateManager, fileUpdateMonitor, @@ -1088,6 +1097,7 @@ public static LibraryTab createLibraryTab(BackgroundTask dataLoadi public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, LibraryTabContainer tabContainer, DialogService dialogService, + AiService aiService, GuiPreferences preferences, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, @@ -1101,6 +1111,7 @@ public static LibraryTab createLibraryTab(BibDatabaseContext databaseContext, databaseContext, tabContainer, dialogService, + aiService, preferences, stateManager, fileUpdateMonitor, diff --git a/src/main/java/org/jabref/gui/entryeditor/AiChatTab.java b/src/main/java/org/jabref/gui/entryeditor/AiChatTab.java index 95e2b7bf102..29fb54f544c 100644 --- a/src/main/java/org/jabref/gui/entryeditor/AiChatTab.java +++ b/src/main/java/org/jabref/gui/entryeditor/AiChatTab.java @@ -11,7 +11,6 @@ import javafx.scene.control.Tooltip; import org.jabref.gui.DialogService; -import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.ai.components.aichat.AiChatGuardedComponent; import org.jabref.gui.ai.components.privacynotice.PrivacyNoticeComponent; import org.jabref.gui.ai.components.util.errorstate.ErrorStateComponent; @@ -31,7 +30,6 @@ public class AiChatTab extends EntryEditorTab { private final BibDatabaseContext bibDatabaseContext; private final AiService aiService; - private final ChatHistoryService chatHistoryService; private final DialogService dialogService; private final AiPreferences aiPreferences; private final ExternalApplicationsPreferences externalApplicationsPreferences; @@ -43,7 +41,6 @@ public class AiChatTab extends EntryEditorTab { public AiChatTab(BibDatabaseContext bibDatabaseContext, AiService aiService, - ChatHistoryService chatHistoryService, DialogService dialogService, GuiPreferences preferences, TaskExecutor taskExecutor @@ -51,7 +48,6 @@ public AiChatTab(BibDatabaseContext bibDatabaseContext, this.bibDatabaseContext = bibDatabaseContext; this.aiService = aiService; - this.chatHistoryService = chatHistoryService; this.dialogService = dialogService; this.aiPreferences = preferences.getAiPreferences(); @@ -76,7 +72,7 @@ public boolean shouldShow(BibEntry entry) { */ @Override protected void bindToEntry(BibEntry entry) { - previousBibEntry.ifPresent(previousBibEntry -> chatHistoryService.closeChatHistoryForEntry(previousBibEntry)); + previousBibEntry.ifPresent(previousBibEntry -> aiService.getChatHistoryService().closeChatHistoryForEntry(previousBibEntry)); previousBibEntry = Optional.of(entry); if (!aiPreferences.getEnableAi()) { @@ -135,7 +131,7 @@ private void bindToCorrectEntry(BibEntry entry) { setContent(new AiChatGuardedComponent( chatName, - chatHistoryService.getChatHistoryForEntry(entry), + aiService.getChatHistoryService().getChatHistoryForEntry(bibDatabaseContext, entry), bibDatabaseContext, FXCollections.observableArrayList(new ArrayList<>(List.of(entry))), aiService, diff --git a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java index 7e99897cadb..d56182edd29 100644 --- a/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java +++ b/src/main/java/org/jabref/gui/entryeditor/EntryEditor.java @@ -30,7 +30,6 @@ import org.jabref.gui.DialogService; import org.jabref.gui.LibraryTab; import org.jabref.gui.StateManager; -import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.citationkeypattern.GenerateCitationKeySingleAction; import org.jabref.gui.cleanup.CleanupSingleAction; import org.jabref.gui.entryeditor.citationrelationtab.CitationRelationsTab; @@ -119,7 +118,6 @@ public class EntryEditor extends BorderPane { @Inject private KeyBindingRepository keyBindingRepository; @Inject private JournalAbbreviationRepository journalAbbreviationRepository; @Inject private AiService aiService; - @Inject private ChatHistoryService chatHistoryService; private final List allPossibleTabs; private final Collection previewTabs; @@ -315,7 +313,7 @@ private List createTabs() { tabs.add(new LatexCitationsTab(databaseContext, preferences, dialogService, directoryMonitorManager)); tabs.add(new FulltextSearchResultsTab(stateManager, preferences, dialogService, databaseContext, taskExecutor, libraryTab.searchQueryProperty())); tabs.add(new AiSummaryTab(libraryTab.getBibDatabaseContext(), aiService, dialogService, preferences)); - tabs.add(new AiChatTab(libraryTab.getBibDatabaseContext(), aiService, chatHistoryService, dialogService, preferences, taskExecutor)); + tabs.add(new AiChatTab(libraryTab.getBibDatabaseContext(), aiService, dialogService, preferences, taskExecutor)); return tabs; } diff --git a/src/main/java/org/jabref/gui/frame/JabRefFrame.java b/src/main/java/org/jabref/gui/frame/JabRefFrame.java index d38d511fe58..573e8eb2a17 100644 --- a/src/main/java/org/jabref/gui/frame/JabRefFrame.java +++ b/src/main/java/org/jabref/gui/frame/JabRefFrame.java @@ -33,7 +33,6 @@ import org.jabref.gui.actions.ActionHelper; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.actions.StandardActions; -import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.desktop.os.NativeDesktop; import org.jabref.gui.importer.NewEntryAction; import org.jabref.gui.importer.actions.OpenDatabaseAction; @@ -77,7 +76,6 @@ public class JabRefFrame extends BorderPane implements LibraryTabContainer, UiMe private final SplitPane splitPane = new SplitPane(); private final GuiPreferences preferences; private final AiService aiService; - private final ChatHistoryService chatHistoryService; private final GlobalSearchBar globalSearchBar; private final FileHistoryMenu fileHistory; @@ -106,7 +104,6 @@ public JabRefFrame(Stage mainStage, FileUpdateMonitor fileUpdateMonitor, GuiPreferences preferences, AiService aiService, - ChatHistoryService chatHistoryService, StateManager stateManager, CountingUndoManager undoManager, BibEntryTypesManager entryTypesManager, @@ -117,7 +114,6 @@ public JabRefFrame(Stage mainStage, this.fileUpdateMonitor = fileUpdateMonitor; this.preferences = preferences; this.aiService = aiService; - this.chatHistoryService = chatHistoryService; this.stateManager = stateManager; this.undoManager = undoManager; this.entryTypesManager = entryTypesManager; @@ -157,7 +153,7 @@ public JabRefFrame(Stage mainStage, this.sidePane = new SidePane( this, this.preferences, - chatHistoryService, + aiService, Injector.instantiateModelOrService(JournalAbbreviationRepository.class), taskExecutor, dialogService, @@ -437,6 +433,7 @@ public void addTab(@NonNull BibDatabaseContext databaseContext, boolean raisePan databaseContext, this, dialogService, + aiService, preferences, stateManager, fileUpdateMonitor, diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeView.java b/src/main/java/org/jabref/gui/groups/GroupTreeView.java index a28919ef26e..4b39d4536db 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeView.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeView.java @@ -50,7 +50,6 @@ import org.jabref.gui.actions.ActionFactory; import org.jabref.gui.actions.SimpleCommand; import org.jabref.gui.actions.StandardActions; -import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.search.SearchTextField; import org.jabref.gui.util.BindingsHelper; @@ -59,6 +58,7 @@ import org.jabref.gui.util.RecursiveTreeItem; import org.jabref.gui.util.ViewModelTreeTableCellFactory; import org.jabref.gui.util.ViewModelTreeTableRowFactory; +import org.jabref.logic.ai.AiService; import org.jabref.logic.l10n.Localization; import org.jabref.logic.util.TaskExecutor; import org.jabref.model.entry.BibEntry; @@ -82,7 +82,7 @@ public class GroupTreeView extends BorderPane { private final StateManager stateManager; private final DialogService dialogService; - private final ChatHistoryService chatHistoryService; + private final AiService aiService; private final TaskExecutor taskExecutor; private final GuiPreferences preferences; @@ -108,13 +108,13 @@ public GroupTreeView(TaskExecutor taskExecutor, StateManager stateManager, GuiPreferences preferences, DialogService dialogService, - ChatHistoryService chatHistoryService + AiService aiService ) { this.taskExecutor = taskExecutor; this.stateManager = stateManager; this.preferences = preferences; this.dialogService = dialogService; - this.chatHistoryService = chatHistoryService; + this.aiService = aiService; createNodes(); this.getStylesheets().add(Objects.requireNonNull(GroupTreeView.class.getResource("GroupTree.css")).toExternalForm()); @@ -164,7 +164,7 @@ private void createNodes() { private void initialize() { this.localDragboard = stateManager.getLocalDragboard(); - viewModel = new GroupTreeViewModel(stateManager, dialogService, chatHistoryService, preferences, taskExecutor, localDragboard); + viewModel = new GroupTreeViewModel(stateManager, dialogService, aiService, preferences, taskExecutor, localDragboard); // Set-up groups tree groupTree.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE); diff --git a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java index 94e4b06aec3..5575fa6837f 100644 --- a/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java +++ b/src/main/java/org/jabref/gui/groups/GroupTreeViewModel.java @@ -24,7 +24,6 @@ import org.jabref.gui.AbstractViewModel; import org.jabref.gui.DialogService; import org.jabref.gui.StateManager; -import org.jabref.gui.ai.chatting.chathistory.ChatHistoryService; import org.jabref.gui.ai.components.aichat.AiChatWindow; import org.jabref.gui.preferences.GuiPreferences; import org.jabref.gui.util.CustomLocalDragboard; @@ -44,7 +43,6 @@ import org.jabref.model.groups.WordKeywordGroup; import org.jabref.model.metadata.MetaData; -import com.airhacks.afterburner.injection.Injector; import com.tobiasdiez.easybind.EasyBind; import dev.langchain4j.data.message.ChatMessage; @@ -54,7 +52,7 @@ public class GroupTreeViewModel extends AbstractViewModel { private final ListProperty selectedGroups = new SimpleListProperty<>(FXCollections.observableArrayList()); private final StateManager stateManager; private final DialogService dialogService; - private final ChatHistoryService chatHistoryService; + private final AiService aiService; private final GuiPreferences preferences; private final TaskExecutor taskExecutor; private final CustomLocalDragboard localDragboard; @@ -78,10 +76,16 @@ public class GroupTreeViewModel extends AbstractViewModel { }; private Optional currentDatabase = Optional.empty(); - public GroupTreeViewModel(StateManager stateManager, DialogService dialogService, ChatHistoryService chatHistoryService, GuiPreferences preferences, TaskExecutor taskExecutor, CustomLocalDragboard localDragboard) { + public GroupTreeViewModel(StateManager stateManager, + DialogService dialogService, + AiService aiService, + GuiPreferences preferences, + TaskExecutor taskExecutor, + CustomLocalDragboard localDragboard + ) { this.stateManager = Objects.requireNonNull(stateManager); this.dialogService = Objects.requireNonNull(dialogService); - this.chatHistoryService = Objects.requireNonNull(chatHistoryService); + this.aiService = Objects.requireNonNull(aiService); this.preferences = Objects.requireNonNull(preferences); this.taskExecutor = Objects.requireNonNull(taskExecutor); this.localDragboard = Objects.requireNonNull(localDragboard); @@ -399,7 +403,7 @@ public void chatWithGroup(GroupNodeViewModel group) { StringProperty nameProperty = new SimpleStringProperty(Localization.lang("Group %0", groupNameProperty.get())); groupNameProperty.addListener((obs, oldValue, newValue) -> nameProperty.setValue(Localization.lang("Group %0", groupNameProperty.get()))); - ObservableList chatHistory = chatHistoryService.getChatHistoryForGroup(group.getGroupNode()); + ObservableList chatHistory = aiService.getChatHistoryService().getChatHistoryForGroup(currentDatabase.get(), group.getGroupNode()); ObservableList bibEntries = FXCollections.observableArrayList(group.getGroupNode().findMatches(currentDatabase.get().getDatabase())); openAiChat(nameProperty, chatHistory, currentDatabase.get(), bibEntries); @@ -412,7 +416,7 @@ private void openAiChat(StringProperty name, ObservableList chatHis existingWindow.get().requestFocus(); } else { AiChatWindow aiChatWindow = new AiChatWindow( - Injector.instantiateModelOrService(AiService.class), + aiService, dialogService, preferences.getAiPreferences(), preferences.getExternalApplicationsPreferences(), diff --git a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java index d30c7d79a3d..605e389e76a 100644 --- a/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java +++ b/src/main/java/org/jabref/gui/importer/actions/OpenDatabaseAction.java @@ -200,6 +200,7 @@ private void openTheFile(Path file) { backgroundTask, file, dialogService, + aiService, preferences, stateManager, tabContainer, diff --git a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java index 267526d0ad7..ad47cc921df 100644 --- a/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java +++ b/src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java @@ -42,6 +42,7 @@ import org.jabref.gui.undo.UndoableKeyChange; import org.jabref.gui.util.DirectoryDialogConfiguration; import org.jabref.gui.util.UiTaskExecutor; +import org.jabref.logic.ai.AiService; import org.jabref.logic.citationkeypattern.CitationKeyGenerator; import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences; import org.jabref.logic.citationstyle.CitationStyle; @@ -103,6 +104,7 @@ public class OpenOfficePanel { private final ClipBoardManager clipBoardManager; private final UndoManager undoManager; private final UiTaskExecutor taskExecutor; + private final AiService aiService; private final StyleLoader loader; private final LibraryTabContainer tabContainer; private final FileUpdateMonitor fileUpdateMonitor; @@ -121,6 +123,7 @@ public OpenOfficePanel(LibraryTabContainer tabContainer, JournalAbbreviationRepository abbreviationRepository, UiTaskExecutor taskExecutor, DialogService dialogService, + AiService aiService, StateManager stateManager, FileUpdateMonitor fileUpdateMonitor, BibEntryTypesManager entryTypesManager, @@ -134,6 +137,7 @@ public OpenOfficePanel(LibraryTabContainer tabContainer, this.citationKeyPatternPreferences = citationKeyPatternPreferences; this.taskExecutor = taskExecutor; this.dialogService = dialogService; + this.aiService = aiService; this.stateManager = stateManager; this.clipBoardManager = clipBoardManager; this.undoManager = undoManager; @@ -322,6 +326,7 @@ private void exportEntries() { databaseContext, tabContainer, dialogService, + aiService, preferences, stateManager, fileUpdateMonitor, diff --git a/src/main/java/org/jabref/gui/preferences/ai/AiTab.fxml b/src/main/java/org/jabref/gui/preferences/ai/AiTab.fxml index c5dfc69e9de..b81bd96ba06 100644 --- a/src/main/java/org/jabref/gui/preferences/ai/AiTab.fxml +++ b/src/main/java/org/jabref/gui/preferences/ai/AiTab.fxml @@ -42,6 +42,21 @@ HBox.hgrow="ALWAYS" maxWidth="Infinity"/> + + + + +