From: Svjatoslav Agejenko Date: Sun, 18 Jan 2026 20:43:49 +0000 (+0200) Subject: Refactor to remove `ConfigurationHelper` and `ModelLibrary`, consolidating functional... X-Git-Url: http://www2.svjatoslav.eu/gitweb/?a=commitdiff_plain;h=d22cd6e7026462389dd962fd15a69ea2143a2294;p=alyverkko-cli.git Refactor to remove `ConfigurationHelper` and `ModelLibrary`, consolidating functionality into `Utils` and `Configuration`. --- diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/Utils.java b/src/main/java/eu/svjatoslav/alyverkko_cli/Utils.java index c01c2a7..b80f9e7 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/Utils.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/Utils.java @@ -1,5 +1,10 @@ package eu.svjatoslav.alyverkko_cli; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; +import eu.svjatoslav.alyverkko_cli.configuration.Configuration; +import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOption; + import java.io.BufferedReader; import java.io.File; import java.io.FileReader; @@ -51,5 +56,42 @@ public class Utils { return firstLine != null && firstLine.startsWith("TOCOMPUTE:"); } + /** + * The default path for the YAML config file, typically under the user's home directory. + */ + public static final String DEFAULT_CONFIG_FILE_PATH = "~/.config/alyverkko-cli/alyverkko-cli.yaml".replaceFirst("^~", System.getProperty("user.home")); + + /** + * Loads the configuration from a given file, or from the default + * path if {@code configFile} is null. + * + * @param configFile the file containing the YAML config; may be null. + * @return the {@link Configuration} object, or null if not found/invalid. + * @throws IOException if file I/O fails during reading. + */ + public static Configuration loadConfiguration(File configFile) throws IOException { + + if (!configFile.exists()) { + System.err.println("Configuration file not found: " + configFile); + return null; + } + + ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); + return mapper.readValue(configFile, Configuration.class); + } + + /** + * Returns the configuration file from the given option, or the default path if not present. + * @param configFileOption the CLI option for the config file. + * @return the configuration file to load. + */ + public static File getConfigurationFile(FileOption configFileOption) { + if (configFileOption != null) + if (configFileOption.isPresent()) + return configFileOption.getValue(); + + return new File(DEFAULT_CONFIG_FILE_PATH); + } + } diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/AddTaskHeaderCommand.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/AddTaskHeaderCommand.java index e108ce0..e1cbce4 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/AddTaskHeaderCommand.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/AddTaskHeaderCommand.java @@ -2,7 +2,6 @@ package eu.svjatoslav.alyverkko_cli.commands; import eu.svjatoslav.alyverkko_cli.Command; import eu.svjatoslav.alyverkko_cli.configuration.Configuration; -import eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper; import eu.svjatoslav.alyverkko_cli.configuration.Model; import java.io.*; @@ -10,7 +9,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.util.*; -import static eu.svjatoslav.alyverkko_cli.Utils.fileHasToComputeMarker; +import static eu.svjatoslav.alyverkko_cli.Utils.*; /** * This command recursively adds a TOCOMPUTE header to all non-hidden files in the current directory @@ -49,7 +48,7 @@ public class AddTaskHeaderCommand implements Command { @Override public void executeCommand(String[] cliArguments) throws IOException, InterruptedException { // Load configuration to validate skills and models - Configuration config = ConfigurationHelper.loadConfiguration(ConfigurationHelper.getConfigurationFile(null)); + Configuration config = loadConfiguration(getConfigurationFile(null)); if (config == null) { System.err.println("ERROR: Failed to load configuration file"); return; diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/JoinFilesCommand.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/JoinFilesCommand.java index 700b853..7f30f84 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/JoinFilesCommand.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/JoinFilesCommand.java @@ -14,8 +14,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.*; import static eu.svjatoslav.alyverkko_cli.Main.configuration; -import static eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper.getConfigurationFile; -import static eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper.loadConfiguration; +import static eu.svjatoslav.alyverkko_cli.Utils.getConfigurationFile; +import static eu.svjatoslav.alyverkko_cli.Utils.loadConfiguration; /** * The JoinFilesCommand aggregates multiple files (optionally matching @@ -94,7 +94,7 @@ public class JoinFilesCommand implements Command { */ @Override public void executeCommand(String[] cliArguments) throws IOException { - configuration = loadConfiguration(getConfigurationFile(null)); + configuration = loadConfiguration(getConfigurationFile(null)); if (configuration == null){ System.out.println("Failed to load configuration file"); return; diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/ListModelsCommand.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/ListModelsCommand.java index 6ffe1ba..63b6cab 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/ListModelsCommand.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/ListModelsCommand.java @@ -1,13 +1,11 @@ package eu.svjatoslav.alyverkko_cli.commands; import eu.svjatoslav.alyverkko_cli.Command; -import eu.svjatoslav.alyverkko_cli.configuration.ModelLibrary; +import eu.svjatoslav.alyverkko_cli.Utils; import java.io.IOException; import static eu.svjatoslav.alyverkko_cli.Main.configuration; -import static eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper.getConfigurationFile; -import static eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper.loadConfiguration; /** *

Displays all available AI models in the configured models directory. This command provides a quick overview of @@ -40,14 +38,13 @@ public class ListModelsCommand implements Command { */ @Override public void executeCommand(String[] cliArguments) throws IOException { - configuration = loadConfiguration(getConfigurationFile(null)); + configuration = Utils.loadConfiguration(Utils.getConfigurationFile(null)); if (configuration == null){ System.out.println("Failed to load configuration file"); return; } System.out.println("Listing models in directory: " + configuration.getModelsDirectory()); - ModelLibrary modelLibrary = new ModelLibrary(configuration.getModelsDirectory(), configuration.getModels()); - modelLibrary.printModels(); + configuration.printModels(); } } diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/WizardCommand.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/WizardCommand.java index 5056ecb..0d8c2b2 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/WizardCommand.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/WizardCommand.java @@ -3,8 +3,8 @@ package eu.svjatoslav.alyverkko_cli.commands; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import eu.svjatoslav.alyverkko_cli.Command; +import eu.svjatoslav.alyverkko_cli.Utils; import eu.svjatoslav.alyverkko_cli.configuration.Configuration; -import eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper; import eu.svjatoslav.alyverkko_cli.configuration.Model; import eu.svjatoslav.commons.cli_helper.parameter_parser.Parser; import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOption; @@ -15,7 +15,6 @@ import java.util.ArrayList; import java.util.List; import static eu.svjatoslav.alyverkko_cli.Utils.printRedMessageToConsole; -import static eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper.getConfigurationFile; import static eu.svjatoslav.commons.cli_helper.CLIHelper.*; /** @@ -67,7 +66,7 @@ public class WizardCommand implements Command { return; } - configurationFile = getConfigurationFile(configFileOption); + configurationFile = Utils.getConfigurationFile(configFileOption); loadOrCreateConfiguration(); checkAndFixGeneralParameters(); @@ -86,7 +85,7 @@ public class WizardCommand implements Command { if (configurationFile.exists()) { System.out.println("Found existing configuration at: \"" + configurationFile.getAbsolutePath() + "\""); - configuration = ConfigurationHelper.loadConfiguration(configurationFile); + configuration = Utils.loadConfiguration(configurationFile); } else { // If no config found, create a fresh one System.out.println("Existing configuration not found at \"" diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcess.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcess.java index 061991b..ad6f68a 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcess.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcess.java @@ -1,7 +1,6 @@ package eu.svjatoslav.alyverkko_cli.commands.task_processor; import eu.svjatoslav.alyverkko_cli.Utils; -import eu.svjatoslav.alyverkko_cli.configuration.ModelLibrary; import java.io.*; import java.nio.file.Files; @@ -39,7 +38,6 @@ public class TaskProcess { * The mail query defining system prompt, user prompt, and which model to use. */ private final Task task; - private final ModelLibrary modelLibrary; /** * Temporary file used as input to the llama.cpp CLI. @@ -50,11 +48,9 @@ public class TaskProcess { * Creates a new AI task with a given mail query. * * @param task the mail query containing model and prompts. - * @param modelLibrary model library containing all available models. */ - public TaskProcess(Task task, ModelLibrary modelLibrary) { + public TaskProcess(Task task) { this.task = task; - this.modelLibrary = modelLibrary; } /** @@ -169,7 +165,7 @@ public class TaskProcess { ArrayList args = new ArrayList<>(); args.add("nice -n " + niceValue); args.add(executablePath); - args.add("--model " + modelLibrary.getModelFullFilesystemPath(task.model)); + args.add("--model " + configuration.getModelFullFilesystemPath(task.model)); args.add("--threads " + configuration.getThreadCount()); args.add("--threads-batch " + configuration.getBatchThreadCount()); diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcessorCommand.java b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcessorCommand.java index 7ac02c2..0653afa 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcessorCommand.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/commands/task_processor/TaskProcessorCommand.java @@ -1,16 +1,12 @@ package eu.svjatoslav.alyverkko_cli.commands.task_processor; import eu.svjatoslav.alyverkko_cli.*; -import eu.svjatoslav.alyverkko_cli.configuration.ConfigurationHelper; import eu.svjatoslav.alyverkko_cli.configuration.Model; import eu.svjatoslav.alyverkko_cli.configuration.SkillConfig; -import eu.svjatoslav.alyverkko_cli.configuration.ModelLibrary; import eu.svjatoslav.commons.cli_helper.parameter_parser.Parser; import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOption; -import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; import java.nio.file.*; import java.util.*; @@ -56,11 +52,6 @@ public class TaskProcessorCommand implements Command { .addAliases("--config", "-c") .mustExist(); - /** - * The library of available models, constructed from configuration. - */ - ModelLibrary modelLibrary; - /** * The WatchService instance for monitoring file system changes in * the mail directory. @@ -98,13 +89,12 @@ public class TaskProcessorCommand implements Command { return; } - configuration = ConfigurationHelper.loadConfiguration(ConfigurationHelper.getConfigurationFile(configFileOption)); + configuration = Utils.loadConfiguration(Utils.getConfigurationFile(configFileOption)); if (configuration == null) { System.out.println("Failed to load configuration file"); return; } - modelLibrary = new ModelLibrary(configuration.getModelsDirectory(), configuration.getModels()); taskDirectory = configuration.getTasksDirectory(); // Set up a directory watch service @@ -245,7 +235,7 @@ public class TaskProcessorCommand implements Command { try { Task task = buildTaskFromFile(file); - TaskProcess aiTask = new TaskProcess(task, modelLibrary); + TaskProcess aiTask = new TaskProcess(task); String aiGeneratedResponse = aiTask.runAiQuery(); saveAiResponseToFile(file, task, aiGeneratedResponse); @@ -321,7 +311,7 @@ public class TaskProcessorCommand implements Command { // Set AI model using hierarchy: TOCOMPUTE > skill config > default String modelAlias = fileProcessingSettings.getOrDefault("model", skill.getModelAlias() != null ? skill.getModelAlias() : "default"); - Optional modelOptional = modelLibrary.findModelByAlias(modelAlias); + Optional modelOptional = configuration.findModelByAlias(modelAlias); if (!modelOptional.isPresent()) { throw new IllegalArgumentException("Model with alias '" + modelAlias + "' not found."); } diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/Configuration.java b/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/Configuration.java index abe5b33..1e425f9 100644 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/Configuration.java +++ b/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/Configuration.java @@ -5,6 +5,8 @@ import lombok.Data; import java.io.*; import java.util.List; +import java.util.Optional; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; @@ -115,4 +117,27 @@ public class Configuration { return mapper.readValue(promptFile, SkillConfig.class); } + + + /** + * Prints the details of each model in the library to standard output. + */ + public void printModels() { + System.out.println("Available models:\n"); + for (Model model : models) { + model.printModelDetails(); + System.out.println(); + } + } + + public String getModelFullFilesystemPath(Model model) { + return new File(modelsDirectory, model.getFilesystemPath()).getAbsolutePath(); + } + + public Optional findModelByAlias(String modelAlias) { + for (Model model : models) { + if (model.getAlias().equals(modelAlias)) return Optional.of(model); + } + return Optional.empty(); + } } diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ConfigurationHelper.java b/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ConfigurationHelper.java deleted file mode 100644 index 6c39b8a..0000000 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ConfigurationHelper.java +++ /dev/null @@ -1,58 +0,0 @@ -package eu.svjatoslav.alyverkko_cli.configuration; - -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; -import eu.svjatoslav.commons.cli_helper.parameter_parser.parameter.FileOption; - -import java.io.File; -import java.io.IOException; - -/** - *

Helper class for configuration file operations. Provides methods for loading configurations - * and determining the default configuration file path in the user's home directory. - *

Key functionality includes: - *

- */ -public class ConfigurationHelper { - - /** - * The default path for the YAML config file, typically under the user's home directory. - */ - public static final String DEFAULT_CONFIG_FILE_PATH = "~/.config/alyverkko-cli/alyverkko-cli.yaml".replaceFirst("^~", System.getProperty("user.home")); - - /** - * Loads the configuration from a given file, or from the default - * path if {@code configFile} is null. - * - * @param configFile the file containing the YAML config; may be null. - * @return the {@link Configuration} object, or null if not found/invalid. - * @throws IOException if file I/O fails during reading. - */ - public static Configuration loadConfiguration(File configFile) throws IOException { - - if (!configFile.exists()) { - System.err.println("Configuration file not found: " + configFile); - return null; - } - - ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); - return mapper.readValue(configFile, Configuration.class); - } - - /** - * Returns the configuration file from the given option, or the default path if not present. - * @param configFileOption the CLI option for the config file. - * @return the configuration file to load. - */ - public static File getConfigurationFile(FileOption configFileOption) { - if (configFileOption != null) - if (configFileOption.isPresent()) - return configFileOption.getValue(); - - return new File(DEFAULT_CONFIG_FILE_PATH); - } -} diff --git a/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ModelLibrary.java b/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ModelLibrary.java deleted file mode 100644 index 68c5ece..0000000 --- a/src/main/java/eu/svjatoslav/alyverkko_cli/configuration/ModelLibrary.java +++ /dev/null @@ -1,108 +0,0 @@ -package eu.svjatoslav.alyverkko_cli.configuration; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * A container (library) for multiple AI models, providing - * functionality for adding and retrieving models by alias. - */ -public class ModelLibrary { - - /** - * The list of all successfully loaded models in this library. - */ - private final List models; - - /** - * The default model for this library (e.g., the first successfully - * loaded model in the list). - */ - private static Model defaultModel; - - /** - * Base directory containing the model files. - */ - private final File modelsBaseDirectory; - - /** - * Constructs a library of AI models from the provided list of - * {@link Model}s, ignoring those whose paths do not exist. - * - * @param modelsBaseDirectory the root directory where model files are stored. - * @param configModels a list of model configurations. - */ - public ModelLibrary(File modelsBaseDirectory, List configModels) { - this.modelsBaseDirectory = modelsBaseDirectory; - this.models = new ArrayList<>(); - - for (Model configModel : configModels) { - addModel(configModel); - } - - if (models.isEmpty()) { - throw new RuntimeException("No models are defined!"); - } - - defaultModel = models.get(0); - } - - - /** - * Adds a model to the library if no model with the same alias - * already exists. - * - * @param model the model to add. - * @throws RuntimeException if a model with the same alias already exists. - */ - public void addModel(Model model) { - if (findModelByAlias(model.getAlias()).isPresent()) { - throw new RuntimeException("Model with alias \"" + model.getAlias() + "\" already exists!"); - } - models.add(model); - } - - /** - * @return the list of loaded models in this library. - */ - public List getModels() { - return models; - } - - /** - * Finds a model by its alias in this library. - * - * @param alias the model alias to look for. - * @return an {@link Optional} describing the found model, or empty if none match. - */ - public Optional findModelByAlias(String alias) { - return models.stream() - .filter(model -> model.getAlias().equals(alias)) - .findFirst(); - } - - /** - * @return the default model (first loaded model). - */ - public Model getDefaultModel() { - return defaultModel; - } - - /** - * Prints the details of each model in the library to standard output. - */ - public void printModels() { - System.out.println("Available models:\n"); - for (Model model : models) { - model.printModelDetails(); - System.out.println(); - } - } - - public String getModelFullFilesystemPath(Model model) { - return new File(modelsBaseDirectory, model.getFilesystemPath()).getAbsolutePath(); - } - -} \ No newline at end of file