From a0daae5f0e14cbf5d7572d6dcbd3a78691a9fc25 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 9 May 2026 13:53:22 -0500 Subject: [PATCH 01/42] Fixed logo error with the updater. --- src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java index 74788457..6789b118 100644 --- a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java +++ b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java @@ -82,7 +82,7 @@ public boolean startUpdate() { } public void buildAndDisplayUpdateWindow(GitHubUtil gitHubUtil) { - window = new WindowBuilder("Update").setDimensions(450, 200).setIcon(new ImageLoader(new File(App.getAppDirectory(), "logo.png"))).build(); + window = new WindowBuilder("Update").setDimensions(450, 200).setIcon(new ImageLoader(new File(App.getExecutedDirectory(), "logo.png"))).build(); container = new EmptyContainer(window.getWidth(), window.getHeight()); window.addContainer(container); window.getStage().setOnHidden(windowEvent -> { From 2983b46ce9e1dd2bbf89e451445dda142e8f6362 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sun, 10 May 2026 07:31:08 -0500 Subject: [PATCH 02/42] Increased avatar size and added image smoothing. --- src/main/java/me/piitex/app/views/chats/ChatPageView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/views/chats/ChatPageView.java b/src/main/java/me/piitex/app/views/chats/ChatPageView.java index 5ccbe9db..965417fa 100644 --- a/src/main/java/me/piitex/app/views/chats/ChatPageView.java +++ b/src/main/java/me/piitex/app/views/chats/ChatPageView.java @@ -114,7 +114,7 @@ public VerticalLayout buildMessageBox(ChatMessage chatMessage) { layout.addElement(separator); //TODO: Make Avatar circular - int avatarSize = 128; + int avatarSize = 196; if (chatMessage.getSender() == Role.ASSISTANT) { displayBox.setAlignment(Pos.CENTER_RIGHT); @@ -126,6 +126,7 @@ public VerticalLayout buildMessageBox(ChatMessage chatMessage) { ImageLoader imageLoader = new ImageLoader(new File(iconPath)); imageLoader.setWidth(avatarSize); imageLoader.setHeight(avatarSize); + imageLoader.setSmoothing(true); ImageOverlay avatar = new ImageOverlay(imageLoader); avatar.setFitWidth(avatarSize); avatar.setFitHeight(avatarSize); @@ -146,6 +147,7 @@ public VerticalLayout buildMessageBox(ChatMessage chatMessage) { ImageLoader imageLoader = new ImageLoader(new File(iconPath)); imageLoader.setWidth(avatarSize); imageLoader.setHeight(avatarSize); + imageLoader.setSmoothing(true); ImageOverlay avatar = new ImageOverlay(imageLoader); avatar.setFitWidth(avatarSize); avatar.setFitHeight(avatarSize); From 9cb8f312692f9fdf3ffb1ca4dd615686ca5216f7 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sun, 10 May 2026 07:31:18 -0500 Subject: [PATCH 03/42] Removed system print line. --- src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java index 6789b118..50fd820b 100644 --- a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java +++ b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java @@ -64,7 +64,6 @@ private void fetchLatestRelease() { public synchronized boolean isUpdateAvailable() { if (current != null && latest != null) { - System.out.println("Not null"); return current.compareTo(latest) < 0; } System.out.println("False"); From 0477767d8ad9d478adfe4245dc6fa1839929a8be Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Mon, 11 May 2026 14:21:33 -0500 Subject: [PATCH 04/42] Deleted default model option and added coloring to icons. --- .../piitex/app/views/models/tabs/ListTab.java | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/src/main/java/me/piitex/app/views/models/tabs/ListTab.java b/src/main/java/me/piitex/app/views/models/tabs/ListTab.java index 7fecfec0..ad019616 100644 --- a/src/main/java/me/piitex/app/views/models/tabs/ListTab.java +++ b/src/main/java/me/piitex/app/views/models/tabs/ListTab.java @@ -4,6 +4,7 @@ import atlantafx.base.theme.Tweaks; import javafx.application.Platform; import javafx.geometry.Pos; +import javafx.scene.paint.Color; import me.piitex.app.App; import me.piitex.app.backend.Model; import me.piitex.app.configuration.AppSettings; @@ -74,7 +75,7 @@ public void buildModelCards(Layout layout) { TitledLayout root = new TitledLayout(model.getFile().getName() + " (" + formattedFileSize + "GB)", scrollContainer.getWidth() - 100, -1); root.setMaxSize(root.getWidth(), -1); root.addStyle(Styles.DENSE); - root.setSpacing(50); + root.setSpacing(25); root.setAlignment(Pos.TOP_CENTER); root.addStyle(Tweaks.ALT_ICON); root.setExpanded(model.getSettings().isDefault()); @@ -100,37 +101,16 @@ public void buildModelCards(Layout layout) { location.setEnabled(false); body.addElement(location); - HorizontalLayout footer = new HorizontalLayout(800, 50); + HorizontalLayout footer = new HorizontalLayout(400, 50); + footer.setAlignment(Pos.CENTER_LEFT); root.addElement(footer); - - CheckBoxOverlay defaultModel = new CheckBoxOverlay(model.getSettings().isDefault(),"Set as default"); - footer.addElement(defaultModel); - defaultModel.onSet(event -> { - // If set to true scan all models and set default to false - // Then set this one to true - // Also, re-render the view - - // Reloop models and disable any defaults - for (Model m : App.getModels("exclude")) { - if (m == model) continue; - if (m.getSettings().isDefault()) { - m.getSettings().setDefault(false); - } - } - model.getSettings().setDefault(event.getNewValue()); - - tabsContainer.replaceTab(tabsContainer.getTabs().get("List"), new ListTab(tabsContainer)); - tabsContainer.setSelectedTab("List"); - }); - - HorizontalLayout subFooter = new HorizontalLayout(400, 50); - subFooter.setX(20); - subFooter.setSpacing(40); - footer.addElement(subFooter); + footer.setSpacing(30); IconOverlay settings = new IconOverlay(Material2MZ.SETTINGS); + settings.setIconSize(18); + settings.setColor(Color.BLUE); settings.setTooltip("Go to model settings."); - subFooter.addElement(settings); + footer.addElement(settings); settings.addStyle(Styles.ACCENT); settings.addStyle(Styles.LARGE); settings.onClick(event -> { @@ -139,9 +119,11 @@ public void buildModelCards(Layout layout) { }); IconOverlay delete = new IconOverlay(Material2AL.DELETE_FOREVER); + delete.setIconSize(18); + delete.setColor(Color.RED); delete.setTooltip("Delete the model."); delete.addStyle(Styles.DANGER); - subFooter.addElement(delete); + footer.addElement(delete); delete.onClick(event -> { // Confirm the model deletion. From db5465f82ec1f14f86279dfb0944cc45fa3f7412 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Tue, 12 May 2026 08:08:52 -0500 Subject: [PATCH 05/42] Refactored ImageLoader from RenEngine changes. --- src/main/java/me/piitex/app/App.java | 6 +++--- src/main/java/me/piitex/app/backend/User.java | 5 +++-- .../me/piitex/app/updater/ApplicationUpdater.java | 4 ++-- .../me/piitex/app/updater/LLamaBackendUpdater.java | 4 ++-- .../piitex/app/views/characters/CharactersView.java | 4 ++-- .../app/views/characters/tabs/CharacterTab.java | 9 +++++---- .../piitex/app/views/characters/tabs/UserTab.java | 11 ++++++----- .../me/piitex/app/views/chats/ChatPageView.java | 7 ++++--- .../characters/CharacterCustomizationView.java | 13 +++++++------ .../characters/CharacterUserCustomizationView.java | 13 +++++++------ .../characters/FinishCharacterCreatorView.java | 3 +-- .../views/creator/users/UserCustomizationView.java | 13 +++++++------ .../me/piitex/app/views/users/UserTemplateView.java | 4 ++-- .../me/piitex/app/views/users/tabs/UserTab.java | 9 +++++---- 14 files changed, 56 insertions(+), 49 deletions(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index a63cd397..5c1b3d43 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -20,13 +20,13 @@ import me.piitex.app.views.HomeView; import me.piitex.app.views.Positions; import me.piitex.engine.WindowBuilder; +import me.piitex.engine.loaders.image.BaseImageLoader; import me.piitex.os.OSPathing; import me.piitex.os.OSUtil; import me.piitex.os.configurations.InfoFile; import me.piitex.engine.Window; import me.piitex.engine.containers.EmptyContainer; import me.piitex.engine.fxloader.FXLoad; -import me.piitex.engine.loaders.ImageLoader; import me.piitex.engine.overlays.AlertOverlay; import me.piitex.engine.overlays.ButtonBuilder; import me.piitex.engine.overlays.ButtonOverlay; @@ -207,7 +207,7 @@ public void initialization(Stage initialStage) { logger.info("Screen Size ({},{})", dimension.width, dimension.height); File logo = new File(getExecutedDirectory(), "logo.png"); - window = new WindowBuilder("Chat App").setIcon(new ImageLoader(logo)).setScale((appSettings.isWindowScaling()) && !mobile).setAntiAliasing(false).setDimensions(setWidth, setHeight).build(); + window = new WindowBuilder("Chat App").setIcon(new BaseImageLoader(logo)).setScale((appSettings.isWindowScaling()) && !mobile).setAntiAliasing(false).setDimensions(setWidth, setHeight).build(); // Initialize global positions. Needed for the rendering process. Positions.initialize(); @@ -469,7 +469,7 @@ public Window buildErrorWindow(String message) { Application.setUserAgentStylesheet(new PrimerDark().getUserAgentStylesheet()); File logo = new File(getExecutedDirectory(), "logo.png"); - window = new WindowBuilder("Error").setDimensions(400, 150).setIcon(new ImageLoader(logo)).build(); + window = new WindowBuilder("Error").setDimensions(400, 150).setIcon(new BaseImageLoader(logo)).build(); EmptyContainer emptyContainer = new EmptyContainer(window.getWidth(), window.getHeight()); window.addContainer(emptyContainer); diff --git a/src/main/java/me/piitex/app/backend/User.java b/src/main/java/me/piitex/app/backend/User.java index ef9a9153..28cd0bfa 100644 --- a/src/main/java/me/piitex/app/backend/User.java +++ b/src/main/java/me/piitex/app/backend/User.java @@ -1,9 +1,10 @@ package me.piitex.app.backend; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import org.jetbrains.annotations.Nullable; import me.piitex.app.App; import me.piitex.os.configurations.InfoFile; -import me.piitex.engine.loaders.ImageLoader; import me.piitex.engine.overlays.ImageOverlay; import java.io.File; @@ -141,7 +142,7 @@ public static ImageOverlay getUserAvatar(String iconPath, double width, double h } - ImageLoader loader = new ImageLoader(file); + ImageLoader loader = new BaseImageLoader(file); loader.setWidth(width); loader.setHeight(height); diff --git a/src/main/java/me/piitex/app/updater/ApplicationUpdater.java b/src/main/java/me/piitex/app/updater/ApplicationUpdater.java index b99c4a3a..8bff6733 100644 --- a/src/main/java/me/piitex/app/updater/ApplicationUpdater.java +++ b/src/main/java/me/piitex/app/updater/ApplicationUpdater.java @@ -7,7 +7,7 @@ import me.piitex.engine.WindowBuilder; import me.piitex.engine.containers.Container; import me.piitex.engine.containers.EmptyContainer; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; import me.piitex.engine.overlays.ButtonBuilder; import me.piitex.engine.overlays.ButtonOverlay; import me.piitex.engine.overlays.ProgressBarOverlay; @@ -55,7 +55,7 @@ public void checkForUpdates() { } public void buildAndDisplayUpdateWindow(GitHubUtil gitHubUtil) { - window = new WindowBuilder("Update").setDimensions(400, 150).setIcon(new ImageLoader(new File(App.getAppDirectory(), "logo.png"))).build(); + window = new WindowBuilder("Update").setDimensions(400, 150).setIcon(new BaseImageLoader(new File(App.getAppDirectory(), "logo.png"))).build(); container = new EmptyContainer(400, 150); window.addContainer(container); diff --git a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java index 50fd820b..c2172b6c 100644 --- a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java +++ b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java @@ -13,7 +13,7 @@ import me.piitex.engine.containers.DownloadContainer; import me.piitex.engine.containers.EmptyContainer; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; import me.piitex.engine.overlays.ButtonBuilder; import me.piitex.engine.overlays.ButtonOverlay; import me.piitex.engine.overlays.ProgressBarOverlay; @@ -81,7 +81,7 @@ public boolean startUpdate() { } public void buildAndDisplayUpdateWindow(GitHubUtil gitHubUtil) { - window = new WindowBuilder("Update").setDimensions(450, 200).setIcon(new ImageLoader(new File(App.getExecutedDirectory(), "logo.png"))).build(); + window = new WindowBuilder("Update").setDimensions(450, 200).setIcon(new BaseImageLoader(new File(App.getExecutedDirectory(), "logo.png"))).build(); container = new EmptyContainer(window.getWidth(), window.getHeight()); window.addContainer(container); window.getStage().setOnHidden(windowEvent -> { diff --git a/src/main/java/me/piitex/app/views/characters/CharactersView.java b/src/main/java/me/piitex/app/views/characters/CharactersView.java index 8fc95c5f..7b7e2677 100644 --- a/src/main/java/me/piitex/app/views/characters/CharactersView.java +++ b/src/main/java/me/piitex/app/views/characters/CharactersView.java @@ -23,7 +23,7 @@ import me.piitex.engine.layouts.FlowLayout; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import org.apache.commons.io.FileUtils; import org.kordamp.ikonli.material2.Material2AL; @@ -269,7 +269,7 @@ private void deleteCharacter(FlowLayout base, CardContainer card, Character char App.getThreadPoolManager().submitSchedule(() -> { try { App.logger.info("Removing image from cache '{}'", character.getIconPath()); - ImageLoader.imageCache.remove(character.getIconPath()); // Clear image from cache. + ImageLoader.clearCache(); App.logger.info("Deleting Character: {}", character.getId()); FileUtils.deleteDirectory(character.getCharacterDirectory()); } catch (IOException e) { diff --git a/src/main/java/me/piitex/app/views/characters/tabs/CharacterTab.java b/src/main/java/me/piitex/app/views/characters/tabs/CharacterTab.java index 737c8e07..2cd0349a 100644 --- a/src/main/java/me/piitex/app/views/characters/tabs/CharacterTab.java +++ b/src/main/java/me/piitex/app/views/characters/tabs/CharacterTab.java @@ -20,7 +20,8 @@ import me.piitex.engine.containers.tabs.Tab; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import me.piitex.app.backend.Character; import org.json.JSONObject; @@ -104,7 +105,7 @@ private CardContainer buildCharacterDisplay() { currentIconPath = new File(App.getAppDirectory(), "icons/character.png"); } - ImageLoader loader = new ImageLoader(currentIconPath); + ImageLoader loader = new BaseImageLoader(currentIconPath); loader.setWidth(256); loader.setHeight(256); @@ -134,7 +135,7 @@ private CardContainer buildCharacterDisplay() { parentView.updateInfoData(); - ImageLoader imageLoader = new ImageLoader(selectedFile); + ImageLoader imageLoader = new BaseImageLoader(selectedFile); imageLoader.setWidth(256); imageLoader.setHeight(256); @@ -207,7 +208,7 @@ private VerticalLayout buildCharacterInput(@Nullable Character character, boolea parentView.setCharacterIconPath(file); parentView.getInfoFile().set("icon-path", file.getAbsolutePath()); - image.setImage(new ImageLoader(file)); + image.setImage(new BaseImageLoader(file)); parentView.updateInfoData(); diff --git a/src/main/java/me/piitex/app/views/characters/tabs/UserTab.java b/src/main/java/me/piitex/app/views/characters/tabs/UserTab.java index 942609bf..60e9deab 100644 --- a/src/main/java/me/piitex/app/views/characters/tabs/UserTab.java +++ b/src/main/java/me/piitex/app/views/characters/tabs/UserTab.java @@ -10,6 +10,8 @@ import me.piitex.app.configuration.AppSettings; import me.piitex.app.utils.ImageCardExporter; import me.piitex.app.utils.UserCardImporter; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.os.configurations.InfoFile; import me.piitex.app.views.characters.CharacterEditView; import me.piitex.engine.containers.CardContainer; @@ -17,7 +19,6 @@ import me.piitex.engine.containers.tabs.Tab; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; import me.piitex.engine.overlays.*; import org.json.JSONObject; @@ -103,7 +104,7 @@ private CardContainer buildUserDisplay() { currentIconPath = new File(App.getAppDirectory(), "icons/character.png"); } - ImageLoader loader = new ImageLoader(currentIconPath); + ImageLoader loader = new BaseImageLoader(currentIconPath); loader.setWidth(256); loader.setHeight(256); @@ -133,7 +134,7 @@ private CardContainer buildUserDisplay() { parentView.updateInfoData(); - ImageLoader imageLoader = new ImageLoader(selectedFile); + ImageLoader imageLoader = new BaseImageLoader(selectedFile); imageLoader.setWidth(256); imageLoader.setHeight(256); @@ -189,7 +190,7 @@ private VerticalLayout buildUserInput() { if (template.getIconPath() != null && !template.getIconPath().isEmpty()) { parentView.setUserIconPath(new File(template.getIconPath())); - image.setImage(new ImageLoader(parentView.getUserIconPath())); + image.setImage(new BaseImageLoader(parentView.getUserIconPath())); } if (parentView.getUser() != null) { @@ -228,7 +229,7 @@ private VerticalLayout buildUserInput() { parentView.setUserIconPath(file); parentView.getInfoFile().set("icon-path-user", file.getAbsolutePath()); - image.setImage(new ImageLoader(file)); + image.setImage(new BaseImageLoader(file)); parentView.updateInfoData(); diff --git a/src/main/java/me/piitex/app/views/chats/ChatPageView.java b/src/main/java/me/piitex/app/views/chats/ChatPageView.java index 965417fa..b308fd4e 100644 --- a/src/main/java/me/piitex/app/views/chats/ChatPageView.java +++ b/src/main/java/me/piitex/app/views/chats/ChatPageView.java @@ -20,7 +20,8 @@ import me.piitex.engine.containers.ScrollContainer; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import org.kordamp.ikonli.material2.Material2MZ; @@ -123,7 +124,7 @@ public VerticalLayout buildMessageBox(ChatMessage chatMessage) { iconPath = new File(App.getExecutedDirectory(), "icons/charater.png").getAbsolutePath(); } - ImageLoader imageLoader = new ImageLoader(new File(iconPath)); + ImageLoader imageLoader = new BaseImageLoader(new File(iconPath)); imageLoader.setWidth(avatarSize); imageLoader.setHeight(avatarSize); imageLoader.setSmoothing(true); @@ -144,7 +145,7 @@ public VerticalLayout buildMessageBox(ChatMessage chatMessage) { iconPath = new File(App.getExecutedDirectory(), "icons/charater.png").getAbsolutePath(); } - ImageLoader imageLoader = new ImageLoader(new File(iconPath)); + ImageLoader imageLoader = new BaseImageLoader(new File(iconPath)); imageLoader.setWidth(avatarSize); imageLoader.setHeight(avatarSize); imageLoader.setSmoothing(true); diff --git a/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java b/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java index 899c169f..3cf3ed44 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java @@ -16,7 +16,8 @@ import me.piitex.engine.containers.TileContainer; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import me.piitex.os.configurations.InfoFile; import org.json.JSONObject; @@ -178,7 +179,7 @@ private VerticalLayout buildSettingsLayout() { characterIdInput.setCurrentText(id); characterDisplayInput.setCurrentText(displayName); characterPersonaInput.setCurrentText(persona); - characterImage.setImage(new ImageLoader(file)); + characterImage.setImage(new BaseImageLoader(file)); loreLayout.removeAllElements(); loreItems.forEach((s, s2) -> loreLayout.addElement(buildLoreEntry(s, s2))); } catch (ImageProcessingException | IOException e) { @@ -257,9 +258,9 @@ private VerticalLayout buildImagesLayout() { ImageLoader imageLoader; if (infoFile.hasKey("icon-path")) { - imageLoader = new ImageLoader(new File(infoFile.get("icon-path"))); + imageLoader = new BaseImageLoader(new File(infoFile.get("icon-path"))); } else { - imageLoader = new ImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); + imageLoader = new BaseImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); } imageLoader.setWidth(imageSize); imageLoader.setHeight(imageSize); @@ -277,7 +278,7 @@ private VerticalLayout buildImagesLayout() { if (file != null && file.isFile() && file.exists()) { App.logger.info("Updating image to '{}'", file.getAbsoluteFile()); - ImageLoader newImage = new ImageLoader(file); + ImageLoader newImage = new BaseImageLoader(file); newImage.setWidth(imageSize); newImage.setHeight(imageSize); characterImage.setImage(newImage); @@ -290,7 +291,7 @@ private VerticalLayout buildImagesLayout() { ButtonOverlay reset = new ButtonBuilder("rst").setText("Reset Image").addStyle(Styles.FLAT).build(); layout.addElement(reset); reset.onClick(_ -> { - ImageLoader loader = new ImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); + ImageLoader loader = new BaseImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); characterImage.setImage(loader); infoFile.set("icon-path", imageLoader.getFile().getAbsolutePath()); }); diff --git a/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java b/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java index 13480229..61b328ac 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java @@ -16,7 +16,8 @@ import me.piitex.engine.containers.TileContainer; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import me.piitex.os.configurations.InfoFile; import org.json.JSONObject; @@ -112,7 +113,7 @@ private VerticalLayout buildSettingsLayout() { tempLore.clear(); userDisplayInput.setCurrentText(user.getDisplayName()); userPersonaInput.setCurrentText(user.getPersona()); - userImage.setImage(new ImageLoader(new File(user.getIconPath()))); + userImage.setImage(new BaseImageLoader(new File(user.getIconPath()))); loreLayout.removeAllElements(); loreItems.forEach((s, s2) -> loreLayout.addElement(buildLoreEntry(s, s2))); }); @@ -183,7 +184,7 @@ private VerticalLayout buildSettingsLayout() { tempLore.clear(); userDisplayInput.setCurrentText(displayName); userPersonaInput.setCurrentText(persona); - userImage.setImage(new ImageLoader(file)); + userImage.setImage(new BaseImageLoader(file)); loreLayout.removeAllElements(); loreItems.forEach((s, s2) -> loreLayout.addElement(buildLoreEntry(s, s2))); } catch (ImageProcessingException | IOException e) { @@ -266,7 +267,7 @@ private VerticalLayout buildImagesLayout() { image = new File(App.getExecutedDirectory(), "icons/character.png"); } - ImageLoader imageLoader = new ImageLoader(image); + ImageLoader imageLoader = new BaseImageLoader(image); imageLoader.setWidth(imageSize); imageLoader.setHeight(imageSize); @@ -284,7 +285,7 @@ private VerticalLayout buildImagesLayout() { if (file != null && !file.isDirectory() && file.exists()) { App.logger.info("Updating image to '{}'", file.getAbsoluteFile()); - ImageLoader newImage = new ImageLoader(file); + ImageLoader newImage = new BaseImageLoader(file); newImage.setWidth(imageSize); newImage.setHeight(imageSize); userImage.setImage(newImage); @@ -297,7 +298,7 @@ private VerticalLayout buildImagesLayout() { ButtonOverlay reset = new ButtonBuilder("rst").setText("Reset Image").addStyle(Styles.FLAT).build(); layout.addElement(reset); reset.onClick(_ -> { - ImageLoader loader = new ImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); + ImageLoader loader = new BaseImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); userImage.setImage(loader); infoFile.set("user-icon-path", loader.getFile().getAbsolutePath()); }); diff --git a/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java b/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java index f62cbf81..73e69c5a 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java @@ -14,7 +14,7 @@ import me.piitex.engine.containers.ScrollContainer; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import me.piitex.os.configurations.InfoFile; import org.kordamp.ikonli.material2.Material2AL; @@ -23,7 +23,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.StandardCopyOption; -import java.util.TreeMap; import java.util.concurrent.TimeUnit; public class FinishCharacterCreatorView extends EmptyContainer { diff --git a/src/main/java/me/piitex/app/views/creator/users/UserCustomizationView.java b/src/main/java/me/piitex/app/views/creator/users/UserCustomizationView.java index e5d0c657..3550fdef 100644 --- a/src/main/java/me/piitex/app/views/creator/users/UserCustomizationView.java +++ b/src/main/java/me/piitex/app/views/creator/users/UserCustomizationView.java @@ -13,7 +13,8 @@ import me.piitex.engine.containers.ScrollContainer; import me.piitex.engine.containers.TileContainer; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import me.piitex.os.configurations.InfoFile; import org.json.JSONObject; @@ -172,7 +173,7 @@ private VerticalLayout buildSettingsLayout() { userIdInput.setCurrentText(id); userDisplayInput.setCurrentText(displayName); userPersonaInput.setCurrentText(persona); - userImage.setImage(new ImageLoader(file)); + userImage.setImage(new BaseImageLoader(file)); parent.getUserLoreCustomizationView().getLoreLayout().removeAllElements(); loreItems.forEach((s, s2) -> parent.getUserLoreCustomizationView().getLoreLayout().addElement(parent.getUserLoreCustomizationView().buildLoreEntry(s, s2))); @@ -253,9 +254,9 @@ private VerticalLayout buildImagesLayout() { ImageLoader imageLoader; if (infoFile.hasKey("icon-path")) { - imageLoader = new ImageLoader(new File(infoFile.get("icon-path"))); + imageLoader = new BaseImageLoader(new File(infoFile.get("icon-path"))); } else { - imageLoader = new ImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); + imageLoader = new BaseImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); } imageLoader.setWidth(imageSize); imageLoader.setHeight(imageSize); @@ -273,7 +274,7 @@ private VerticalLayout buildImagesLayout() { if (file != null && file.isFile() && file.exists()) { App.logger.info("Updating image to '{}'", file.getAbsoluteFile()); - ImageLoader newImage = new ImageLoader(file); + ImageLoader newImage = new BaseImageLoader(file); newImage.setWidth(imageSize); newImage.setHeight(imageSize); userImage.setImage(newImage); @@ -286,7 +287,7 @@ private VerticalLayout buildImagesLayout() { ButtonOverlay reset = new ButtonBuilder("rst").setText("Reset Image").addStyle(Styles.FLAT).build(); layout.addElement(reset); reset.onClick(_ -> { - ImageLoader loader = new ImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); + ImageLoader loader = new BaseImageLoader(new File(App.getExecutedDirectory(), "icons/character.png")); userImage.setImage(loader); infoFile.set("icon-path", imageLoader.getFile().getAbsolutePath()); }); diff --git a/src/main/java/me/piitex/app/views/users/UserTemplateView.java b/src/main/java/me/piitex/app/views/users/UserTemplateView.java index 8e48e8b3..808ba7bf 100644 --- a/src/main/java/me/piitex/app/views/users/UserTemplateView.java +++ b/src/main/java/me/piitex/app/views/users/UserTemplateView.java @@ -23,7 +23,7 @@ import me.piitex.engine.layouts.FlowLayout; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import org.apache.commons.io.FileUtils; import org.kordamp.ikonli.material2.Material2AL; @@ -281,7 +281,7 @@ private void deleteUser(FlowLayout base, CardContainer card, me.piitex.app.backe App.getThreadPoolManager().submitSchedule(() -> { try { App.logger.info("Removing image from cache '{}'", user.getIconPath()); - ImageLoader.imageCache.remove(user.getIconPath()); // Clear image from cache. + ImageLoader.clearCache(); App.logger.info("Deleting User: {}", user.getId()); FileUtils.deleteDirectory(user.getUserDirectory()); } catch (IOException e) { diff --git a/src/main/java/me/piitex/app/views/users/tabs/UserTab.java b/src/main/java/me/piitex/app/views/users/tabs/UserTab.java index 0033b8a0..62c577c8 100644 --- a/src/main/java/me/piitex/app/views/users/tabs/UserTab.java +++ b/src/main/java/me/piitex/app/views/users/tabs/UserTab.java @@ -14,7 +14,8 @@ import me.piitex.engine.containers.tabs.Tab; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.ImageLoader; +import me.piitex.engine.loaders.image.BaseImageLoader; +import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import org.json.JSONObject; @@ -92,7 +93,7 @@ private CardContainer buildUserDisplay() { currentIconPath = new File(App.getAppDirectory(), "icons/character.png"); } - ImageLoader loader = new ImageLoader(currentIconPath); + ImageLoader loader = new BaseImageLoader(currentIconPath); loader.setWidth(256); loader.setHeight(256); @@ -120,7 +121,7 @@ private CardContainer buildUserDisplay() { appSettings.setImagesPath(selectedFile.getParent()); userEditView.setUserIconPath(selectedFile.getAbsoluteFile()); - ImageLoader imageLoader = new ImageLoader(selectedFile); + ImageLoader imageLoader = new BaseImageLoader(selectedFile); imageLoader.setWidth(256); imageLoader.setHeight(256); @@ -179,7 +180,7 @@ private VerticalLayout buildUserInput() { userEditView.getUserLoreBookTab().buildLorebookTabContent(); userEditView.setUserIconPath(file); - image.setImage(new ImageLoader(file)); + image.setImage(new BaseImageLoader(file)); } catch (ImageProcessingException | IOException e) { App.logger.error("Error importing character card: ", e); Platform.runLater(() -> { From 85943a035a6a082bfe14baac33d8a895f508e551 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Tue, 12 May 2026 08:09:27 -0500 Subject: [PATCH 06/42] Fixed issue where VRAM would not be properly calculated due to old llama.cpp versions. --- .../app/backend/server/ServerProcess.java | 19 +++++++++++++++++++ .../piitex/app/views/setup/GPUSetupView.java | 6 ++++++ .../app/views/setup/SetupRunnerView.java | 6 ++++++ src/main/java/module-info.java | 1 + 4 files changed, 32 insertions(+) diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 8b14639e..0884dd90 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -8,6 +8,10 @@ import me.piitex.engine.PopupPosition; import me.piitex.engine.overlays.MessageOverlay; import me.piitex.os.OSUtil; +import oshi.SystemInfo; +import oshi.hardware.CentralProcessor; +import oshi.hardware.GraphicsCard; +import oshi.hardware.HardwareAbstractionLayer; import java.io.File; import java.io.FileInputStream; @@ -176,6 +180,21 @@ private LinkedList getParameters(File server, ServerSettings settings) { // The usage is a percentage of the total layers (model.getGpuLayers()); double TOTAL_AVAILABLE_VRAM_MIB = App.getInstance().getAppSettings().getTotalGpuVram(); + if (TOTAL_AVAILABLE_VRAM_MIB <= 0) { + App.logger.warn("VRAM is set to 0. Attempting to fetch VRAM..."); + // Fallback to Oshi + SystemInfo systemInfo = new SystemInfo(); + HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware(); + GraphicsCard graphicsCard = hardwareAbstractionLayer.getGraphicsCards().getFirst(); + if (graphicsCard != null) { + TOTAL_AVAILABLE_VRAM_MIB = graphicsCard.getVRam() / (1024.0 * 1024.0); + App.getInstance().getAppSettings().setTotalGpuVram(TOTAL_AVAILABLE_VRAM_MIB); + } else { + App.logger.error("Could not find dedicated GPU. Using global memory pool..."); + TOTAL_AVAILABLE_VRAM_MIB = systemInfo.getHardware().getMemory().getTotal() / (1024.0 * 1024.0); + } + } + double KV_CACHE = model.getSettings().getKvCacheSize(); double COMPUTED_BUFFER_SIZE = model.getSettings().getComputeBufferSize(); double FIXED_OVERHEAD_MIB = KV_CACHE + COMPUTED_BUFFER_SIZE; diff --git a/src/main/java/me/piitex/app/views/setup/GPUSetupView.java b/src/main/java/me/piitex/app/views/setup/GPUSetupView.java index 85a17bc0..1abcaf0b 100644 --- a/src/main/java/me/piitex/app/views/setup/GPUSetupView.java +++ b/src/main/java/me/piitex/app/views/setup/GPUSetupView.java @@ -63,6 +63,12 @@ private void init() { backendBox.addElement(backendSelection); backendSelection.onItemSelect(event -> { settings.setBackend(event.getNewValue()); + + try { + new DeviceProcess(event.getNewValue()); + } catch (IOException e) { + App.logger.error("Could not load devices for '" + event.getNewValue() + "'!", e); + } }); VerticalLayout gpuBox = new VerticalLayout(-1, -1); diff --git a/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java b/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java index 450b6963..3e41cc89 100644 --- a/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java +++ b/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java @@ -92,6 +92,12 @@ private void startRunner() { } private void downloadSmallModel() { + File model = new File(App.getModelsDirectory(), "gemma-3-270m-it-UD-IQ2_M.gguf"); + if (model.exists()) { + startLLama(model); + return; + } + FileDownloader fileDownloader = new FileDownloader(); fileDownloader.addDownloadListener(new DownloadListener() { @Override diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 8c8647ed..42635b48 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -22,6 +22,7 @@ requires org.apache.commons.lang3; requires org.apache.commons.compress; requires javafx.base; + requires com.github.oshi; opens me.piitex.app to javafx.fxml; exports me.piitex.app; From 88a1758b7778cf13104fd90c2f85dbe8cb717616 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Wed, 13 May 2026 10:45:38 -0500 Subject: [PATCH 07/42] Added URISyntaxException catch. --- .../java/me/piitex/app/views/models/tabs/DownloadTab.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/piitex/app/views/models/tabs/DownloadTab.java b/src/main/java/me/piitex/app/views/models/tabs/DownloadTab.java index bb9c890d..2579fa0b 100644 --- a/src/main/java/me/piitex/app/views/models/tabs/DownloadTab.java +++ b/src/main/java/me/piitex/app/views/models/tabs/DownloadTab.java @@ -30,6 +30,7 @@ import java.io.File; import java.io.IOException; import java.net.SocketTimeoutException; +import java.net.URISyntaxException; import java.util.LinkedHashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -233,7 +234,7 @@ private void setupFileInfoFetch(HorizontalLayout tileLayout, String key, String long fileSize = 0; try { fileSize = downloader.getRemoteFileSize(url); - } catch (IOException e) { + } catch (IOException | URISyntaxException e) { App.logger.warn("Failed to fetch download size. Connection could not be established: '{}'", url); } String fileName = url.substring(url.lastIndexOf('/') + 1); @@ -315,7 +316,7 @@ private void createDownloadInputs(HorizontalLayout tileLayout, ButtonOverlay dow DownloadInfo existingInfo = downloader.getDownloadInfo(url); RingProgressIndicator progressIndicator = new RingProgressIndicator(0, false); - IconOverlay stopButton = createStopButton(url, destinationFile, downloadIcon, tileLayout, fileInfoRef); + IconOverlay stopButton = createStopButton(url, destinationFile, existingInfo, fileInfoRef); TextField downloadSpeed = new TextField(""); downloadSpeed.setMaxWidth(100); @@ -411,7 +412,7 @@ public void onDownloadCancel(DownloadInfo info) { } } - private IconOverlay createStopButton(String url, File fileToDelete, ButtonOverlay downloadIcon, HorizontalLayout tileLayout, AtomicReference fileInfoRef) { + private IconOverlay createStopButton(String url, File fileToDelete, DownloadInfo info, AtomicReference fileInfoRef) { IconOverlay stop = new IconOverlay(Material2MZ.STOP_CIRCLE); stop.setColor(Color.RED); stop.onClick(event -> { From 2a7cd8f994a288c65ec901e906f91c59bafeebe2 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Wed, 13 May 2026 10:48:50 -0500 Subject: [PATCH 08/42] Removed qodana. --- .github/workflows/qodana_code_quality.yml | 39 ------------------- qodana.yaml | 46 ----------------------- 2 files changed, 85 deletions(-) delete mode 100644 .github/workflows/qodana_code_quality.yml delete mode 100644 qodana.yaml diff --git a/.github/workflows/qodana_code_quality.yml b/.github/workflows/qodana_code_quality.yml deleted file mode 100644 index 78f34d3a..00000000 --- a/.github/workflows/qodana_code_quality.yml +++ /dev/null @@ -1,39 +0,0 @@ -#-------------------------------------------------------------------------------# -# Discover all capabilities of Qodana in our documentation # -# https://www.jetbrains.com/help/qodana/about-qodana.html # -#-------------------------------------------------------------------------------# - -name: Qodana -on: - workflow_dispatch: - pull_request: - push: - branches: - - master - -jobs: - qodana: - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - checks: write - steps: - - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} - fetch-depth: 0 - - name: 'Qodana Scan' - uses: JetBrains/qodana-action@v2025.2 - env: - QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} - with: - # When pr-mode is set to true, Qodana analyzes only the files that have been changed - pr-mode: false - use-caches: true - post-pr-comment: true - use-annotations: true - # Upload Qodana results (SARIF, other artifacts, logs) as an artifact to the job - upload-result: false - # quick-fixes available in Ultimate and Ultimate Plus plans - push-fixes: 'none' \ No newline at end of file diff --git a/qodana.yaml b/qodana.yaml deleted file mode 100644 index 6d050d82..00000000 --- a/qodana.yaml +++ /dev/null @@ -1,46 +0,0 @@ -#-------------------------------------------------------------------------------# -# Qodana analysis is configured by qodana.yaml file # -# https://www.jetbrains.com/help/qodana/qodana-yaml.html # -#-------------------------------------------------------------------------------# -################################################################################# -# WARNING: Do not store sensitive information in this file, # -# as its contents will be included in the Qodana report. # -################################################################################# -version: '1.0' -#Specify inspection profile for code analysis -profile: - name: qodana.starter -#Enable inspections -#include: -# - name: -#Disable inspections -#exclude: -# - name: -# paths: -# - -projectJDK: '25' #(Applied in CI/CD pipeline) -#Execute shell command before Qodana execution (Applied in CI/CD pipeline) -#bootstrap: sh ./prepare-qodana.sh -#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline) -#plugins: -# - id: #(plugin id can be found at https://plugins.jetbrains.com) -# Quality gate. Will fail the CI/CD pipeline if any condition is not met -# severityThresholds - configures maximum thresholds for different problem severities -# testCoverageThresholds - configures minimum code coverage on a whole project and newly added code -# Code Coverage is available in Ultimate and Ultimate Plus plans -#failureConditions: -# severityThresholds: -# any: 15 -# critical: 5 -# testCoverageThresholds: -# fresh: 70 -# total: 50 -#Qodana supports other languages, for example, Python, JavaScript, TypeScript, Go, C#, PHP -#For all supported languages see https://www.jetbrains.com/help/qodana/linters.html -linter: 'jetbrains/qodana-jvm-community:2025.2' -include: - - name: UNUSED_IMPORT - - name: ThrowablePrintStackTrace - - name: GroovyUnnecessaryReturn - - name: FieldMayBeFinal - - name: UnnecessaryLocalVariable From 1c2e2216ce706e8e3a805e66612a3956c78ce287 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Wed, 13 May 2026 10:49:36 -0500 Subject: [PATCH 09/42] Added force disable reasoning to fix issues with unsupported models. --- .../app/backend/server/ServerProcess.java | 5 ++++ .../app/configuration/ModelSettings.java | 13 ++++++++++ .../app/views/models/ModelEditView.java | 25 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 0884dd90..d2a34960 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -261,6 +261,11 @@ private LinkedList getParameters(File server, ServerSettings settings) { parameters.add(model.getSettings().getReasoningTemplate()); } + if (model.getSettings().isForceDisableReasoning()) { + App.logger.info("Force disable reasoning...."); + parameters.add("--no-prefill-assistant"); + } + if (!model.getSettings().getChatTemplate().equalsIgnoreCase("default")) { App.logger.debug("Setting chat template..."); parameters.add("--chat-template"); diff --git a/src/main/java/me/piitex/app/configuration/ModelSettings.java b/src/main/java/me/piitex/app/configuration/ModelSettings.java index 29ae48aa..ecfa2e14 100644 --- a/src/main/java/me/piitex/app/configuration/ModelSettings.java +++ b/src/main/java/me/piitex/app/configuration/ModelSettings.java @@ -29,6 +29,7 @@ public class ModelSettings { private String reasoningTemplate = "disabled"; private boolean useDefault; private boolean jinja = false; + private boolean forceDisableReasoning = false; private int totalLayers = 0; private double dataPerLayer; private double kvCacheSize; @@ -184,6 +185,9 @@ public ModelSettings(InfoFile infoFile) { if (infoFile.hasKey("change")) { this.change = infoFile.getBoolean("change"); } + if (infoFile.hasKey("force-disable-reason")) { + this.forceDisableReasoning = infoFile.getBoolean("force-disable-reason"); + } } public String getModelInstructions() { @@ -474,6 +478,15 @@ public void setChange(boolean change) { infoFile.set("change", change); } + public boolean isForceDisableReasoning() { + return forceDisableReasoning; + } + + public void setForceDisableReasoning(boolean forceDisableReasoning) { + this.forceDisableReasoning = forceDisableReasoning; + infoFile.set("force-disable-reason", forceDisableReasoning); + } + @Nullable public InfoFile getInfoFile() { return infoFile; diff --git a/src/main/java/me/piitex/app/views/models/ModelEditView.java b/src/main/java/me/piitex/app/views/models/ModelEditView.java index 96795a60..ccbc4769 100644 --- a/src/main/java/me/piitex/app/views/models/ModelEditView.java +++ b/src/main/java/me/piitex/app/views/models/ModelEditView.java @@ -43,6 +43,7 @@ public class ModelEditView extends EmptyContainer { private String mmProj = "None / Disabled"; private String chatTemplate = "default"; private String reasoningTemplate = "disabled"; + private boolean forceDisableReasoning = false; private boolean jinja = false; public ModelEditView(ModelSettings settings) { @@ -91,6 +92,7 @@ public ModelEditView(ModelSettings settings) { layout.addElement(buildDryPenaltyToken()); layout.addElement(buildChatTemplates()); layout.addElement(buildReasoningTemplate()); + layout.addElement(buildForceReasoning()); layout.addElement(buildJinjaTemplate()); page.addElement(buildSubmitBox()); @@ -687,6 +689,28 @@ private TileContainer buildReasoningTemplate() { return tileContainer; } + private TileContainer buildForceReasoning() { + TileContainer tileContainer = new TileContainer(0, 0); + tileContainer.addStyle(Styles.BORDER_DEFAULT); + tileContainer.addStyle(Styles.BG_DEFAULT); + tileContainer.addStyle(appSettings.getGlobalTextSize()); + tileContainer.setMaxSize(appSettings.getWidth() - 300, 150); + tileContainer.setTitle("Force Disable Reasoning"); + tileContainer.setDescription("Forcefully disables reasoning."); + + IconOverlay info = new IconOverlay(Material2AL.INFO); + info.setTooltip("Only enable if the reasoning is incompatible with llama.cpp."); + tileContainer.setGraphic(info); + + ToggleSwitchOverlay switchOverlay = new ToggleSwitchOverlay(forceDisableReasoning); + switchOverlay.onToggle(event -> { + this.forceDisableReasoning = event.getNewValue(); + }); + tileContainer.setAction(switchOverlay); + + return tileContainer; + } + private TileContainer buildJinjaTemplate() { TileContainer tileContainer = new TileContainer(0, 0); tileContainer.addStyle(Styles.BORDER_DEFAULT); @@ -751,6 +775,7 @@ public HorizontalLayout buildSubmitBox() { settings.setMmProj(mmProj); settings.setChatTemplate(chatTemplate); settings.setReasoningTemplate(reasoningTemplate); + settings.setForceDisableReasoning(forceDisableReasoning); settings.setJinja(jinja); settings.setChange(true); From 101dfe61b3c21c90f7738119c1d5ce6790b78313 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Wed, 13 May 2026 10:50:06 -0500 Subject: [PATCH 10/42] Added missing URISyntaxException. --- src/main/java/me/piitex/app/App.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index 5c1b3d43..80407cfd 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -41,6 +41,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URISyntaxException; import java.util.*; import java.util.List; @@ -399,7 +400,7 @@ public void performUpdates() { logger.info("Model list updated."); downloader.shutdown(); - } catch (IOException e) { + } catch (IOException | URISyntaxException e) { App.logger.error("Failed to fetch download size.", e); } From 64ae5f3fa79a084baa545f352f93e3f519db3e8e Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Thu, 14 May 2026 14:10:18 -0500 Subject: [PATCH 11/42] Added missing initial value for forceDisableReasoning. --- src/main/java/me/piitex/app/views/models/ModelEditView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/me/piitex/app/views/models/ModelEditView.java b/src/main/java/me/piitex/app/views/models/ModelEditView.java index ccbc4769..cf80e1ee 100644 --- a/src/main/java/me/piitex/app/views/models/ModelEditView.java +++ b/src/main/java/me/piitex/app/views/models/ModelEditView.java @@ -121,6 +121,7 @@ private void initializeSettings() { this.dryPenaltyTokens = settings.getDryPenaltyTokens(); this.chatTemplate = settings.getChatTemplate(); this.reasoningTemplate = settings.getReasoningTemplate(); + this.forceDisableReasoning = settings.isForceDisableReasoning(); this.jinja = settings.isJinja(); } From c0079c31df875db6922c0a2d48c514bd2fefaf50 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Thu, 14 May 2026 14:15:13 -0500 Subject: [PATCH 12/42] Fixed issues with new llama.cpp version where the server process would not hook start. --- src/main/java/me/piitex/app/backend/server/ServerProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index d2a34960..506e7394 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -315,7 +315,7 @@ protected void waitForServer() { process.destroy(); break; } - if (line.contains("starting the main loop")) { + if (line.contains("starting the main loop") || line.contains("main: model loaded")) { App.logger.info("Backend server stated!"); started = true; break; From 7327d178942949a7ccd1556c75073612c0a61655 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 12:24:28 -0500 Subject: [PATCH 13/42] Added process verification before killing it. --- src/main/java/me/piitex/app/App.java | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index 80407cfd..ae1ecd23 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -485,15 +485,19 @@ public Window buildErrorWindow(String message) { emptyContainer.addElement(kill); kill.onClick(event -> { App.logger.info("Killing old process."); - if (ProcessUtil.killProcess(Long.parseLong(settings.getInfoFile().get("main-pid")))) { - App.logger.info("Old process was destroyed gracefully."); - Platform.exit(); - System.exit(0); - } else { - App.logger.info("Forcefully killing old process."); - ProcessUtil.terminateProcess(Long.parseLong(settings.getInfoFile().get("main-pid"))); - } - + Optional handle = ProcessUtil.getRunningProcess(Long.parseLong(settings.getInfoFile().get("main-pid"))); + handle.ifPresent(processHandle -> { + if (processHandle.info().toString().contains("java.exe") || processHandle.info().toString().contains("javaw.exe") || processHandle.info().toString().contains("CCA.exe")) { + if (ProcessUtil.killProcess(Long.parseLong(settings.getInfoFile().get("main-pid")))) { + App.logger.info("Old process was destroyed gracefully."); + Platform.exit(); + System.exit(0); + } else { + App.logger.info("Forcefully killing old process."); + ProcessUtil.terminateProcess(Long.parseLong(settings.getInfoFile().get("main-pid"))); + } + } + }); appSettings.getInfoFile().set("main-pid", ""); }); From bbbd8eb2b4257bdcff601e820f92d44b232343a6 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 12:24:56 -0500 Subject: [PATCH 14/42] Finished implementation of chat importer and exporter. --- .../app/views/chats/ChatViewSidebar.java | 62 ++++++++++++++++++- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/piitex/app/views/chats/ChatViewSidebar.java b/src/main/java/me/piitex/app/views/chats/ChatViewSidebar.java index fa8c83d6..937ab754 100644 --- a/src/main/java/me/piitex/app/views/chats/ChatViewSidebar.java +++ b/src/main/java/me/piitex/app/views/chats/ChatViewSidebar.java @@ -5,10 +5,12 @@ import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.paint.Color; +import javafx.stage.FileChooser; import me.piitex.app.App; import me.piitex.app.backend.Character; import me.piitex.app.backend.Chat; import me.piitex.app.configuration.AppSettings; +import me.piitex.app.utils.ChatUtil; import me.piitex.app.views.HomeView; import me.piitex.app.views.LoadingView; import me.piitex.engine.containers.BorderContainer; @@ -20,6 +22,7 @@ import me.piitex.engine.overlays.*; import org.kordamp.ikonli.material2.Material2AL; +import javax.crypto.IllegalBlockSizeException; import java.io.File; import java.io.IOException; import java.nio.file.Files; @@ -31,6 +34,7 @@ public class ChatViewSidebar extends EmptyContainer { private final ChatView parent; private final VerticalLayout root; + private ChoiceBoxOverlay chatSelection; private static final AppSettings APP_SETTINGS = App.getInstance().getAppSettings(); @@ -100,16 +104,70 @@ private StackContainer buildCurrentChatSelection(Layout layout) { downloadIcon.setColor(Color.LIGHTBLUE); ButtonOverlay downloadChat = new ButtonBuilder("download").addStyle(Styles.FLAT).setIcon(downloadIcon).build(); downloadChat.setTooltip("Download Chat"); + downloadIcon.onClick(_ -> { + FileChooser chooser = new FileChooser(); + chooser.setTitle("Save Chat File"); + chooser.setInitialFileName(currentChat.getCurrentText() + ".dat"); + chooser.setSelectedExtensionFilter(new FileChooser.ExtensionFilter("Chat Message", ".dat")); + File file = chooser.showSaveDialog(App.window.getStage()); + + if (file.isDirectory()) return; + if (!file.getParentFile().exists()) return; + + // Now save the data inside the file. + try { + file.createNewFile(); + } catch (IOException e) { + App.logger.error("Could not create chat file!", e); + } + + try { + ChatUtil.exportChat(parent.getChat(), file); + } catch (IOException e) { + App.logger.error("Could not export chat file!", e); + } + }); IconOverlay importIcon = new IconOverlay(Material2AL.IMPORT_EXPORT); importIcon.setColor(Color.LIGHTYELLOW); ButtonOverlay importChat = new ButtonBuilder("import").addStyle(Styles.FLAT).setIcon(importIcon).build(); importChat.setTooltip("Import Chat"); + importChat.onClick(_ -> { + FileChooser chooser = new FileChooser(); + chooser.setTitle("Save Chat File"); + chooser.setSelectedExtensionFilter(new FileChooser.ExtensionFilter("Chat Message", ".dat")); + + File file = chooser.showOpenDialog(App.window.getStage()); + if (!file.exists() || file.isDirectory()) return; + + try { + ChatUtil.importChat(parent.getCharacter(), file); + App.logger.info("Imported Chat: '{}'", file.getAbsolutePath()); + + Chat chat = parent.getCharacter().getChat("import-" + file.getName()); + parent.getCharacter().setLastChat(chat); + App.window.clearContainers(); + EmptyContainer progressContainer = new EmptyContainer(APP_SETTINGS.getWidth(), APP_SETTINGS.getHeight()); + progressContainer.addElement(new LoadingView("Loading chat...", progressContainer.getWidth(), progressContainer.getHeight())); + App.window.addContainer(progressContainer); + + App.getThreadPoolManager().submitTask(() -> { + ChatView chatView = new ChatView(parent.getCharacter(), chat); + Node assemble = chatView.assemble(); + Platform.runLater(() -> { + App.window.clearContainers(); + App.window.addContainer(chatView, assemble); + }); + }); + } catch (IOException | IllegalBlockSizeException e) { + App.logger.error("Could not import chat file!", e); + } + }); IconOverlay renameIcon = new IconOverlay(Material2AL.EDIT); renameIcon.setColor(Color.LIGHTGREEN); ButtonOverlay renameChat = new ButtonBuilder("rename").addStyle(Styles.FLAT).setIcon(renameIcon).build(); - renameChat.setTooltip("Rename Chat"); + renameChat.setTooltip("Enter the new name in the text box. Press this button to apply."); renameIcon.onClick(_ -> { Character character = parent.getCharacter(); Chat chat = parent.getChat(); @@ -154,7 +212,7 @@ private StackContainer buildCurrentChatSelection(Layout layout) { chats.add(chat.getFile().getName()); } - ChoiceBoxOverlay chatSelection = new ChoiceBoxOverlay(chats); + chatSelection = new ChoiceBoxOverlay(chats); chatSelection.setWidth(layout.getWidth()); chatSelection.setDefaultItem(parent.getChat().getFile().getName()); layout.addElement(chatSelection); From be4ce411c6c09805566df917225276113c8da322 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 12:37:30 -0500 Subject: [PATCH 15/42] Removed old User creator. --- .../piitex/app/views/creator/CreatorView.java | 1 - .../piitex/app/views/users/UserEditView.java | 227 ---------------- .../me/piitex/app/views/users/UsersView.java | 254 ------------------ .../app/views/users/tabs/UserLoreBookTab.java | 134 --------- .../piitex/app/views/users/tabs/UserTab.java | 209 -------------- 5 files changed, 825 deletions(-) delete mode 100644 src/main/java/me/piitex/app/views/users/UserEditView.java delete mode 100644 src/main/java/me/piitex/app/views/users/UsersView.java delete mode 100644 src/main/java/me/piitex/app/views/users/tabs/UserLoreBookTab.java delete mode 100644 src/main/java/me/piitex/app/views/users/tabs/UserTab.java diff --git a/src/main/java/me/piitex/app/views/creator/CreatorView.java b/src/main/java/me/piitex/app/views/creator/CreatorView.java index 24111192..02ecaff0 100644 --- a/src/main/java/me/piitex/app/views/creator/CreatorView.java +++ b/src/main/java/me/piitex/app/views/creator/CreatorView.java @@ -10,7 +10,6 @@ import me.piitex.app.views.SidebarView; import me.piitex.app.views.creator.characters.CharacterCreator; import me.piitex.app.views.creator.users.UserCreator; -import me.piitex.app.views.users.UsersView; import me.piitex.engine.containers.EmptyContainer; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; diff --git a/src/main/java/me/piitex/app/views/users/UserEditView.java b/src/main/java/me/piitex/app/views/users/UserEditView.java deleted file mode 100644 index f49bb7aa..00000000 --- a/src/main/java/me/piitex/app/views/users/UserEditView.java +++ /dev/null @@ -1,227 +0,0 @@ -package me.piitex.app.views.users; - -import atlantafx.base.theme.Styles; -import javafx.geometry.Pos; -import javafx.scene.control.TextField; -import me.piitex.app.App; -import me.piitex.app.backend.User; -import me.piitex.app.configuration.AppSettings; -import me.piitex.app.views.SidebarView; -import me.piitex.app.views.users.tabs.UserLoreBookTab; -import me.piitex.app.views.users.tabs.UserTab; -import me.piitex.engine.PopupPosition; -import me.piitex.engine.containers.DialogueContainer; -import me.piitex.engine.containers.EmptyContainer; -import me.piitex.engine.containers.tabs.TabsContainer; -import me.piitex.engine.layouts.HorizontalLayout; -import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.overlays.ButtonBuilder; -import me.piitex.engine.overlays.ButtonOverlay; -import me.piitex.engine.overlays.MessageOverlay; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.StandardCopyOption; -import java.util.TreeMap; - -public class UserEditView extends EmptyContainer { - private User user; - private String userId = ""; - private String userDisplay = ""; - private String userPersona = ""; - private File userIconPath; - - // Lore Map - private TreeMap loreBook; - - private TabsContainer tabsContainer; - private UserTab userTab; - private UserLoreBookTab userLoreBookTab; - - private static final AppSettings appSettings = App.getInstance().getAppSettings(); - - public UserEditView() { - super(appSettings.getWidth(), appSettings.getHeight()); - this.loreBook = new TreeMap<>(); - init(); - } - - public UserEditView(User user) { - super(appSettings.getWidth(), appSettings.getHeight()); - this.user = user; - this.userId = user.getId(); - this.userDisplay = user.getDisplayName(); - this.userPersona = user.getPersona(); - this.userIconPath = new File(user.getIconPath()); - this.loreBook = user.getLorebook(); - init(); - } - - public void init() { - addStyle(Styles.BG_INSET); - - HorizontalLayout root = new HorizontalLayout(getWidth(), getHeight()); - root.setMaxSize(root.getWidth(), root.getHeight()); - addElement(root); - - SidebarView sidebarView = new SidebarView(); - root.addElement(sidebarView); - - VerticalLayout mainPage = new VerticalLayout(appSettings.getWidth() - 200, 0); - mainPage.setMaxSize(mainPage.getWidth(), mainPage.getHeight()); - root.addElement(mainPage); - - tabsContainer = new TabsContainer(0, 0, mainPage.getWidth(), appSettings.getHeight()); - mainPage.addElement(tabsContainer); - - userTab = new UserTab("User", this); - tabsContainer.addTab(userTab); - - userLoreBookTab = new UserLoreBookTab("Lorebook", this); - tabsContainer.addTab(userLoreBookTab); - } - - public HorizontalLayout buildSubmitBox() { - HorizontalLayout layout = new HorizontalLayout(appSettings.getWidth() - 300, 50); - layout.setY(appSettings.getHeight() - 150); - layout.setSpacing(20); - layout.setAlignment(Pos.CENTER); - - ButtonOverlay cancel = new ButtonBuilder("cancel").setText("Cancel").build(); - cancel.addStyle(Styles.DANGER); - cancel.addStyle(Styles.BUTTON_OUTLINED); - layout.addElement(cancel); - - ButtonOverlay submit = new ButtonBuilder("submit").setText("Submit").build(); - submit.addStyle(Styles.SUCCESS); - submit.addStyle(Styles.BUTTON_OUTLINED); - layout.addElements(submit); - - cancel.onClick(event -> { - DialogueContainer dialogueContainer = new DialogueContainer("Do you want to exit without saving?", 500, 500); - - ButtonOverlay stay = new ButtonBuilder("stay").setText("Stay").build(); - stay.setWidth(150); - stay.addStyle(Styles.SUCCESS); - stay.onClick(_ -> App.window.removeContainer(dialogueContainer)); - - ButtonOverlay leave = new ButtonBuilder("leave").setText("Leave").build(); - leave.setWidth(150); - leave.addStyle(Styles.DANGER); - leave.onClick(_ -> { - App.window.clearContainers(); - App.window.addContainer(new UsersView()); - }); - - dialogueContainer.setCancelButton(stay); - dialogueContainer.setConfirmButton(leave); - - App.window.renderPopup(dialogueContainer, event.getHandler().getSceneX(), event.getHandler().getSceneY() - 100, 500, 500); - }); - - submit.onClick(event -> { - if (!validate()) { - return; - } - - if (user == null) { - user = new User(userId); - } - user.setDisplayName(userDisplay); - user.setPersona(userPersona); - user.setLorebook(loreBook); - if (userIconPath == null || !userIconPath.exists()) { - userIconPath = new File(App.getAppDirectory(), "icons/character.png"); - } - try { - File output = new File(user.getUserDirectory(), "user.png"); - Files.copy(userIconPath.toPath(), output.toPath(), StandardCopyOption.REPLACE_EXISTING); - user.setIconPath(output.getAbsolutePath()); - } catch (IOException e) { - App.logger.error("Failed to move image to user.", e); - } - - App.getInstance().getUserTemplates().putIfAbsent(userId, user); - - App.window.clearContainers(); - App.window.addContainer(new UsersView()); - }); - - return layout; - } - - public boolean validate() { - if (userId.isEmpty() || ((TextField) userTab.getUserIdInput().getNode()).getText().isEmpty()) { - tabsContainer.getTabPane().getSelectionModel().select(userTab.getJfxTab()); - MessageOverlay required = new MessageOverlay(0, 0, 600, 100, "User ID", "ID is required."); - required.addStyle(Styles.WARNING); - required.addStyle(Styles.BG_DEFAULT); - App.window.renderPopup(required, PopupPosition.CENTER, 600, 100, true); - userTab.getUserIdInput().getNode().requestFocus(); - return false; - } else if (userDisplay.isEmpty() || ((TextField) userTab.getUserDisplayNameInput().getNode()).getText().isEmpty()) { - tabsContainer.getTabPane().getSelectionModel().select(userTab.getJfxTab()); - MessageOverlay required = new MessageOverlay(0, 0, 600, 100, "Display Name", "Display name is required."); - required.addStyle(Styles.WARNING); - required.addStyle(Styles.BG_DEFAULT); - App.window.renderPopup(required, PopupPosition.CENTER, 600, 100, true); - userTab.getUserIdInput().getNode().requestFocus(); - return false; - } else { - return true; - } - } - - public UserTab getUserTab() { - return userTab; - } - - public UserLoreBookTab getUserLoreBookTab() { - return userLoreBookTab; - } - - public User getUser() { - return user; - } - - public String getUserId() { - return userId; - } - - public File getUserIconPath() { - return userIconPath; - } - - public String getUserDisplay() { - return userDisplay; - } - - public String getUserPersona() { - return userPersona; - } - - public TreeMap getLoreBook() { - return loreBook; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - public void setUserDisplay(String userDisplay) { - this.userDisplay = userDisplay; - } - - public void setUserPersona(String userPersona) { - this.userPersona = userPersona; - } - - public void setUserIconPath(File userIconPath) { - this.userIconPath = userIconPath; - } - - public void setLoreBook(TreeMap loreBook) { - this.loreBook = loreBook; - } -} diff --git a/src/main/java/me/piitex/app/views/users/UsersView.java b/src/main/java/me/piitex/app/views/users/UsersView.java deleted file mode 100644 index af780630..00000000 --- a/src/main/java/me/piitex/app/views/users/UsersView.java +++ /dev/null @@ -1,254 +0,0 @@ -package me.piitex.app.views.users; - -import atlantafx.base.theme.Styles; -import javafx.application.Platform; -import javafx.geometry.Pos; -import javafx.scene.Node; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.MenuItem; -import javafx.scene.paint.Color; -import me.piitex.app.App; -import me.piitex.app.backend.User; -import me.piitex.app.configuration.AppSettings; -import me.piitex.app.views.LoadingView; -import me.piitex.app.views.SidebarView; -import me.piitex.engine.containers.Container; -import me.piitex.engine.containers.CardContainer; -import me.piitex.engine.containers.DialogueContainer; -import me.piitex.engine.containers.EmptyContainer; -import me.piitex.engine.containers.ScrollContainer; -import me.piitex.engine.layouts.FlowLayout; -import me.piitex.engine.layouts.HorizontalLayout; -import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.overlays.*; -import org.apache.commons.io.FileUtils; -import org.kordamp.ikonli.material2.Material2AL; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; - -public class UsersView extends EmptyContainer { - private static final AppSettings appSettings = App.getInstance().getAppSettings(); - private final VerticalLayout mainPage; - - public UsersView() { - super(appSettings.getWidth(), appSettings.getHeight()); - addStyle(Styles.BG_INSET); - HorizontalLayout root = new HorizontalLayout(getWidth(), getHeight()); - root.setMaxSize(root.getWidth(), root.getHeight()); - addElement(root); - - SidebarView sidebarView = new SidebarView(); - root.addElement(sidebarView); - - mainPage = new VerticalLayout(appSettings.getWidth() - 200, 0); - mainPage.setMaxSize(mainPage.getWidth(), mainPage.getHeight()); - root.addElement(mainPage); - - init(); - } - - public void init() { - VerticalLayout header = new VerticalLayout(appSettings.getWidth() - 200, 100); - header.addStyle(Styles.BG_DEFAULT); - header.setMaxSize(header.getWidth(), header.getHeight()); - header.setAlignment(Pos.CENTER); - mainPage.addElement(header); - - ButtonOverlay newUser = new ButtonBuilder("new").setText("New User").build(); - newUser.addStyle(Styles.SUCCESS); - newUser.addStyle(Styles.BUTTON_OUTLINED); - newUser.onClick(_ -> { - App.window.clearContainers(); - App.window.addContainer(new UserEditView()); - }); - header.addElement(newUser); - - buildFlowLayout(); - } - - public void buildFlowLayout() { - VerticalLayout flowRoot = new VerticalLayout(appSettings.getWidth() - 200, 0); - - ScrollContainer base = new ScrollContainer(flowRoot, 10, 10, mainPage.getMaxWidth(), -1); - base.setMaxSize(base.getWidth(), base.getHeight()); - - FlowLayout flowLayout = new FlowLayout(appSettings.getWidth() - 200, 0); - flowLayout.setX(10); - flowLayout.setMaxSize(flowLayout.getWidth(), flowLayout.getHeight()); - mainPage.addElement(flowLayout); - flowLayout.addStyle(Styles.BORDER_DEFAULT); - - for (User user : App.getInstance().getUserTemplates().values()) { - CardContainer card = new CardContainer(0,0, 280, 380); - card.setMaxSize(card.getWidth(), card.getHeight()); - - VerticalLayout displayBox = new VerticalLayout(0, 330); - displayBox.setSpacing(15); - displayBox.setAlignment(Pos.TOP_CENTER); - - TextOverlay id = new TextOverlay(user.getId()); - displayBox.addElement(id); - - - ContextMenu contextMenu = new ContextMenu(); - - MenuItem edit = new MenuItem("Edit"); - edit.setOnAction(_ -> editUser(user)); - MenuItem copy = new MenuItem("Copy"); - copy.setOnAction(_ -> duplicateUser(user)); - MenuItem delete = new MenuItem("Delete"); - delete.setOnAction(_ -> deleteUser(user, flowLayout, card)); - - contextMenu.getItems().add(edit); - contextMenu.getItems().add(copy); - contextMenu.getItems().add(delete); - - ImageOverlay icon = User.getUserAvatar(user.getIconPath(), 256, 256); - if (icon != null && icon.getImage() != null) { - icon.setPreserveRatio(false); - displayBox.addElement(icon); - } - - TextOverlay name = new TextOverlay(user.getDisplayName()); - displayBox.addElement(name); - - card.setBody(displayBox); - - card.setFooter(buildControlBox(flowLayout, card, user)); - - flowLayout.addElement(card); - } - } - - public HorizontalLayout buildControlBox(FlowLayout base, CardContainer card, User user) { - HorizontalLayout root = new HorizontalLayout(200, 25); - root.setIndex(10); - root.setSpacing(20); - if (!App.mobile) { - root.setAlignment(Pos.BASELINE_CENTER); - } - - IconOverlay edit = new IconOverlay(Material2AL.EDIT); - edit.setTooltip("Edit the user"); - edit.setColor(Color.GREEN); - edit.onClick(event -> { - editUser(user); - }); - root.addElement(edit); - - IconOverlay duplicate = new IconOverlay(Material2AL.FILE_COPY); - duplicate.setTooltip("Duplicate the user."); - duplicate.setColor(Color.YELLOW); - duplicate.onClick(event -> { - duplicateUser(user); - }); - root.addElement(duplicate); - - IconOverlay delete = new IconOverlay(Material2AL.DELETE_FOREVER); - delete.setColor(Color.RED); - delete.setTooltip("Delete the user."); - delete.onClick(event -> { - deleteUser(base, card, user, event.getHandler().getSceneX(), event.getHandler().getSceneY()); - }); - root.addElement(delete); - return root; - } - - private void editUser(User user) { - App.window.clearContainers(); - EmptyContainer progressContainer = new EmptyContainer(App.getInstance().getAppSettings().getWidth(), App.getInstance().getAppSettings().getHeight()); - progressContainer.addElement(new LoadingView("Loading User data...", progressContainer.getWidth(), progressContainer.getHeight())); - App.window.addContainer(progressContainer); - - App.getThreadPoolManager().submitTask(() -> { - Container container = new UserEditView(user); - Node assemble = container.assemble(); - Platform.runLater(() -> { - App.window.clearContainers(); - App.window.addContainer(container, assemble); - }); - }); - } - - private void duplicateUser(User user) { - // Duplicate the User. - String newId = user.getId() + " (copy)"; - while (App.getInstance().getUser(newId) != null) { - newId += " (copy)"; - } - - // Edit the User in the edit view rather than duplicating the files - // Allow the id to be edited and changed. - - // Create a copy of the User. - App.window.clearContainers(); - EmptyContainer progressContainer = new EmptyContainer(App.getInstance().getAppSettings().getWidth(), App.getInstance().getAppSettings().getHeight()); - progressContainer.addElement(new LoadingView("Loading User data...", progressContainer.getWidth(), progressContainer.getHeight())); - App.window.addContainer(progressContainer); - - User duplicated = new User(newId, null); - App.getThreadPoolManager().submitTask(() -> { - duplicated.copy(user); - UserEditView editView = new UserEditView(duplicated); - Node assemble = editView.assemble(); - Platform.runLater(() -> { - App.window.clearContainers(); - App.window.addContainer(editView, assemble); - }); - }); - } - - private void deleteUser(FlowLayout base, CardContainer card, User user, double x, double y) { - DialogueContainer dialogueContainer = new DialogueContainer("Delete '" + user.getId() + "'?", 500, 500); - - ButtonOverlay cancel = new ButtonBuilder("cancel").setText("Keep").build(); - cancel.setWidth(150); - cancel.addStyle(Styles.SUCCESS); - cancel.onClick(_ -> { - App.window.removeContainer(dialogueContainer); - }); - - ButtonOverlay confirm = new ButtonBuilder("confirm").setText("Delete").build(); - confirm.setWidth(150); - confirm.addStyle(Styles.DANGER); - confirm.onClick(_ -> { - App.getInstance().getUserTemplates().remove(user.getId()); - App.window.removeContainer(dialogueContainer); - - // Cleanup image usage - VerticalLayout verticalLayout = (VerticalLayout) card.getBody(); - ImageOverlay imageOverlay = (ImageOverlay) verticalLayout.getElementAt(1); - - // When setting to null the engine will dispose of the image and the JVM will call gc. - imageOverlay.setImage(null); - - deleteUserDirectory(user); - base.removeElement(card); - }); - - dialogueContainer.setCancelButton(cancel); - dialogueContainer.setConfirmButton(confirm); - - // Render this on top - App.window.renderPopup(dialogueContainer, x, y, 500, 500); - } - - private void deleteUser(User user, FlowLayout base, CardContainer card) { - App.getInstance().getUserTemplates().remove(user.getId()); - deleteUserDirectory(user); - base.removeElement(card); - } - - private void deleteUserDirectory(User user) { - // Add a delay to ensure all io operations are completed. - App.getThreadPoolManager().submitSchedule(() -> { - App.logger.info("Deleting User: {}", user.getId()); - try { - FileUtils.deleteDirectory(user.getUserDirectory()); - } catch (IOException e) { - App.logger.error("Could not delete directory!", e); - } - }, 1, TimeUnit.SECONDS); - } -} diff --git a/src/main/java/me/piitex/app/views/users/tabs/UserLoreBookTab.java b/src/main/java/me/piitex/app/views/users/tabs/UserLoreBookTab.java deleted file mode 100644 index 7e0afe72..00000000 --- a/src/main/java/me/piitex/app/views/users/tabs/UserLoreBookTab.java +++ /dev/null @@ -1,134 +0,0 @@ -package me.piitex.app.views.users.tabs; - -import atlantafx.base.theme.Styles; -import javafx.geometry.Pos; -import me.piitex.app.App; -import me.piitex.app.configuration.AppSettings; -import me.piitex.app.views.users.UserEditView; -import me.piitex.engine.containers.CardContainer; -import me.piitex.engine.containers.ScrollContainer; -import me.piitex.engine.containers.tabs.Tab; -import me.piitex.engine.layouts.HorizontalLayout; -import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.overlays.*; -import org.kordamp.ikonli.javafx.FontIcon; -import org.kordamp.ikonli.material2.Material2AL; - -import java.util.Map; - -public class UserLoreBookTab extends Tab { - private final UserEditView userEditView; - private TextFieldOverlay addKeyInput; - private TextAreaOverlay addValueInput; - private ScrollContainer scrollLoreContainer; - - private static final AppSettings appSettings = App.getInstance().getAppSettings(); - - public UserLoreBookTab(String text, UserEditView userEditView) { - super(text); - this.userEditView = userEditView; - buildLorebookTabContent(); - } - - public void buildLorebookTabContent() { - removeAllElements(); - - VerticalLayout rootLayout = new VerticalLayout(appSettings.getWidth() - 300, appSettings.getHeight()); - rootLayout.setSpacing(50); - rootLayout.setAlignment(Pos.TOP_CENTER); - this.addElement(rootLayout); - - IconOverlay info = new IconOverlay(Material2AL.INFO); - info.setTooltip("Use the following placeholders; {char}, {{char}}, {chara}, {{chara}}, {character}, {{character}}, {user}, {{user}}, {usr}, {{usr}}"); - rootLayout.addElement(info); - - HorizontalLayout displayBox = new HorizontalLayout(0, -1); - displayBox.setAlignment(Pos.TOP_CENTER); - displayBox.setSpacing(100); - rootLayout.addElement(displayBox); - - CardContainer addContainer = new CardContainer(0, 0, 400, 400); - addContainer.setMaxSize(400, 400); - - addKeyInput = new TextFieldOverlay("", "Separate multiple keys with a comma (,)", 0, 0, 200, 50); - addContainer.setHeader(addKeyInput); - - addValueInput = new TextAreaOverlay("", "Enter the lore info", 0, 0, 400, 200); - addContainer.setBody(addValueInput); - - HorizontalLayout buttonBox = new HorizontalLayout(200, 50); - buttonBox.setAlignment(Pos.CENTER); - - ButtonOverlay add = new ButtonBuilder("add").setText("Add").build(); - add.addStyle(Styles.SUCCESS); - add.addStyle(Styles.BUTTON_OUTLINED); - buttonBox.addElement(add); - addContainer.setFooter(buttonBox); - - scrollLoreContainer = getLoreItems(); - add.onClick(_ -> { - String keyText = addKeyInput.getCurrentText(); - String valueText = addValueInput.getCurrentText(); - - if (keyText.isEmpty() || valueText.isEmpty()) { - return; - } - - userEditView.getLoreBook().put(keyText, valueText); - - VerticalLayout scrollLayout = (VerticalLayout) scrollLoreContainer.getLayout(); - CardContainer newLoreEntryCard = buildLoreEntry(keyText, scrollLayout); - scrollLayout.addElement(newLoreEntryCard); - - addKeyInput.setCurrentText(""); - addValueInput.setCurrentText(""); - }); - - displayBox.addElement(addContainer); - displayBox.addElement(scrollLoreContainer); - - this.addElement(userEditView.buildSubmitBox()); - } - - private ScrollContainer getLoreItems() { - VerticalLayout scrollLayout = new VerticalLayout(0, -1); - - ScrollContainer root = new ScrollContainer(scrollLayout, 0, 0, 450, appSettings.getHeight() - 300); - root.setMaxSize(450, appSettings.getHeight() - 300); - root.setVerticalScroll(true); - root.setScrollWhenNeeded(false); - root.setHorizontalScroll(false); - root.setPannable(true); - - App.logger.info("Building lore cache..."); - for (Map.Entry entry : userEditView.getLoreBook().entrySet()) { - scrollLayout.addElement(buildLoreEntry(entry.getKey(), scrollLayout)); - } - return root; - } - - private CardContainer buildLoreEntry(String key, VerticalLayout scrollContainer) { - CardContainer card = new CardContainer(0, 0, 400, 300); - - TextFieldOverlay entryKey = new TextFieldOverlay(key, 0, 0, 400, 50); - entryKey.setEnabled(false); // Make key read-only - card.setHeader(entryKey); - - TextAreaOverlay entryValue = new TextAreaOverlay(userEditView.getLoreBook().get(key), "", 400, 200); - entryValue.onInputSetEvent(event -> userEditView.getLoreBook().put(key, event.getInput())); - card.setBody(entryValue); - - ButtonOverlay remove = new ButtonBuilder("remove").setText("Remove").build(); - remove.setX(170); - remove.addStyle(Styles.DANGER); - remove.addStyle(Styles.BUTTON_OUTLINED); - card.setFooter(remove); - - remove.onClick(_ -> { - userEditView.getLoreBook().remove(key); - scrollContainer.removeElement(card); - }); - - return card; - } -} diff --git a/src/main/java/me/piitex/app/views/users/tabs/UserTab.java b/src/main/java/me/piitex/app/views/users/tabs/UserTab.java deleted file mode 100644 index 62c577c8..00000000 --- a/src/main/java/me/piitex/app/views/users/tabs/UserTab.java +++ /dev/null @@ -1,209 +0,0 @@ -package me.piitex.app.views.users.tabs; - -import atlantafx.base.theme.Styles; -import com.drew.imaging.ImageProcessingException; -import javafx.application.Platform; -import javafx.geometry.Pos; -import javafx.stage.FileChooser; -import me.piitex.app.App; -import me.piitex.app.configuration.AppSettings; -import me.piitex.app.utils.UserCardImporter; -import me.piitex.app.views.users.UserEditView; -import me.piitex.engine.containers.CardContainer; -import me.piitex.engine.containers.ScrollContainer; -import me.piitex.engine.containers.tabs.Tab; -import me.piitex.engine.layouts.HorizontalLayout; -import me.piitex.engine.layouts.VerticalLayout; -import me.piitex.engine.loaders.image.BaseImageLoader; -import me.piitex.engine.loaders.image.ImageLoader; -import me.piitex.engine.overlays.*; -import org.json.JSONObject; - -import java.io.File; -import java.io.IOException; - -public class UserTab extends Tab { - private final UserEditView userEditView; - - private TextFieldOverlay userIdInput; - private TextFieldOverlay userDisplayNameInput; - private RichTextAreaOverlay userDescription; - - private ImageOverlay image; - - private static final AppSettings appSettings = App.getInstance().getAppSettings(); - - public UserTab(String text, UserEditView userEditView) { - super(text); - this.userEditView = userEditView; - init(); - } - - public void init() { - VerticalLayout rootLayout = new VerticalLayout(appSettings.getWidth() - 315, 0); - rootLayout.setSpacing(40); - rootLayout.setAlignment(Pos.TOP_CENTER); - - ScrollContainer scrollContainer = new ScrollContainer(rootLayout, 0, 0, appSettings.getWidth() - 300, appSettings.getHeight() - 200); - scrollContainer.setMaxSize(scrollContainer.getWidth(), scrollContainer.getHeight()); - scrollContainer.setHorizontalScroll(false); - scrollContainer.setPannable(true); - addElement(scrollContainer); - - HorizontalLayout displayBox = new HorizontalLayout(600, 320); - displayBox.setMaxSize(600, 320); - displayBox.addStyle(Styles.BORDER_SUBTLE); - displayBox.setSpacing(20); - rootLayout.addElement(displayBox); - - CardContainer displayCard = buildUserDisplay(); - displayBox.addElement(displayCard); - displayBox.addElement(buildUserInput()); - - double scaleFactor = (double) appSettings.getWidth() / 1920.0; - userDescription = new RichTextAreaOverlay(userEditView.getUserPersona(), 600, 400 * scaleFactor); - userDescription.setBackgroundColor(appSettings.getThemeDefaultColor(appSettings.getTheme())); - userDescription.setBorderColor(appSettings.getThemeBorderColor(appSettings.getTheme())); - userDescription.setTextFill(appSettings.getThemeTextColor(appSettings.getTheme())); - userDescription.setMaxHeight(400 * scaleFactor); - userDescription.setMaxWidth(600); - userDescription.onInputSetEvent(event -> { - userEditView.setUserPersona(event.getInput()); - }); - userDescription.addStyle(Styles.BG_DEFAULT); - userDescription.addStyle(appSettings.getChatTextSize()); - userDescription.addStyle(Styles.TEXT_ON_EMPHASIS); - - rootLayout.addElement(userDescription); - - addElement(userEditView.buildSubmitBox()); - } - - private CardContainer buildUserDisplay() { - CardContainer root = new CardContainer(0, 0, 300, 320); - - VerticalLayout layout = new VerticalLayout(300, 320); - root.setBody(layout); - layout.setAlignment(Pos.TOP_CENTER); - layout.setSpacing(25); - - // Use parentView's userIconPath - File currentIconPath = userEditView.getUserIconPath(); - if (currentIconPath == null || !currentIconPath.exists() || currentIconPath.isDirectory()) { - currentIconPath = new File(App.getAppDirectory(), "icons/character.png"); - } - - ImageLoader loader = new BaseImageLoader(currentIconPath); - loader.setWidth(256); - loader.setHeight(256); - - image = new ImageOverlay(loader); - image.setFitWidth(256); - image.setFitHeight(256); - image.setPreserveRatio(false); - - layout.addElement(image); - - TextOverlay upload = new TextOverlay("Click to upload image"); - upload.setTextFill(javafx.scene.paint.Color.WHITE); - upload.setUnderline(true); - layout.addElement(upload); - - root.onClick(event -> { - FileChooser chooser = new FileChooser(); - chooser.getExtensionFilters().add(new FileChooser.ExtensionFilter("Select an image.", "*.img", "*.png", "*.webp", "*.jpg", "*.gif")); - if (appSettings.getImagesPath() != null && !appSettings.getImagesPath().isEmpty()) { - chooser.setInitialDirectory(new File(appSettings.getImagesPath())); - } - File selectedFile = chooser.showOpenDialog(App.window.getStage()); - if (selectedFile != null) { - userEditView.setUserIconPath(selectedFile); - appSettings.setImagesPath(selectedFile.getParent()); - userEditView.setUserIconPath(selectedFile.getAbsoluteFile()); - - ImageLoader imageLoader = new BaseImageLoader(selectedFile); - imageLoader.setWidth(256); - imageLoader.setHeight(256); - - image.setImage(imageLoader); - } - }); - - return root; - } - - private VerticalLayout buildUserInput() { - VerticalLayout root = new VerticalLayout(250, 150); - root.setAlignment(Pos.BASELINE_CENTER); - root.setMaxSize(250, 200); - root.setSpacing(10); - - userIdInput = new TextFieldOverlay(userEditView.getUserId(), 0, 0, 200, 50); - userIdInput.setEnabled(true); - userIdInput.setHintText("Unique Identifier"); - userIdInput.onInputSetEvent(event -> { - userEditView.setUserId(event.getInput()); - }); - if (userEditView.getUser() != null) { - userIdInput.setEnabled(false); - } - root.addElement(userIdInput); - - userDisplayNameInput = new TextFieldOverlay(userEditView.getUserDisplay(), 0, 0, 200, 50); - userDisplayNameInput.setEnabled(true); - userDisplayNameInput.setHintText("Display Name"); - userDisplayNameInput.onInputSetEvent(event -> { - userEditView.setUserDisplay(event.getInput()); - }); - root.addElement(userDisplayNameInput); - - ButtonOverlay importCard = new ButtonBuilder("import").setText("Import Character Card").build(); - if (userEditView.getUser() != null) { - importCard.setEnabled(false); - } - importCard.addStyle(Styles.ACCENT); - importCard.addStyle(Styles.BUTTON_OUTLINED); - importCard.setWidth(200); - importCard.setHeight(50); - - FileChooserOverlay fileSelector = new FileChooserOverlay(App.window, importCard); - root.addElement(fileSelector); - fileSelector.onFileSelect(event -> { - File file = event.getDirectory(); - try { - JSONObject metadata = UserCardImporter.getImageMetaData(file); - userDisplayNameInput.setCurrentText(UserCardImporter.getUserDisplay(metadata)); - userDescription.setCurrentText(UserCardImporter.getUserPersona(metadata)); - - userEditView.getLoreBook().clear(); - userEditView.getLoreBook().putAll(UserCardImporter.getLoreItems(metadata)); - userEditView.getUserLoreBookTab().buildLorebookTabContent(); - - userEditView.setUserIconPath(file); - image.setImage(new BaseImageLoader(file)); - } catch (ImageProcessingException | IOException e) { - App.logger.error("Error importing character card: ", e); - Platform.runLater(() -> { - MessageOverlay errorOverlay = new MessageOverlay(0, 0, 500, 50, "Import Failed", "Could not import character card: " + e.getMessage()); - errorOverlay.addStyle(Styles.DANGER); - errorOverlay.addStyle(Styles.BG_DEFAULT); - App.window.renderPopup(errorOverlay, 650, 870, 500, 50, false, null); - }); - } - }); - - return root; - } - - public TextFieldOverlay getUserIdInput() { - return userIdInput; - } - - public TextFieldOverlay getUserDisplayNameInput() { - return userDisplayNameInput; - } - - public RichTextAreaOverlay getUserDescription() { - return userDescription; - } -} From 580bc8974775ac6819a0c9a7a3ac4f2b4b203b05 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 12:37:54 -0500 Subject: [PATCH 16/42] Fixed display issues for user templates. --- .../java/me/piitex/app/views/users/UserTemplateView.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/me/piitex/app/views/users/UserTemplateView.java b/src/main/java/me/piitex/app/views/users/UserTemplateView.java index 808ba7bf..2355affa 100644 --- a/src/main/java/me/piitex/app/views/users/UserTemplateView.java +++ b/src/main/java/me/piitex/app/views/users/UserTemplateView.java @@ -102,7 +102,7 @@ public void buildUsers() { imageWidth = 256; imageHeight = 256; cardWidth = 280; - cardHeight = 380; + cardHeight = 350; } body.setScrollWhenNeeded(false); body.setHorizontalScroll(false); @@ -119,16 +119,11 @@ public void buildUsers() { CardContainer card = new CardContainer(0,0, cardWidth, cardHeight); card.setMaxSize(cardWidth, cardHeight); - VerticalLayout displayBox = new VerticalLayout(0, 330); + VerticalLayout displayBox = new VerticalLayout(0, cardHeight - 50); displayBox.setSpacing(15); displayBox.setAlignment(Pos.TOP_CENTER); - TextOverlay helper = new TextOverlay("Click to chat"); - helper.setUnderline(true); - displayBox.addElement(helper); - ContextMenu contextMenu = new ContextMenu(); - MenuItem edit = new MenuItem("Edit"); edit.setOnAction(_ -> editUser(user)); MenuItem copy = new MenuItem("Copy"); From 697a011f7f93c3fe22eb8b3c2c63a91a51c6766f Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 12:39:15 -0500 Subject: [PATCH 17/42] Removed debugger line. --- src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java index c2172b6c..bbc822fd 100644 --- a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java +++ b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java @@ -66,7 +66,6 @@ public synchronized boolean isUpdateAvailable() { if (current != null && latest != null) { return current.compareTo(latest) < 0; } - System.out.println("False"); return false; } From 3f1f4243b912803c9ef5b27aa6f0409bc1689a10 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 13:11:34 -0500 Subject: [PATCH 18/42] Fixed issues where global memory wouldn't be set. --- .../java/me/piitex/app/backend/server/ServerProcess.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 506e7394..7ec49dca 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -186,13 +186,16 @@ private LinkedList getParameters(File server, ServerSettings settings) { SystemInfo systemInfo = new SystemInfo(); HardwareAbstractionLayer hardwareAbstractionLayer = systemInfo.getHardware(); GraphicsCard graphicsCard = hardwareAbstractionLayer.getGraphicsCards().getFirst(); - if (graphicsCard != null) { + if (graphicsCard != null && graphicsCard.getVRam() > 0) { + App.logger.info("Using GPU memory..."); TOTAL_AVAILABLE_VRAM_MIB = graphicsCard.getVRam() / (1024.0 * 1024.0); - App.getInstance().getAppSettings().setTotalGpuVram(TOTAL_AVAILABLE_VRAM_MIB); } else { App.logger.error("Could not find dedicated GPU. Using global memory pool..."); TOTAL_AVAILABLE_VRAM_MIB = systemInfo.getHardware().getMemory().getTotal() / (1024.0 * 1024.0); + App.logger.info("VRAM: {} MiB", TOTAL_AVAILABLE_VRAM_MIB); } + + App.getInstance().getAppSettings().setTotalGpuVram(TOTAL_AVAILABLE_VRAM_MIB); } double KV_CACHE = model.getSettings().getKvCacheSize(); From a85c80c99ab90be5d165128eeb6dc5831b0333ed Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 13:19:47 -0500 Subject: [PATCH 19/42] Fixed issues when deleting user. --- .../java/me/piitex/app/views/users/UserTemplateView.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/views/users/UserTemplateView.java b/src/main/java/me/piitex/app/views/users/UserTemplateView.java index 2355affa..1a31cae6 100644 --- a/src/main/java/me/piitex/app/views/users/UserTemplateView.java +++ b/src/main/java/me/piitex/app/views/users/UserTemplateView.java @@ -7,6 +7,7 @@ import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.paint.Color; +import javafx.scene.text.Font; import javafx.stage.FileChooser; import me.piitex.app.App; import me.piitex.app.backend.User; @@ -23,6 +24,7 @@ import me.piitex.engine.layouts.FlowLayout; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; +import me.piitex.engine.loaders.FontLoader; import me.piitex.engine.loaders.image.ImageLoader; import me.piitex.engine.overlays.*; import org.apache.commons.io.FileUtils; @@ -265,7 +267,7 @@ private void deleteUser(FlowLayout base, CardContainer card, me.piitex.app.backe // Cleanup image usage VerticalLayout verticalLayout = (VerticalLayout) card.getBody(); - ImageOverlay imageOverlay = (ImageOverlay) verticalLayout.getElementAt(1); + ImageOverlay imageOverlay = (ImageOverlay) verticalLayout.getElementAt(0); // When setting to null the engine will dispose of the image and the JVM will call gc. imageOverlay.setImage(null); @@ -279,6 +281,7 @@ private void deleteUser(FlowLayout base, CardContainer card, me.piitex.app.backe ImageLoader.clearCache(); App.logger.info("Deleting User: {}", user.getId()); FileUtils.deleteDirectory(user.getUserDirectory()); + App.getInstance().getUserTemplates().remove(user.getId()); } catch (IOException e) { App.logger.error("Could not delete directory!", e); } From 19aafdfff178a39f5d90ea3dc2a9c1bed5a0a52d Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 16 May 2026 13:20:00 -0500 Subject: [PATCH 20/42] Added body text when no users exist. --- .../app/views/users/UserTemplateView.java | 41 ++++++++++++------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/main/java/me/piitex/app/views/users/UserTemplateView.java b/src/main/java/me/piitex/app/views/users/UserTemplateView.java index 1a31cae6..f164127f 100644 --- a/src/main/java/me/piitex/app/views/users/UserTemplateView.java +++ b/src/main/java/me/piitex/app/views/users/UserTemplateView.java @@ -60,21 +60,34 @@ public void init() { root.addElement(sidebarView); root.setSpacing(35); - if (App.getInstance().isLoading()) { - root.addElement(new LoadingView("Loading data...", root.getWidth(), 650)); - App.getThreadPoolManager().submitSchedule(() -> { - boolean loading = App.getInstance().isLoading(); - while (loading) { - loading = App.getInstance().isLoading(); - if (!loading) break; - } - Platform.runLater(() -> { - root.removeElement(1); - buildUsers(); - }); - }, 1, TimeUnit.SECONDS); + if (!App.getInstance().getUserTemplates().isEmpty()) { + if (App.getInstance().isLoading()) { + root.addElement(new LoadingView("Loading data...", root.getWidth(), 650)); + App.getThreadPoolManager().submitSchedule(() -> { + boolean loading = App.getInstance().isLoading(); + while (loading) { + loading = App.getInstance().isLoading(); + if (!loading) break; + } + Platform.runLater(() -> { + root.removeElement(1); + buildUsers(); + }); + }, 1, TimeUnit.SECONDS); + } else { + buildUsers(); + } } else { - buildUsers(); + VerticalLayout layout = new VerticalLayout(appSettings.getWidth() - Positions.SIDEBAR_WIDTH - 25, -1); + layout.setMaxSize(layout.getWidth(), layout.getHeight()); + layout.setSpacing(20); + layout.setAlignment(Pos.CENTER); + layout.addStyle(Styles.BORDER_DEFAULT); + root.addElement(layout); + + TextOverlay body = new TextOverlay("Create your first user in the creator page."); + body.setFont(new FontLoader(Font.getDefault(), 24)); + layout.addElement(body); } } From b5dd5a0ed0e993f55998296408af04a95be963c1 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sun, 17 May 2026 10:47:39 -0500 Subject: [PATCH 21/42] Removed stage parameter. --- src/main/java/me/piitex/app/App.java | 2 +- .../java/me/piitex/app/views/settings/SettingsView.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index ae1ecd23..117fc930 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -129,7 +129,7 @@ public void preInitialization() { } @Override - public void initialization(Stage initialStage) { + public void initialization() { // Error will pass if another instance is running, if (error) return; App.logger.info("Loading app from '{}'", getAppDirectory().getAbsolutePath()); diff --git a/src/main/java/me/piitex/app/views/settings/SettingsView.java b/src/main/java/me/piitex/app/views/settings/SettingsView.java index 98f219fa..ede18af4 100644 --- a/src/main/java/me/piitex/app/views/settings/SettingsView.java +++ b/src/main/java/me/piitex/app/views/settings/SettingsView.java @@ -79,7 +79,7 @@ public TileContainer buildWindowScaling() { App.window.clear(); App.window.close(false); appSettings.setWindowScaling(event.getNewValue()); - App.getInstance().initialization(App.window.getStage()); + App.getInstance().initialization(); }); tileContainer.setAction(toggleSwitchOverlay); @@ -175,7 +175,7 @@ public TileContainer buildChatSize() { App.getInstance().getCharacters().values().forEach(character -> character.getChatViewCachedNodes().clear()); App.window.clear(); App.window.close(false); - App.getInstance().initialization(App.window.getStage()); + App.getInstance().initialization(); }); tileContainer.setAction(selection); @@ -230,7 +230,7 @@ public TileContainer buildGlobalChatSize() { App.getInstance().getCharacters().values().forEach(character -> character.getChatViewCachedNodes().clear()); App.window.clear(); App.window.close(false); - App.getInstance().initialization(App.window.getStage()); + App.getInstance().initialization(); }); From 763bc06864e873f1101b5e254285d59ec372c2a4 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sun, 17 May 2026 10:48:47 -0500 Subject: [PATCH 22/42] Added concurrent character loading. --- src/main/java/me/piitex/app/App.java | 32 ++++++++++++------- .../java/me/piitex/app/backend/Character.java | 6 ++-- 2 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index 117fc930..5f1ce576 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -44,6 +44,7 @@ import java.net.URISyntaxException; import java.util.*; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; public class App extends FXLoad { private ServerSettings settings; @@ -71,6 +72,7 @@ public class App extends FXLoad { public static final Logger logger = LogManager.getLogger(App.class); + private final ConcurrentLinkedQueue characterLoadQueue = new ConcurrentLinkedQueue<>(); private volatile boolean loading = true; private volatile boolean error = false; @@ -123,7 +125,6 @@ public void preInitialization() { loadUserTemplates(); loadCharacters(); App.logger.info("Finished pre-initialization."); - loading = false; }); threadPoolManager.submitTask(this::loadBackendServer); } @@ -344,19 +345,28 @@ public void loadCharacters() { return; } for (File file : files) { - logger.info("Loading character '{}'...", file.getName()); if (file.isDirectory()) { - String id = file.getName(); - // Check if info file exists - File info = new File(file, "character.info"); - if (info.exists()) { - InfoFile infoFile = new InfoFile(info, true); - characters.put(id, new Character(id, infoFile)); - } else { - logger.error("Character file does not exist for '{}'", file.getName()); - } + App.getThreadPoolManager().submitTask(() -> { + characterLoadQueue.add(file.getName()); + logger.info("Loading character '{}'...", file.getName()); + String id = file.getName(); + // Check if info file exists + File info = new File(file, "character.info"); + if (info.exists()) { + InfoFile infoFile = new InfoFile(info, true); + characters.put(id, new Character(id, infoFile)); + } else { + logger.error("Character file does not exist for '{}'", file.getName()); + } + + characterLoadQueue.remove(file.getName()); + }); } } + + while (loading) { + loading = !characterLoadQueue.isEmpty(); + } } public void loadUserTemplates() { diff --git a/src/main/java/me/piitex/app/backend/Character.java b/src/main/java/me/piitex/app/backend/Character.java index ae92abba..8b22d4fc 100644 --- a/src/main/java/me/piitex/app/backend/Character.java +++ b/src/main/java/me/piitex/app/backend/Character.java @@ -118,10 +118,8 @@ private void loadChats() { if (getChatDirectory() == null || !getChatDirectory().exists()) return; for (File file : getChatDirectory().listFiles()) { if (file.isDirectory()) continue; - App.getThreadPoolManager().submitTask(() -> { - Chat chat = new Chat(file); - chats.add(chat); - }); + Chat chat = new Chat(file); + chats.add(chat); } } From c7d892f9bff4e71c38fa7eb94137e075ab4c47c4 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Mon, 18 May 2026 20:39:56 -0500 Subject: [PATCH 23/42] Fixed issue where character view would load while characters were loading. --- src/main/java/me/piitex/app/views/HomeView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/views/HomeView.java b/src/main/java/me/piitex/app/views/HomeView.java index 7b346fb5..be9c1530 100644 --- a/src/main/java/me/piitex/app/views/HomeView.java +++ b/src/main/java/me/piitex/app/views/HomeView.java @@ -49,8 +49,8 @@ public void init() { boolean loading = App.getInstance().isLoading(); while (loading) { loading = App.getInstance().isLoading(); - if (!loading) break; } + Platform.runLater(() -> { root.removeElement(1); buildBody(); From 9760776c05ce5c9f59a32eae4b21eccc018c3972 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Mon, 18 May 2026 20:40:52 -0500 Subject: [PATCH 24/42] Removed unused application updater. --- src/main/java/me/piitex/app/App.java | 10 +- .../app/updater/ApplicationUpdater.java | 141 ------------------ 2 files changed, 2 insertions(+), 149 deletions(-) delete mode 100644 src/main/java/me/piitex/app/updater/ApplicationUpdater.java diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index 5f1ce576..fe0c83b9 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -15,7 +15,6 @@ import me.piitex.app.backend.server.ServerProcess; import me.piitex.app.backend.server.ServerSettings; import me.piitex.app.configuration.AppSettings; -import me.piitex.app.updater.ApplicationUpdater; import me.piitex.app.updater.LLamaBackendUpdater; import me.piitex.app.views.HomeView; import me.piitex.app.views.Positions; @@ -344,6 +343,7 @@ public void loadCharacters() { logger.error("Could not initialize characters directory. Program may lack permission to access file system."); return; } + for (File file : files) { if (file.isDirectory()) { App.getThreadPoolManager().submitTask(() -> { @@ -414,19 +414,13 @@ public void performUpdates() { App.logger.error("Failed to fetch download size.", e); } - // Microslop, the multi trillion dollar company that can't handle more than 50 API requests. - App.logger.info("Checking for application updates..."); - ApplicationUpdater applicationUpdater = new ApplicationUpdater(getVersion()); - //applicationUpdater.checkForUpdates(); - App.logger.info("Checking for backend version..."); - if (settings.getDevice().equals("error")) { App.logger.info("Could not load backend devices. Force checking updates..."); settings.setDevice("Auto"); lLamaBackendUpdater = new LLamaBackendUpdater("0"); } else { - File backendVersionFile = Arrays.stream(getBackendDirectory().listFiles()).filter(file -> file.getName().endsWith(".txt")).findAny().orElse(null); + File backendVersionFile = Arrays.stream(Objects.requireNonNull(getBackendDirectory().listFiles())).filter(file -> file.getName().endsWith(".txt")).findAny().orElse(null); if (backendVersionFile != null) { lLamaBackendUpdater = new LLamaBackendUpdater(backendVersionFile.getName().split(".txt")[0]); } else { diff --git a/src/main/java/me/piitex/app/updater/ApplicationUpdater.java b/src/main/java/me/piitex/app/updater/ApplicationUpdater.java deleted file mode 100644 index 8bff6733..00000000 --- a/src/main/java/me/piitex/app/updater/ApplicationUpdater.java +++ /dev/null @@ -1,141 +0,0 @@ -package me.piitex.app.updater; - -import javafx.application.Platform; -import me.piitex.app.App; -import me.piitex.app.backend.server.ServerProcess; -import me.piitex.engine.Window; -import me.piitex.engine.WindowBuilder; -import me.piitex.engine.containers.Container; -import me.piitex.engine.containers.EmptyContainer; -import me.piitex.engine.loaders.image.BaseImageLoader; -import me.piitex.engine.overlays.ButtonBuilder; -import me.piitex.engine.overlays.ButtonOverlay; -import me.piitex.engine.overlays.ProgressBarOverlay; -import me.piitex.engine.overlays.TextOverlay; -import me.piitex.os.*; - -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; - -public class ApplicationUpdater { - private String currentVersion; - private Window window; - private Container container; - - public ApplicationUpdater(String currentVersion) { - this.currentVersion = currentVersion; - } - - public void checkForUpdates() { - App.logger.info("Checking version: {}", currentVersion); - GitHubUtil gitHubUtil = new GitHubUtil("https://api.github.com/repos/HackusatePvP/character-chat-app/"); - try { - String latestVersionString = gitHubUtil.getLatestReleaseJson().getString("tag_name"); - Version latestVersion = VersionUtil.parseVersion(latestVersionString); - App.logger.info("Latest tag is {}", latestVersionString); - - if (!currentVersion.startsWith("v")) { - currentVersion = "v" + currentVersion; - } - Version version = VersionUtil.parseVersion(currentVersion); - - if (version.compareTo(latestVersion) < 0) { - App.logger.info("New application version available."); - Platform.runLater(() -> { - buildAndDisplayUpdateWindow(gitHubUtil); - }); - } else { - App.logger.info("No update available."); - } - - } catch (IOException | URISyntaxException e) { - App.logger.error("Could not fetch latest app release!", e); - } - } - - public void buildAndDisplayUpdateWindow(GitHubUtil gitHubUtil) { - window = new WindowBuilder("Update").setDimensions(400, 150).setIcon(new BaseImageLoader(new File(App.getAppDirectory(), "logo.png"))).build(); - container = new EmptyContainer(400, 150); - window.addContainer(container); - - TextOverlay textOverlay = new TextOverlay("App updates available. Click 'Update' to start."); - textOverlay.setY(20); - textOverlay.setX(10); - container.addElement(textOverlay); - - ButtonOverlay buttonOverlay = new ButtonBuilder("update").setText("Update").build(); - container.addElement(buttonOverlay); - buttonOverlay.setX(150); - buttonOverlay.setY(70); - - buttonOverlay.onClick(_ -> { - App.window.close(false); - App.getInstance().getCharacters().clear(); - App.getInstance().getUserTemplates().clear(); - App.reloadModelList(); - if (ServerProcess.getCurrentServer() != null) { - ServerProcess serverProcess = ServerProcess.getCurrentServer(); - serverProcess.stop(); - } - - container.removeAllElements(); - TextOverlay updateInfo = new TextOverlay("Preparing for installation..."); - updateInfo.setY(20); - updateInfo.setX(10); - container.addElement(updateInfo); - - ProgressBarOverlay progressBarOverlay = new ProgressBarOverlay(); - progressBarOverlay.setX(150); - progressBarOverlay.setY(70); - container.addElement(progressBarOverlay); - }); - App.window.getStage().getScene().getRoot().setDisable(true); - window.getStage().setAlwaysOnTop(true); - window.render(); - } - - private void downloadUpdate(GitHubUtil gitHubUtil, TextOverlay textOverlay, ProgressBarOverlay progressBarOverlay) { - textOverlay.setText("Download updates..."); - progressBarOverlay.getProgressBar().setProgress(0); - - App.getThreadPoolManager().submitTask(() -> { - try { - gitHubUtil.downloadAsset(gitHubUtil.getLatestReleaseID(), new File("download.jar"), new DownloadListener() { - @Override - public void onDownloadStart(DownloadInfo info) { - App.logger.info("Starting download..."); - } - - @Override - public void onDownloadProgress(DownloadInfo info) { - progressBarOverlay.getProgressBar().progressProperty().set(info.getDownloadProgress()); - } - - @Override - public void onDownloadComplete(DownloadInfo info, File outputFile) { - App.logger.info("Update completed! Shutting down..."); - - // Call the file to be moved after the runtime shuts down. - - Platform.exit(); - System.exit(1); - } - - @Override - public void onDownloadError(DownloadInfo info, Exception e) { - - } - - @Override - public void onDownloadCancel(DownloadInfo info) { - - } - - }); - } catch (IOException | URISyntaxException e) { - // TOOD: Display error window - } - }); - } -} From e1bfe74e8dc769ccb462d6aec173f9d376d8f1c1 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 23 May 2026 12:28:03 -0500 Subject: [PATCH 25/42] Fixed duplicated App constructor. --- src/main/java/me/piitex/app/Main.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/me/piitex/app/Main.java b/src/main/java/me/piitex/app/Main.java index 6b97cfda..7c77bf29 100644 --- a/src/main/java/me/piitex/app/Main.java +++ b/src/main/java/me/piitex/app/Main.java @@ -21,7 +21,6 @@ public static void main(String[] args) { if (Arrays.asList(args).contains("--force-updates")) { forceUpdate = true; } - new App(); Application.launch(App.class); } } From 7a0f6eae6391b7983fdc264b6f0c6da19a357dea Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 23 May 2026 12:28:19 -0500 Subject: [PATCH 26/42] Updated log4j api to match core version. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b13cc9aa..25b71c49 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ me.piitex.app character-chat-app - 1.1.3.1105 + 1.1.4 character-chat-app @@ -25,7 +25,7 @@ org.apache.logging.log4j log4j-api - 2.25.2 + 2.25.4 org.apache.logging.log4j From d2b3b4065fe6bc548aa97a85eb775f38d7d00672 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 23 May 2026 12:59:18 -0500 Subject: [PATCH 27/42] Fixed issue where backend server wouldn't start on newer llama.cpp versions. --- src/main/java/me/piitex/app/backend/server/ServerProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 7ec49dca..3377a74f 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -318,7 +318,7 @@ protected void waitForServer() { process.destroy(); break; } - if (line.contains("starting the main loop") || line.contains("main: model loaded")) { + if (line.contains("starting the main loop") || line.contains("model loaded")) { App.logger.info("Backend server stated!"); started = true; break; From 6bf9e8ebbb4b1c77b0536e75f091eea3e75f3c34 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 23 May 2026 12:59:32 -0500 Subject: [PATCH 28/42] Updated RenEngine > 1.0.8 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 25b71c49..eeaa66b5 100644 --- a/pom.xml +++ b/pom.xml @@ -42,7 +42,7 @@ me.piitex.engine ren-engine - 1.0.7-SNAPSHOT + 1.0.8-SNAPSHOT org.junit.jupiter From c22aeaff5c10d73f466e4bb7d803981b6ac1d5cb Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 23 May 2026 13:00:27 -0500 Subject: [PATCH 29/42] Added reset button for fixing corrupted installations. --- .../views/models/tabs/ConfigurationTab.java | 68 ++++++++++++++++++- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java index 4609d6be..49a1ecc7 100644 --- a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java +++ b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java @@ -11,6 +11,7 @@ import me.piitex.app.backend.Model; import me.piitex.app.backend.server.*; import me.piitex.app.configuration.AppSettings; +import me.piitex.app.views.HomeView; import me.piitex.engine.Element; import me.piitex.engine.PopupPosition; import me.piitex.engine.containers.CardContainer; @@ -23,11 +24,15 @@ import me.piitex.engine.layouts.VerticalLayout; import me.piitex.engine.overlays.*; import me.piitex.os.OSUtil; +import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; +import java.util.Objects; import java.util.concurrent.TimeUnit; import static me.piitex.app.views.Positions.*; @@ -63,6 +68,7 @@ public ConfigurationTab(TabsContainer tabsContainer) { // When enabled it allows the user to remotely connect to an endpoint. // Not sure how control of the server would work. layout.addElement(buildServerZone()); + layout.addElement(buildBackendReset()); layout.addElement(buildHostTile()); layout.addElement(buildRemoteModeTile()); layout.addElement(buildBackend()); @@ -77,6 +83,57 @@ public ConfigurationTab(TabsContainer tabsContainer) { Platform.runLater(this::handleServerLoad); } + public TileContainer buildBackendReset() { + TileContainer container = new TileContainer(0, -1); + container.setMaxSize(layout.getWidth(), 180); + container.setTitle("Reset backend files."); + container.setDescription("Deletes all backend files and prompts a re-installation."); + container.addStyle(Styles.BG_DEFAULT); + container.addStyle(Styles.BORDER_DEFAULT); + container.addStyle(appSettings.getGlobalTextSize()); + + VerticalLayout configLayout = new VerticalLayout(400, 150); + configLayout.setSpacing(10); + configLayout.setAlignment(Pos.CENTER_RIGHT); + + ButtonOverlay reset = new ButtonOverlay(new ButtonBuilder("reset").setText("Reset").addStyle(Styles.DANGER).addStyle(Styles.BUTTON_OUTLINED)); + reset.onClick(_ -> { + if (ServerProcess.getCurrentServer() == null) return; + ServerProcess.getCurrentServer().stop(); + File backendDir = App.getBackendDirectory(); + for (File dir : backendDir.listFiles()) { + if (dir.isDirectory()) { + App.logger.info("Deleted '{}'", dir.getAbsolutePath()); + try { + FileUtils.deleteDirectory(dir); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + File backendVersionFile = Arrays.stream(Objects.requireNonNull(backendDir.listFiles())).filter(file -> file.getName().endsWith(".txt")).findAny().orElse(null); + if (backendVersionFile != null) { + try { + FileUtils.delete(backendVersionFile); + App.logger.info("Deleted backend version file..."); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + App.getInstance().performUpdates(); + + App.window.clearContainers(); + App.window.addContainer(new HomeView()); + }); + configLayout.addElement(reset); + + container.setAction(configLayout); + + return container; + } + public TileContainer buildHostTile() { TileContainer container = new TileContainer(0, -1); container.setMaxSize(layout.getWidth(), 180); @@ -328,8 +385,8 @@ public TileContainer buildRunningModel() { } public CardContainer buildServerZone() { - CardContainer card = new CardContainer(0, 0, layout.getWidth(), 200); - card.setMaxSize(layout.getWidth(), 200); + CardContainer card = new CardContainer(0, 0, layout.getWidth(), 250); + card.setMaxSize(card.getWidth(), card.getHeight()); TextOverlay text = new TextOverlay("Server Zone"); text.addStyle(Styles.TITLE_3); @@ -341,10 +398,15 @@ public CardContainer buildServerZone() { desc.addStyle(appSettings.getGlobalTextSize()); card.setBody(desc); + VerticalLayout wrapper = new VerticalLayout(0, 0); + wrapper.setSpacing(10); + card.setFooter(wrapper); + HorizontalLayout layout = new HorizontalLayout(0, 0); layout.setSpacing(20); layout.setAlignment(Pos.CENTER); - card.setFooter(layout); + wrapper.addElement(layout); + start = new ButtonBuilder("start").setText("Start").build(); start.setEnabled(true); From dc6fc76f561d417289e793207b584dbecdc1ac09 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 23 May 2026 13:31:23 -0500 Subject: [PATCH 30/42] Improved loading times and fixed desync issues. --- src/main/java/me/piitex/app/App.java | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index fe0c83b9..cc793ce8 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -44,6 +44,7 @@ import java.util.*; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.Future; public class App extends FXLoad { private ServerSettings settings; @@ -344,9 +345,11 @@ public void loadCharacters() { return; } + Collection> tasks = new HashSet<>(); + for (File file : files) { if (file.isDirectory()) { - App.getThreadPoolManager().submitTask(() -> { + tasks.add(App.getThreadPoolManager().submitTask(() -> { characterLoadQueue.add(file.getName()); logger.info("Loading character '{}'...", file.getName()); String id = file.getName(); @@ -360,13 +363,25 @@ public void loadCharacters() { } characterLoadQueue.remove(file.getName()); - }); + })); } } - while (loading) { - loading = !characterLoadQueue.isEmpty(); - } + int total = tasks.size(); + Collection> completed; + do { + completed = new HashSet<>(); + for (Future task : tasks) { + if (task.isDone()) { + completed.add(task); + } + } + + if (completed.size() == total) { + loading = false; + } + } while (loading); + } public void loadUserTemplates() { @@ -424,6 +439,7 @@ public void performUpdates() { if (backendVersionFile != null) { lLamaBackendUpdater = new LLamaBackendUpdater(backendVersionFile.getName().split(".txt")[0]); } else { + App.logger.info("No update file found."); lLamaBackendUpdater = new LLamaBackendUpdater("0"); } } From 23c41dff96c13acce3974259b997dbf07858a647 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Thu, 28 May 2026 13:20:58 -0500 Subject: [PATCH 31/42] Fixed ui layout issues. --- .../java/me/piitex/app/views/Positions.java | 4 +- .../views/models/tabs/ConfigurationTab.java | 58 +++++++++---------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/main/java/me/piitex/app/views/Positions.java b/src/main/java/me/piitex/app/views/Positions.java index 5ef69d22..d6340feb 100644 --- a/src/main/java/me/piitex/app/views/Positions.java +++ b/src/main/java/me/piitex/app/views/Positions.java @@ -14,7 +14,7 @@ public class Positions { */ public static int SIDEBAR_WIDTH; public static int SIDEBAR_WIDTH_COLLAPSE; - public static int SIDEBAR_HEIGHT; + public static double SIDEBAR_HEIGHT; /* ########################### @@ -80,7 +80,7 @@ private static void initializeDesktop() { SIDEBAR_WIDTH = 200; SIDEBAR_WIDTH_COLLAPSE = 50; - SIDEBAR_HEIGHT = (int) window.getHeight(); + SIDEBAR_HEIGHT = window.getAdjustedHeight(); MODEL_CONFIGURATION_SCROLL_HEIGHT = window.getHeight() - 100; MODEL_CONFIGURATION_LAYOUT_WIDTH = window.getWidth() - SIDEBAR_WIDTH - 25; // -25 to account for spacing diff --git a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java index 49a1ecc7..3a88af97 100644 --- a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java +++ b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java @@ -4,6 +4,7 @@ import javafx.application.Platform; import javafx.geometry.Pos; import javafx.scene.control.ComboBox; +import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.stage.DirectoryChooser; import javafx.util.StringConverter; @@ -28,7 +29,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -84,15 +84,15 @@ public ConfigurationTab(TabsContainer tabsContainer) { } public TileContainer buildBackendReset() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 180); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Reset backend files."); container.setDescription("Deletes all backend files and prompts a re-installation."); container.addStyle(Styles.BG_DEFAULT); container.addStyle(Styles.BORDER_DEFAULT); container.addStyle(appSettings.getGlobalTextSize()); - VerticalLayout configLayout = new VerticalLayout(400, 150); + VerticalLayout configLayout = new VerticalLayout(400, container.getHeight()); configLayout.setSpacing(10); configLayout.setAlignment(Pos.CENTER_RIGHT); @@ -135,15 +135,15 @@ public TileContainer buildBackendReset() { } public TileContainer buildHostTile() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 180); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Set device as host."); container.setDescription("Allows other devices to connect to this devices backend server."); container.addStyle(Styles.BG_DEFAULT); container.addStyle(Styles.BORDER_DEFAULT); container.addStyle(appSettings.getGlobalTextSize()); - VerticalLayout configLayout = new VerticalLayout(400, 150); + VerticalLayout configLayout = new VerticalLayout(400, container.getHeight()); configLayout.setSpacing(10); configLayout.setAlignment(Pos.CENTER_RIGHT); @@ -157,15 +157,15 @@ public TileContainer buildHostTile() { } public TileContainer buildRemoteModeTile() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 180); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Remote Server Mode"); container.setDescription("Setup a remote connection to use a different device to run models."); container.addStyle(Styles.BG_DEFAULT); container.addStyle(Styles.BORDER_DEFAULT); container.addStyle(appSettings.getGlobalTextSize()); - VerticalLayout configLayout = new VerticalLayout(400, 150); + VerticalLayout configLayout = new VerticalLayout(400, container.getHeight()); configLayout.setSpacing(10); configLayout.setAlignment(Pos.CENTER_RIGHT); @@ -193,8 +193,8 @@ public TileContainer buildRemoteModeTile() { } public TileContainer buildModelPathTile() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 100); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Model Path"); container.setDescription("Select the folder for your models."); container.addStyle(Styles.BG_DEFAULT); @@ -243,8 +243,8 @@ private ButtonOverlay actionButton(TileContainer container) { public TileContainer buildCurrentModel() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 100); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Model Selection"); container.setDescription("Select a model to use. Will require a \"reload\"."); container.addStyle(Styles.BG_DEFAULT); @@ -283,15 +283,15 @@ public TileContainer buildCurrentModel() { } public TileContainer buildGpuLayers() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 100); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("GPU Usage"); container.setDescription("Percentage of total VRAM to use. Recommended to keep below 80%."); container.addStyle(Styles.BG_DEFAULT); container.addStyle(Styles.BORDER_DEFAULT); container.addStyle(appSettings.getGlobalTextSize()); - VerticalLayout action = new VerticalLayout(200, 100); + VerticalLayout action = new VerticalLayout(200, container.getHeight()); action.setAlignment(Pos.CENTER); SliderOverlay input = new SliderOverlay(0, 100, settings.getGpuUsage()); @@ -326,8 +326,8 @@ public Double fromString(String string) { } public TileContainer buildMemoryLock() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 100); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Memory Lock"); container.setDescription("Locks model in RAM. Can improve generation times. Disables model swapping."); container.addStyle(Styles.BG_DEFAULT); @@ -344,8 +344,8 @@ public TileContainer buildMemoryLock() { } public TileContainer buildFlashAttention() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 100); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Flash Attention"); container.setDescription("Toggles flash attention. Designed to speed up training and inference while reducing memory usage. In some rare cases it can greatly reduce quality."); container.addStyle(Styles.BG_DEFAULT); @@ -362,8 +362,8 @@ public TileContainer buildFlashAttention() { } public TileContainer buildRunningModel() { - TileContainer container = new TileContainer(0, -1); - container.setMaxSize(layout.getWidth(), 100); + TileContainer container = new TileContainer(layout.getWidth(), -1); + container.setMaxSize(container.getWidth(), container.getHeight()); container.setTitle("Current Model"); container.setDescription("The current running model that is loaded. Will be null if no model is active."); container.addStyle(Styles.BG_DEFAULT); @@ -385,7 +385,7 @@ public TileContainer buildRunningModel() { } public CardContainer buildServerZone() { - CardContainer card = new CardContainer(0, 0, layout.getWidth(), 250); + CardContainer card = new CardContainer(0, 0, layout.getWidth(), -1); card.setMaxSize(card.getWidth(), card.getHeight()); TextOverlay text = new TextOverlay("Server Zone"); @@ -398,14 +398,12 @@ public CardContainer buildServerZone() { desc.addStyle(appSettings.getGlobalTextSize()); card.setBody(desc); - VerticalLayout wrapper = new VerticalLayout(0, 0); - wrapper.setSpacing(10); - card.setFooter(wrapper); - HorizontalLayout layout = new HorizontalLayout(0, 0); + HorizontalLayout layout = new HorizontalLayout(-1, 80); + layout.setMaxSize(layout.getWidth(), layout.getHeight()); layout.setSpacing(20); - layout.setAlignment(Pos.CENTER); - wrapper.addElement(layout); + layout.setAlignment(Pos.BOTTOM_CENTER); + card.setFooter(layout); start = new ButtonBuilder("start").setText("Start").build(); From 65366ce5d1594f9767d17756b9f60f9105f9ad11 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Thu, 28 May 2026 13:21:32 -0500 Subject: [PATCH 32/42] Added error catch if the backend version file is not uploaded. --- .../app/updater/LLamaBackendUpdater.java | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java index bbc822fd..b4d5b51a 100644 --- a/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java +++ b/src/main/java/me/piitex/app/updater/LLamaBackendUpdater.java @@ -4,6 +4,8 @@ import javafx.application.Platform; import javafx.geometry.Pos; import javafx.scene.control.ProgressIndicator; +import javafx.scene.paint.Color; +import javafx.scene.text.TextAlignment; import me.piitex.app.App; import me.piitex.app.backend.Model; import me.piitex.app.backend.server.ServerProcess; @@ -14,10 +16,7 @@ import me.piitex.engine.containers.EmptyContainer; import me.piitex.engine.layouts.VerticalLayout; import me.piitex.engine.loaders.image.BaseImageLoader; -import me.piitex.engine.overlays.ButtonBuilder; -import me.piitex.engine.overlays.ButtonOverlay; -import me.piitex.engine.overlays.ProgressBarOverlay; -import me.piitex.engine.overlays.TextOverlay; +import me.piitex.engine.overlays.*; import me.piitex.os.*; import org.apache.commons.io.FileUtils; import org.json.JSONObject; @@ -113,9 +112,21 @@ public void buildAndDisplayUpdateWindow(GitHubUtil gitHubUtil) { container.removeAllElements(); if (OSUtil.getOS().contains("Windows")) { - downloadCudaBackendNew(gitHubUtil); + try { + downloadCudaBackendNew(gitHubUtil); + } catch (Exception ignored) { + VerticalLayout errorBox = new VerticalLayout(container.getWidth() - 20, container.getHeight() - 20); + errorBox.setMaxSize(errorBox.getWidth(), errorBox.getHeight()); + container.addElement(errorBox); + + TextFlowOverlay error = new TextFlowOverlay("Error occurred while fetching update. Please try updating at a later point.", errorBox.getWidth(), errorBox.getHeight()); + error.setTextAlignment(TextAlignment.CENTER); + error.setMaxSize(error.getWidth(), error.getHeight()); + error.setTextFillColor(Color.RED); + errorBox.addElement(error); + } } else { - + downloadVulkanBackendNew(gitHubUtil, null); } }); From 7e5c7d6e7bffdb440cb3e2cf8cad9558fc164814 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:00:08 -0500 Subject: [PATCH 33/42] Fixed scroll position issues. --- .../views/creator/characters/CharacterCustomizationView.java | 2 +- .../creator/characters/CharacterUserCustomizationView.java | 2 +- .../app/views/creator/characters/ChatCustomizationView.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java b/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java index 3cf3ed44..ded08e91 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/CharacterCustomizationView.java @@ -57,7 +57,7 @@ public CharacterCustomizationView(CharacterCreator parent, InfoFile infoFile, do root.setAlignment(Pos.CENTER); addProperties("progress", "Character"); - scrollContainer = new ScrollContainer(root, width - 5, height - 40); + scrollContainer = new ScrollContainer(root, width - 15, height - 40); scrollContainer.setMaxSize(scrollContainer.getWidth(), scrollContainer.getHeight()); scrollContainer.setHorizontalScroll(false); scrollContainer.setScrollWhenNeeded(false); diff --git a/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java b/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java index 61b328ac..26817a29 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/CharacterUserCustomizationView.java @@ -49,7 +49,7 @@ public CharacterUserCustomizationView(CharacterCreator parent, InfoFile infoFile root.setAlignment(Pos.CENTER); addProperties("progress", "User"); - ScrollContainer scrollContainer = new ScrollContainer(root, width, height); + ScrollContainer scrollContainer = new ScrollContainer(root, width - 15, height - 40); scrollContainer.setHorizontalScroll(false); scrollContainer.setScrollWhenNeeded(false); scrollContainer.setMaxSize(width, height); diff --git a/src/main/java/me/piitex/app/views/creator/characters/ChatCustomizationView.java b/src/main/java/me/piitex/app/views/creator/characters/ChatCustomizationView.java index 38aba3b9..a5373048 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/ChatCustomizationView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/ChatCustomizationView.java @@ -31,7 +31,7 @@ public ChatCustomizationView(CharacterCreator parent, InfoFile infoFile, double root.setSpacing(50); addProperties("progress", "User"); - ScrollContainer scrollContainer = new ScrollContainer(root, width, height); + ScrollContainer scrollContainer = new ScrollContainer(root, width - 15, height - 40); scrollContainer.setHorizontalScroll(false); scrollContainer.setScrollWhenNeeded(false); scrollContainer.setMaxSize(width, height); From b4efc7131ad617f0523bd298f8d3d1d17560012a Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:02:49 -0500 Subject: [PATCH 34/42] Added model reasoning options. --- .../me/piitex/app/backend/server/Server.java | 11 +++- .../app/backend/server/ServerProcess.java | 8 +++ .../app/configuration/ModelSettings.java | 28 +++++++++- .../app/views/models/ModelEditView.java | 55 ++++++++++++++++++- 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/src/main/java/me/piitex/app/backend/server/Server.java b/src/main/java/me/piitex/app/backend/server/Server.java index bfdd58cd..6c20fec4 100644 --- a/src/main/java/me/piitex/app/backend/server/Server.java +++ b/src/main/java/me/piitex/app/backend/server/Server.java @@ -106,6 +106,14 @@ private static HttpPost prepareOAIStreamRequest(Response response) throws JSONEx */ private static void addModelSettingsToJSON(JSONObject toPost, ModelSettings settings) throws JSONException { toPost.put("stream", true); + + if (settings.isReasoning()) { + JSONObject chatTemplateKwargs = new JSONObject(); + chatTemplateKwargs.put("enable_thinking", true); + chatTemplateKwargs.put("thinking", true); + toPost.put("chat_template_kwargs", chatTemplateKwargs); + } + toPost.put("temperature", settings.getTemperature()); toPost.put("dynatemp_range", settings.getDynamicTempRage()); toPost.put("dynatemp_exponent", settings.getDynamicExponent()); @@ -215,8 +223,9 @@ private static boolean processStreamChunk(String content, StringBuilder appender } JSONObject delta = arrayObject.getJSONObject("delta"); + String line = delta.optString("content", ""); - if (line.equalsIgnoreCase("null")) continue; + if (line.isEmpty() || line.equalsIgnoreCase("null")) continue; appender.append(line); diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 3377a74f..c596a4e1 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -267,6 +267,14 @@ private LinkedList getParameters(File server, ServerSettings settings) { if (model.getSettings().isForceDisableReasoning()) { App.logger.info("Force disable reasoning...."); parameters.add("--no-prefill-assistant"); + parameters.add("-rea"); + parameters.add("off"); + } else { + if (model.getSettings().isReasoning()) { + App.logger.info("Enabling thinking mode...."); + parameters.add("-rea"); + parameters.add("on"); + } } if (!model.getSettings().getChatTemplate().equalsIgnoreCase("default")) { diff --git a/src/main/java/me/piitex/app/configuration/ModelSettings.java b/src/main/java/me/piitex/app/configuration/ModelSettings.java index ecfa2e14..cc4ef16e 100644 --- a/src/main/java/me/piitex/app/configuration/ModelSettings.java +++ b/src/main/java/me/piitex/app/configuration/ModelSettings.java @@ -26,9 +26,11 @@ public class ModelSettings { private int dryPenaltyTokens = -1; private String mmProj = "None / Disabled"; private String chatTemplate = "default"; - private String reasoningTemplate = "disabled"; + private String reasoningTemplate = "auto"; private boolean useDefault; private boolean jinja = false; + private boolean reasoning = false; + private int reasoningBudget = -1; private boolean forceDisableReasoning = false; private int totalLayers = 0; private double dataPerLayer; @@ -188,6 +190,12 @@ public ModelSettings(InfoFile infoFile) { if (infoFile.hasKey("force-disable-reason")) { this.forceDisableReasoning = infoFile.getBoolean("force-disable-reason"); } + if (infoFile.hasKey("reasoning")) { + this.reasoning = infoFile.getBoolean("reasoning"); + } + if (infoFile.hasKey("reasoning-budget")) { + this.reasoningBudget = infoFile.getInteger("reasoning-budget"); + } } public String getModelInstructions() { @@ -478,6 +486,24 @@ public void setChange(boolean change) { infoFile.set("change", change); } + public int getReasoningBudget() { + return reasoningBudget; + } + + public boolean isReasoning() { + return reasoning; + } + + public void setReasoning(boolean reasoning) { + this.reasoning = reasoning; + infoFile.set("reasoning", reasoning); + } + + public void setReasoningBudget(int reasoningBudget) { + this.reasoningBudget = reasoningBudget; + infoFile.set("reasoning-budget", reasoningBudget); + } + public boolean isForceDisableReasoning() { return forceDisableReasoning; } diff --git a/src/main/java/me/piitex/app/views/models/ModelEditView.java b/src/main/java/me/piitex/app/views/models/ModelEditView.java index cf80e1ee..b287b170 100644 --- a/src/main/java/me/piitex/app/views/models/ModelEditView.java +++ b/src/main/java/me/piitex/app/views/models/ModelEditView.java @@ -42,7 +42,9 @@ public class ModelEditView extends EmptyContainer { private int dryPenaltyTokens = -1; private String mmProj = "None / Disabled"; private String chatTemplate = "default"; - private String reasoningTemplate = "disabled"; + private String reasoningTemplate = "auto"; + private int reasoningBudget = 1; + private boolean reasoning = false; private boolean forceDisableReasoning = false; private boolean jinja = false; @@ -91,6 +93,8 @@ public ModelEditView(ModelSettings settings) { layout.addElement(buildDryAllowedLength()); layout.addElement(buildDryPenaltyToken()); layout.addElement(buildChatTemplates()); + layout.addElement(buildReasoningEnable()); + layout.addElement(buildReasoningBudget()); layout.addElement(buildReasoningTemplate()); layout.addElement(buildForceReasoning()); layout.addElement(buildJinjaTemplate()); @@ -121,6 +125,8 @@ private void initializeSettings() { this.dryPenaltyTokens = settings.getDryPenaltyTokens(); this.chatTemplate = settings.getChatTemplate(); this.reasoningTemplate = settings.getReasoningTemplate(); + this.reasoning = settings.isReasoning(); + this.reasoningBudget = settings.getReasoningBudget(); this.forceDisableReasoning = settings.isForceDisableReasoning(); this.jinja = settings.isJinja(); } @@ -679,6 +685,7 @@ private TileContainer buildReasoningTemplate() { items.add("deepseek"); items.add("none"); items.add("disabled"); + items.add("auto"); ComboBoxOverlay selection = new ComboBoxOverlay(items, 400, 50); selection.setDefaultItem(reasoningTemplate); @@ -690,6 +697,50 @@ private TileContainer buildReasoningTemplate() { return tileContainer; } + private TileContainer buildReasoningEnable() { + TileContainer tileContainer = new TileContainer(0, 0); + tileContainer.addStyle(Styles.BORDER_DEFAULT); + tileContainer.addStyle(Styles.BG_DEFAULT); + tileContainer.addStyle(appSettings.getGlobalTextSize()); + tileContainer.setMaxSize(appSettings.getWidth() - 300, 150); + tileContainer.setTitle("Enable Reasoning"); + tileContainer.setDescription("Enables thinking mode."); + + IconOverlay info = new IconOverlay(Material2AL.INFO); + info.setTooltip("Only enable if the model is capable of reasoning."); + tileContainer.setGraphic(info); + + ToggleSwitchOverlay switchOverlay = new ToggleSwitchOverlay(reasoning); + switchOverlay.onToggle(event -> { + this.reasoning = event.getNewValue(); + }); + tileContainer.setAction(switchOverlay); + + return tileContainer; + } + + private TileContainer buildReasoningBudget() { + TileContainer tileContainer = new TileContainer(0, 0); + tileContainer.addStyle(Styles.BORDER_DEFAULT); + tileContainer.addStyle(Styles.BG_DEFAULT); + tileContainer.addStyle(appSettings.getGlobalTextSize()); + tileContainer.setMaxSize(appSettings.getWidth() - 300, 150); + tileContainer.setTitle("Reasoning Budget"); + tileContainer.setDescription("Set the maximum tokens allowed for reasoning."); + + IconOverlay info = new IconOverlay(Material2AL.INFO); + info.setTooltip("Default is -1 which disables the limit."); + tileContainer.setGraphic(info); + + SpinnerNumberOverlay input = new SpinnerNumberOverlay(-1, Double.MAX_VALUE, reasoningBudget); + input.onValueChange(event -> { + this.reasoningBudget = event.getNewValue().intValue(); + }); + tileContainer.setAction(input); + + return tileContainer; + } + private TileContainer buildForceReasoning() { TileContainer tileContainer = new TileContainer(0, 0); tileContainer.addStyle(Styles.BORDER_DEFAULT); @@ -776,6 +827,8 @@ public HorizontalLayout buildSubmitBox() { settings.setMmProj(mmProj); settings.setChatTemplate(chatTemplate); settings.setReasoningTemplate(reasoningTemplate); + settings.setReasoning(reasoning); + settings.setReasoningBudget(reasoningBudget); settings.setForceDisableReasoning(forceDisableReasoning); settings.setJinja(jinja); settings.setChange(true); From 30c4f44d14a14bc5aa906cdadbf4e7eb90584dd6 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:06:08 -0500 Subject: [PATCH 35/42] Moved ServerSettings to configuration package. --- .../java/me/piitex/app/backend/server/ModelTestProcess.java | 1 + src/main/java/me/piitex/app/backend/server/Server.java | 1 + src/main/java/me/piitex/app/backend/server/ServerProcess.java | 2 +- .../app/{backend/server => configuration}/ServerSettings.java | 2 +- src/main/java/me/piitex/app/views/chats/ChatPageView.java | 1 + .../me/piitex/app/views/models/tabs/ConfigurationTab.java | 2 +- .../java/me/piitex/app/views/setup/ConfigureBackendView.java | 2 +- .../java/me/piitex/app/views/setup/ConfigureModelView.java | 4 +--- src/main/java/me/piitex/app/views/setup/GPUSetupView.java | 2 +- src/main/java/me/piitex/app/views/setup/SetupModelView.java | 3 +-- src/main/java/me/piitex/app/views/setup/SetupRunnerView.java | 4 +--- 11 files changed, 11 insertions(+), 13 deletions(-) rename src/main/java/me/piitex/app/{backend/server => configuration}/ServerSettings.java (99%) diff --git a/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java b/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java index 3e89a2ee..e9bd4938 100644 --- a/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java @@ -2,6 +2,7 @@ import me.piitex.app.App; import me.piitex.app.backend.Model; +import me.piitex.app.configuration.ServerSettings; import me.piitex.os.OSUtil; import java.io.File; diff --git a/src/main/java/me/piitex/app/backend/server/Server.java b/src/main/java/me/piitex/app/backend/server/Server.java index 6c20fec4..ab4124af 100644 --- a/src/main/java/me/piitex/app/backend/server/Server.java +++ b/src/main/java/me/piitex/app/backend/server/Server.java @@ -6,6 +6,7 @@ import me.piitex.app.backend.ChatMessage; import me.piitex.app.backend.Response; import me.piitex.app.configuration.ModelSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.utils.Placeholder; import me.piitex.engine.Element; import me.piitex.engine.containers.CardContainer; diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index c596a4e1..492a5d7e 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -5,11 +5,11 @@ import javafx.application.Platform; import me.piitex.app.App; import me.piitex.app.backend.Model; +import me.piitex.app.configuration.ServerSettings; import me.piitex.engine.PopupPosition; import me.piitex.engine.overlays.MessageOverlay; import me.piitex.os.OSUtil; import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; import oshi.hardware.GraphicsCard; import oshi.hardware.HardwareAbstractionLayer; diff --git a/src/main/java/me/piitex/app/backend/server/ServerSettings.java b/src/main/java/me/piitex/app/configuration/ServerSettings.java similarity index 99% rename from src/main/java/me/piitex/app/backend/server/ServerSettings.java rename to src/main/java/me/piitex/app/configuration/ServerSettings.java index db26c3a6..92485ffd 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerSettings.java +++ b/src/main/java/me/piitex/app/configuration/ServerSettings.java @@ -1,4 +1,4 @@ -package me.piitex.app.backend.server; +package me.piitex.app.configuration; import me.piitex.app.App; import me.piitex.app.backend.Model; diff --git a/src/main/java/me/piitex/app/views/chats/ChatPageView.java b/src/main/java/me/piitex/app/views/chats/ChatPageView.java index b308fd4e..3527659c 100644 --- a/src/main/java/me/piitex/app/views/chats/ChatPageView.java +++ b/src/main/java/me/piitex/app/views/chats/ChatPageView.java @@ -12,6 +12,7 @@ import me.piitex.app.backend.Response; import me.piitex.app.backend.Role; import me.piitex.app.backend.server.Server; +import me.piitex.app.backend.server.ServerProcess; import me.piitex.app.configuration.AppSettings; import me.piitex.app.utils.Placeholder; import me.piitex.app.views.chats.components.ControlBarView; diff --git a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java index 3a88af97..77268483 100644 --- a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java +++ b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java @@ -4,7 +4,6 @@ import javafx.application.Platform; import javafx.geometry.Pos; import javafx.scene.control.ComboBox; -import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.stage.DirectoryChooser; import javafx.util.StringConverter; @@ -12,6 +11,7 @@ import me.piitex.app.backend.Model; import me.piitex.app.backend.server.*; import me.piitex.app.configuration.AppSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.views.HomeView; import me.piitex.engine.Element; import me.piitex.engine.PopupPosition; diff --git a/src/main/java/me/piitex/app/views/setup/ConfigureBackendView.java b/src/main/java/me/piitex/app/views/setup/ConfigureBackendView.java index f109c785..28f4d5d4 100644 --- a/src/main/java/me/piitex/app/views/setup/ConfigureBackendView.java +++ b/src/main/java/me/piitex/app/views/setup/ConfigureBackendView.java @@ -6,7 +6,7 @@ import javafx.scene.text.TextAlignment; import javafx.util.StringConverter; import me.piitex.app.App; -import me.piitex.app.backend.server.ServerSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.configuration.AppSettings; import me.piitex.app.views.Positions; import me.piitex.engine.layouts.VerticalLayout; diff --git a/src/main/java/me/piitex/app/views/setup/ConfigureModelView.java b/src/main/java/me/piitex/app/views/setup/ConfigureModelView.java index 9f5f37ac..a1277c59 100644 --- a/src/main/java/me/piitex/app/views/setup/ConfigureModelView.java +++ b/src/main/java/me/piitex/app/views/setup/ConfigureModelView.java @@ -3,13 +3,11 @@ import atlantafx.base.theme.Styles; import javafx.geometry.Orientation; import javafx.geometry.Pos; -import javafx.scene.paint.Color; import javafx.stage.DirectoryChooser; import me.piitex.app.App; -import me.piitex.app.backend.server.ServerSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.configuration.AppSettings; import me.piitex.app.views.Positions; -import me.piitex.engine.containers.TileContainer; import me.piitex.engine.layouts.HorizontalLayout; import me.piitex.engine.layouts.VerticalLayout; import me.piitex.engine.overlays.*; diff --git a/src/main/java/me/piitex/app/views/setup/GPUSetupView.java b/src/main/java/me/piitex/app/views/setup/GPUSetupView.java index 1abcaf0b..f050103d 100644 --- a/src/main/java/me/piitex/app/views/setup/GPUSetupView.java +++ b/src/main/java/me/piitex/app/views/setup/GPUSetupView.java @@ -5,7 +5,7 @@ import javafx.geometry.Pos; import me.piitex.app.App; import me.piitex.app.backend.server.DeviceProcess; -import me.piitex.app.backend.server.ServerSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.configuration.AppSettings; import me.piitex.app.views.Positions; import me.piitex.engine.layouts.VerticalLayout; diff --git a/src/main/java/me/piitex/app/views/setup/SetupModelView.java b/src/main/java/me/piitex/app/views/setup/SetupModelView.java index b1145200..4c849a13 100644 --- a/src/main/java/me/piitex/app/views/setup/SetupModelView.java +++ b/src/main/java/me/piitex/app/views/setup/SetupModelView.java @@ -7,7 +7,7 @@ import javafx.scene.text.TextAlignment; import me.piitex.app.App; import me.piitex.app.backend.server.ServerProcess; -import me.piitex.app.backend.server.ServerSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.configuration.AppSettings; import me.piitex.app.views.Positions; import me.piitex.app.views.creator.characters.CharacterCreator; @@ -18,7 +18,6 @@ import me.piitex.os.FileDownloader; import me.piitex.os.OSUtil; -import java.awt.*; import java.io.File; import java.io.IOException; diff --git a/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java b/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java index 3e41cc89..75e4af8f 100644 --- a/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java +++ b/src/main/java/me/piitex/app/views/setup/SetupRunnerView.java @@ -2,16 +2,14 @@ import atlantafx.base.theme.Styles; import javafx.application.Platform; -import javafx.beans.binding.Bindings; import javafx.geometry.Orientation; import javafx.geometry.Pos; import javafx.scene.control.ProgressBar; import javafx.scene.paint.Color; import me.piitex.app.App; import me.piitex.app.backend.Model; -import me.piitex.app.backend.server.DeviceProcess; import me.piitex.app.backend.server.ServerProcess; -import me.piitex.app.backend.server.ServerSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.configuration.AppSettings; import me.piitex.app.views.Positions; import me.piitex.engine.layouts.VerticalLayout; From c7cf87a716d1fa48c87ed70b0ba33b7c0198b57c Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:06:55 -0500 Subject: [PATCH 36/42] Fixed issues with scroll position. --- .../views/creator/characters/FinishCharacterCreatorView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java b/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java index 73e69c5a..da996062 100644 --- a/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java +++ b/src/main/java/me/piitex/app/views/creator/characters/FinishCharacterCreatorView.java @@ -43,7 +43,7 @@ public FinishCharacterCreatorView(CharacterCreator parent, InfoFile infoFile, do root.setSpacing(50); addProperties("progress", "User"); - ScrollContainer scrollContainer = new ScrollContainer(root, width, height); + ScrollContainer scrollContainer = new ScrollContainer(root, width - 15, height - 40); scrollContainer.setHorizontalScroll(false); scrollContainer.setScrollWhenNeeded(false); scrollContainer.setMaxSize(width, height); From fe85b3261c159ec6239f561250926ba241a67242 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:07:44 -0500 Subject: [PATCH 37/42] Moved order of model selection. --- .../app/views/models/tabs/ConfigurationTab.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java index 77268483..b8d18fd1 100644 --- a/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java +++ b/src/main/java/me/piitex/app/views/models/tabs/ConfigurationTab.java @@ -64,18 +64,15 @@ public ConfigurationTab(TabsContainer tabsContainer) { scrollContainer.setScrollWhenNeeded(false); addElement(scrollContainer); // Adds the scroll container - // TODO: Allow remote server routing. - // When enabled it allows the user to remotely connect to an endpoint. - // Not sure how control of the server would work. layout.addElement(buildServerZone()); layout.addElement(buildBackendReset()); layout.addElement(buildHostTile()); layout.addElement(buildRemoteModeTile()); layout.addElement(buildBackend()); layout.addElement(buildGpuDevice()); + layout.addElement(buildCurrentModel()); layout.addElement(buildRunningModel()); layout.addElement(buildModelPathTile()); - layout.addElement(buildCurrentModel()); layout.addElement(buildGpuLayers()); layout.addElement(buildMemoryLock()); layout.addElement(buildFlashAttention()); @@ -487,7 +484,7 @@ public CardContainer buildServerZone() { }); - stop.onClick(event -> { + stop.onClick(_ -> { if (ServerProcess.getCurrentServer() == null) { return; } @@ -566,13 +563,11 @@ public void onServerLoadingComplete(boolean success) { Platform.runLater(() -> { if (App.window.getCurrentPopup() != null) { // Check if popup still exists App.window.removeContainer(App.window.getCurrentPopup()); - - start.getNode().setDisable(false); - stop.getNode().setDisable(false); - reload.getNode().setDisable(false); + start.setEnabled(true); + stop.setEnabled(true); + reload.setEnabled(true); } }); - // Crucial: Remove the listener if it's a one-time event, to prevent memory leaks serverProcess.removeServerLoadingListener(this); } }); From ed7a3a8690c3bba5025bedcc32d4a57ec3bdfecb Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:08:12 -0500 Subject: [PATCH 38/42] Fixed null exception issue when a chat message was queued before the ServerProcess was started. --- src/main/java/me/piitex/app/views/chats/ChatPageView.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/me/piitex/app/views/chats/ChatPageView.java b/src/main/java/me/piitex/app/views/chats/ChatPageView.java index 3527659c..5adb3528 100644 --- a/src/main/java/me/piitex/app/views/chats/ChatPageView.java +++ b/src/main/java/me/piitex/app/views/chats/ChatPageView.java @@ -175,6 +175,8 @@ public VerticalLayout buildMessageBox(ChatMessage chatMessage) { public void generateResponse(String prompt, boolean update) { Chat chat = parent.getChat(); + if (ServerProcess.getCurrentServer() == null) return; + // Remove regenerate button from last message if (!chatRoot.getElements().isEmpty()) { VerticalLayout lastMessageBox = (VerticalLayout) chatRoot.getLastElement(); From 5c43a099423553e602b768dc29d53f4a8439d5e3 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:09:16 -0500 Subject: [PATCH 39/42] Fixed issues where server would not output model info causing VRAM and layer calculations to fail. --- .../java/me/piitex/app/backend/server/ModelTestProcess.java | 3 +++ src/main/java/me/piitex/app/backend/server/ServerProcess.java | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java b/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java index e9bd4938..3b11493c 100644 --- a/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java @@ -137,6 +137,8 @@ private LinkedList getParameters(File server, ServerSettings settings) { parameters.add("-no-cnv"); parameters.add("--no-warmup"); + parameters.add("-lv"); + parameters.add("4"); return parameters; } @@ -189,6 +191,7 @@ protected void processOutput() { try (Scanner scanner = new Scanner(new FileInputStream(output))) { while (scanner.hasNextLine()) { String line = scanner.nextLine(); + line = line.substring(15); if (line.contains("cleaning up before exit...") || line.contains("failed to load model") || line.contains("error while handling") || line.startsWith("error:") || line.startsWith("ROCm error:")) { App.logger.error("ERROR: Could not start backend server."); error = true; diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 492a5d7e..3a386201 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -300,6 +300,8 @@ private LinkedList getParameters(File server, ServerSettings settings) { parameters.add("--port"); parameters.add("8187"); parameters.add("--no-webui"); + parameters.add("-lv"); + parameters.add("4"); if (settings.isHost()) { App.logger.info("Server is listening on 0.0.0.0"); @@ -319,7 +321,7 @@ protected void waitForServer() { Thread.sleep(100); // Wait for 100 milliseconds before checking the file again try (Scanner scanner = new Scanner(new FileInputStream(output))) { while (scanner.hasNextLine()) { - String line = scanner.nextLine(); + String line = scanner.nextLine().substring(15); if (line.contains("cleaning up before exit...") || line.contains("failed to load model") || line.contains("error while handling") || line.startsWith("error:") || line.startsWith("ROCm error:")) { App.logger.error("ERROR: Could not start backend server."); error = true; From e0115e077a43f785b94a43190bd69b931403cfc1 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sat, 30 May 2026 21:09:28 -0500 Subject: [PATCH 40/42] Cleaned up code. --- src/main/java/me/piitex/app/App.java | 2 +- .../java/me/piitex/app/views/LoadingView.java | 1 - .../java/me/piitex/app/views/SidebarView.java | 27 +------------------ 3 files changed, 2 insertions(+), 28 deletions(-) diff --git a/src/main/java/me/piitex/app/App.java b/src/main/java/me/piitex/app/App.java index cc793ce8..46ce51ba 100644 --- a/src/main/java/me/piitex/app/App.java +++ b/src/main/java/me/piitex/app/App.java @@ -13,7 +13,7 @@ import me.piitex.app.backend.User; import me.piitex.app.backend.server.DeviceProcess; import me.piitex.app.backend.server.ServerProcess; -import me.piitex.app.backend.server.ServerSettings; +import me.piitex.app.configuration.ServerSettings; import me.piitex.app.configuration.AppSettings; import me.piitex.app.updater.LLamaBackendUpdater; import me.piitex.app.views.HomeView; diff --git a/src/main/java/me/piitex/app/views/LoadingView.java b/src/main/java/me/piitex/app/views/LoadingView.java index cf5620d0..74b9c640 100644 --- a/src/main/java/me/piitex/app/views/LoadingView.java +++ b/src/main/java/me/piitex/app/views/LoadingView.java @@ -1,6 +1,5 @@ package me.piitex.app.views; -import atlantafx.base.theme.Styles; import javafx.geometry.Pos; import me.piitex.engine.layouts.VerticalLayout; diff --git a/src/main/java/me/piitex/app/views/SidebarView.java b/src/main/java/me/piitex/app/views/SidebarView.java index b9826e8e..94971f67 100644 --- a/src/main/java/me/piitex/app/views/SidebarView.java +++ b/src/main/java/me/piitex/app/views/SidebarView.java @@ -194,29 +194,4 @@ private VerticalLayout buildVersionLayout() { return layout; } -} - -// ButtonOverlay users = new ButtonBuilder("users").setText("User Templates").setIcon(new FontIcon(Material2MZ.MEMORY)).build(); -// users.addStyle(appSettings.getGlobalTextSize()); -// users.setWidth(rootWidth); -// users.setAlignment(Pos.BASELINE_LEFT); -// addElement(users); -// users.onClick(event -> { -// MessageOverlay warning = new MessageOverlay("Development", "User templates are still in development."); -// warning.addStyle(Styles.WARNING); -// App.window.renderPopup(warning, PopupPosition.BOTTOM_CENTER, 400, 100, true); -// -// App.window.clearContainers(); -// App.window.addContainer(new UsersView()); -// }); -// -// ButtonOverlay characters = new ButtonBuilder("characters").setText("New Character").setIcon(new FontIcon(Material2MZ.PERSON)).build(); -// characters.addStyle(appSettings.getGlobalTextSize()); -// characters.setWidth(rootWidth); -// addElement(characters); -// characters.setAlignment(Pos.BASELINE_LEFT); -// characters.onClick(event -> { -// App.window.clearContainers(); -// App.window.addContainer(new CharacterEditView(null).getRoot()); -// }); - +} \ No newline at end of file From 2e6da7889f4f76b8a792c47578454ca96b5ac7f0 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Sun, 31 May 2026 15:14:12 -0500 Subject: [PATCH 41/42] Fixed height issues with views. --- src/main/java/me/piitex/app/views/HomeView.java | 2 +- src/main/java/me/piitex/app/views/Positions.java | 2 +- src/main/java/me/piitex/app/views/chats/ChatView.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/me/piitex/app/views/HomeView.java b/src/main/java/me/piitex/app/views/HomeView.java index be9c1530..39a7bbd2 100644 --- a/src/main/java/me/piitex/app/views/HomeView.java +++ b/src/main/java/me/piitex/app/views/HomeView.java @@ -23,7 +23,7 @@ public class HomeView extends EmptyContainer { private final SidebarView sidebarView; public HomeView() { - int height = App.getInstance().getAppSettings().getHeight() - 50; + double height = App.window.getDrawHeight(); super(600, height); this.sidebarView = new SidebarView(); if (App.mobile) { diff --git a/src/main/java/me/piitex/app/views/Positions.java b/src/main/java/me/piitex/app/views/Positions.java index d6340feb..6b672c8d 100644 --- a/src/main/java/me/piitex/app/views/Positions.java +++ b/src/main/java/me/piitex/app/views/Positions.java @@ -80,7 +80,7 @@ private static void initializeDesktop() { SIDEBAR_WIDTH = 200; SIDEBAR_WIDTH_COLLAPSE = 50; - SIDEBAR_HEIGHT = window.getAdjustedHeight(); + SIDEBAR_HEIGHT = window.getDrawHeight(); MODEL_CONFIGURATION_SCROLL_HEIGHT = window.getHeight() - 100; MODEL_CONFIGURATION_LAYOUT_WIDTH = window.getWidth() - SIDEBAR_WIDTH - 25; // -25 to account for spacing diff --git a/src/main/java/me/piitex/app/views/chats/ChatView.java b/src/main/java/me/piitex/app/views/chats/ChatView.java index f14f6bfa..b615edf2 100644 --- a/src/main/java/me/piitex/app/views/chats/ChatView.java +++ b/src/main/java/me/piitex/app/views/chats/ChatView.java @@ -21,7 +21,7 @@ public class ChatView extends EmptyContainer { private static final AppSettings APP_SETTINGS = App.getInstance().getAppSettings(); public ChatView(@NotNull Character character, @Nullable Chat chat) { - super(APP_SETTINGS.getWidth(), APP_SETTINGS.getHeight()); + super(APP_SETTINGS.getWidth(), App.window.getDrawHeight()); this.character = character; if (chat == null) { // Create a new chat @@ -34,7 +34,7 @@ public ChatView(@NotNull Character character, @Nullable Chat chat) { } public void init() { - layout = new HorizontalLayout(APP_SETTINGS.getWidth() - 100, APP_SETTINGS.getHeight()); + layout = new HorizontalLayout(getWidth() - 100, getHeight()); layout.setMaxSize(layout.getWidth(), layout.getHeight()); layout.setSpacing(5); layout.addStyle(Styles.BG_INSET); From 13df28631e94fc63a0bde3d57c442ba0ca6b96b7 Mon Sep 17 00:00:00 2001 From: HackusatePvP Date: Thu, 4 Jun 2026 16:48:15 -0500 Subject: [PATCH 42/42] Fixed issues where vram-per-layer was not calculated correctly. --- .../app/backend/server/ModelTestProcess.java | 17 +++++++++++------ .../app/backend/server/ServerProcess.java | 8 ++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java b/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java index 3b11493c..9a6b273e 100644 --- a/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ModelTestProcess.java @@ -191,16 +191,19 @@ protected void processOutput() { try (Scanner scanner = new Scanner(new FileInputStream(output))) { while (scanner.hasNextLine()) { String line = scanner.nextLine(); - line = line.substring(15); + if (line.contains(" ")) { + line = line.split(" ", 2)[1]; + } + line = line.replace("I ", "").trim(); if (line.contains("cleaning up before exit...") || line.contains("failed to load model") || line.contains("error while handling") || line.startsWith("error:") || line.startsWith("ROCm error:")) { App.logger.error("ERROR: Could not start backend server."); error = true; break; } if (line.startsWith("print_info: n_layer") && model.getSettings().getTotalLayers() == 0) { - line = line.split("=")[1].trim(); - App.logger.info("Total Model Layers: {}", line); - model.getSettings().setTotalLayers(Integer.parseInt(line)); + String layers = line.substring(15).split("=")[1].trim(); + App.logger.info("Total Model Layers: {}", layers); + model.getSettings().setTotalLayers(Integer.parseInt(layers)); } if (line.contains("common_memory_breakdown_print:") && line.contains("|") && line.contains("=")) { String[] parts = line.split("\\|"); @@ -268,10 +271,12 @@ protected void processOutput() { if (computeBufferMiB > 0.0) { model.getSettings().setComputeBufferSize(computeBufferMiB); } - } catch (FileNotFoundException e) { + } catch (Exception e) { error = true; - stop(); + App.logger.error("Err while testing model.", e); } + + App.logger.info("Model data processed!"); stop(); } diff --git a/src/main/java/me/piitex/app/backend/server/ServerProcess.java b/src/main/java/me/piitex/app/backend/server/ServerProcess.java index 3a386201..4298c7bb 100644 --- a/src/main/java/me/piitex/app/backend/server/ServerProcess.java +++ b/src/main/java/me/piitex/app/backend/server/ServerProcess.java @@ -229,8 +229,8 @@ private LinkedList getParameters(File server, ServerSettings settings) { if (VRAM_PER_LAYER_MIB > 0.0) { layers = (int) Math.floor(LAYER_ALLOC_BUDGET / VRAM_PER_LAYER_MIB); } else { - App.logger.warn("VRAM per layer (dataPerLayer) is 0.0, defaulting layers to 0."); - layers = 0; + App.logger.warn("VRAM per layer (dataPerLayer) is 0.0, defaulting layers to {}.", model.getSettings().getTotalLayers()); + layers = model.getSettings().getTotalLayers(); } // Cap the offloaded layers @@ -321,14 +321,14 @@ protected void waitForServer() { Thread.sleep(100); // Wait for 100 milliseconds before checking the file again try (Scanner scanner = new Scanner(new FileInputStream(output))) { while (scanner.hasNextLine()) { - String line = scanner.nextLine().substring(15); + String line = scanner.nextLine(); if (line.contains("cleaning up before exit...") || line.contains("failed to load model") || line.contains("error while handling") || line.startsWith("error:") || line.startsWith("ROCm error:")) { App.logger.error("ERROR: Could not start backend server."); error = true; process.destroy(); break; } - if (line.contains("starting the main loop") || line.contains("model loaded")) { + if (line.contains("starting the main loop") || line.contains("model loaded") || line.contains("server is listening on")) { App.logger.info("Backend server stated!"); started = true; break;