diff --git a/cookbook/rules/quarkus-spring/010-springboot-replace-bom-quarkus.yaml b/cookbook/rules/quarkus-spring/010-springboot-replace-bom-quarkus.yaml index e35be3b0..12468f5e 100644 --- a/cookbook/rules/quarkus-spring/010-springboot-replace-bom-quarkus.yaml +++ b/cookbook/rules/quarkus-spring/010-springboot-replace-bom-quarkus.yaml @@ -13,6 +13,9 @@ order: 1 instructions: ai: + - skills: + - "spring-boot-to-quarkus/check-jdk" + - "spring-boot-to-quarkus/configuration" - tasks: - "Add to the pom.xml file the Quarkus BOM dependency version 3.31.3 within the dependencyManagement section and the following dependencies: quarkus-arc, quarkus-core and quarkus-smallrye-openapi" - "Remove next from the ôpm.xml the plugin org.springframework.boot:spring-boot-maven-plugin" diff --git a/migration-cli/pom.xml b/migration-cli/pom.xml index 7cf4818c..a09273da 100644 --- a/migration-cli/pom.xml +++ b/migration-cli/pom.xml @@ -81,7 +81,12 @@ io.quarkiverse.langchain4j quarkus-langchain4j-openai - 1.8.4 + ${quarkus-langchain4j.version} + + + io.quarkiverse.langchain4j + quarkus-langchain4j-skills + ${quarkus-langchain4j.version} diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/commands/TransformCommand.java b/migration-cli/src/main/java/dev/snowdrop/mtool/commands/TransformCommand.java index 29cbb2d0..c8614d6d 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/commands/TransformCommand.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/commands/TransformCommand.java @@ -6,6 +6,7 @@ import dev.snowdrop.mtool.model.transform.MigrationTasksExport; import dev.snowdrop.mtool.transform.provider.ai.Assistant; import dev.snowdrop.mtool.transform.provider.ai.FileSystemTool; +import dev.snowdrop.mtool.transform.provider.ai.SkillsAssistant; import dev.snowdrop.mtool.transform.provider.impl.OpenRewriteProvider; import dev.snowdrop.mtool.transform.provider.model.ExecutionContext; import dev.snowdrop.mtool.transform.provider.model.ExecutionResult; @@ -40,7 +41,7 @@ public class TransformCommand implements Runnable { private boolean dryRun; @CommandLine.Option(names = { "-p", - "--provider" }, description = "Migration provider to use (ai, openrewrite, manual). Default: from migration.provider property") + "--provider" }, description = "Migration provider to use (ai, ai-skill, openrewrite, manual). Default: from migration.provider property") @ConfigProperty(name = "migration.provider") private String provider; @@ -50,9 +51,15 @@ public class TransformCommand implements Runnable { @ConfigProperty(name = "openrewrite.maven-plugin.version") private String openRewriteMavenPluginVersion; + @ConfigProperty(name = "quarkus.langchain4j.skills.directories") + private String aiAgentSkillsHomeDir; + @Inject Assistant aiAssistant; + @Inject + SkillsAssistant aiSkillsAssistant; + @Inject FileSystemTool fileSystemTool; @@ -162,8 +169,8 @@ private void startTransformation() { // Configure the Context with the information used by the Provider fileSystemTool.setBasePath(projectPath); - ExecutionContext context = new ExecutionContext(projectPath, verbose, dryRun, provider, aiAssistant, - openRewriteMavenPluginVersion, compositeRecipeName); + ExecutionContext context = new ExecutionContext(projectPath, verbose, dryRun, provider, aiAssistant, aiSkillsAssistant, + aiAgentSkillsHomeDir, openRewriteMavenPluginVersion, compositeRecipeName); if ("openrewrite".equals(provider)) { // Batch all OpenRewrite tasks into a single Maven execution @@ -212,7 +219,7 @@ private void executeTaskWithProvider(String taskId, MigrationTask task, Executio var instructions = task.getRule().instructions(); boolean hasInstructions = instructions != null && switch (provider) { case "openrewrite" -> instructions.openrewrite() != null; - case "ai" -> instructions.ai() != null; + case "ai", "ai-skills" -> instructions.ai() != null; case "manual" -> instructions.manual() != null; default -> false; }; diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/TransformationService.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/TransformationService.java index eb1ae673..fcdeed0d 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/TransformationService.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/TransformationService.java @@ -27,6 +27,8 @@ public class TransformationService { public void logExecutionResult(ExecutionResult result, boolean verbose) { if (result.success()) { logger.infof("Task completed successfully: %s", result.message()); + } else if (result.warning() != null) { + logger.warn(result.warning()); } else { logger.errorf("Task failed: %s", result.message()); if (result.exception() != null && verbose) { @@ -62,6 +64,8 @@ public ExecutionResult execute(MigrationTask task, ExecutionContext ctx) { if (result.success()) { return ExecutionResult.success(String.format(" %s execution completed successfully", ctx.provideType()), allDetails); + } else if (result.warning() != null) { + return ExecutionResult.warning(String.format(" %s for provider: %s", result.warning(), ctx.provideType())); } else { return ExecutionResult.failure(String.format(" %s execution failed !", ctx.provideType())); } diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ProviderFactory.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ProviderFactory.java index 78500a99..bc0f9595 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ProviderFactory.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ProviderFactory.java @@ -1,6 +1,7 @@ package dev.snowdrop.mtool.transform.provider; import dev.snowdrop.mtool.transform.provider.impl.AiProvider; +import dev.snowdrop.mtool.transform.provider.impl.AiSkillsProvider; import dev.snowdrop.mtool.transform.provider.impl.ManualProvider; import dev.snowdrop.mtool.transform.provider.impl.OpenRewriteProvider; @@ -18,6 +19,7 @@ public class ProviderFactory { static { registerProvider(new OpenRewriteProvider()); registerProvider(new AiProvider()); + registerProvider(new AiSkillsProvider()); registerProvider(new ManualProvider()); } diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/SkillsEnabledProvider.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/SkillsEnabledProvider.java new file mode 100644 index 00000000..9b6c1625 --- /dev/null +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/SkillsEnabledProvider.java @@ -0,0 +1,8 @@ +package dev.snowdrop.mtool.transform.provider; + +import dev.snowdrop.mtool.transform.provider.model.ExecutionContext; +import dev.snowdrop.mtool.transform.provider.model.ExecutionResult; + +public interface SkillsEnabledProvider extends MigrationProvider { + ExecutionResult execute(String skillPath, ExecutionContext context); +} \ No newline at end of file diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/FileSystemTool.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/FileSystemTool.java index 5a71f83b..2a339736 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/FileSystemTool.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/FileSystemTool.java @@ -9,6 +9,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; /** * A LangChain4j tool that exposes file system read and write operations to AI agents. @@ -63,7 +65,29 @@ public String readFile(@P("Path to the file to analyze") String path) { logger.debugf("Reading file: %s", resolved); return Files.readString(resolved); } catch (IOException e) { - return "Error reading file: " + e.getMessage(); + return String.format("Skip the path: %s as this %s", path, e.getMessage()); + } + } + + @Tool("Whenever you need to know the files part of an application to understand the java project structure") + public List listFiles(@P("The relative path from the project root. Use '.' for the root directory. " + + "Example: 'src/main/java' or 'src/test/resources'. " + + "Do not use absolute paths or leading slashes.") String path) + throws IOException { + + Path resolved = resolve(path); + + if (!resolved.startsWith(basePath)) { + return List.of("Error: Access denied. You cannot look outside the project root."); + } + + if (!Files.exists(resolved)) { + return List.of("Error: Directory does not exist: " + path); + } + + try (var stream = Files.list(resolved)) { + return stream.map(p -> basePath.relativize(p).toString()) + .collect(Collectors.toList()); } } diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/SkillsAssistant.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/SkillsAssistant.java new file mode 100644 index 00000000..d3bd6ea7 --- /dev/null +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/ai/SkillsAssistant.java @@ -0,0 +1,13 @@ +package dev.snowdrop.mtool.transform.provider.ai; + +import dev.langchain4j.model.chat.response.StreamingChatResponseHandler; +import io.quarkiverse.langchain4j.RegisterAiService; +import io.quarkiverse.langchain4j.ToolBox; +import jakarta.enterprise.context.ApplicationScoped; + +@RegisterAiService +@ApplicationScoped +public interface SkillsAssistant { + @ToolBox(FileSystemTool.class) + String chat(String message); +} diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiProvider.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiProvider.java index 90c5bed0..dbd2ed51 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiProvider.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiProvider.java @@ -74,7 +74,7 @@ private ExecutionResult executeAiInstruction(Rule.Ai ai, Rule rule, ExecutionCon details.add("- " + task); }); - boolean success = execAiCmd(context, tasks, details); + boolean success = execAiCmd(context, tasks); details.add("Ai cmd executed successfully"); if (success) { @@ -84,7 +84,7 @@ private ExecutionResult executeAiInstruction(Rule.Ai ai, Rule rule, ExecutionCon } } - private boolean execAiCmd(ExecutionContext ctx, List tasks, List details) { + private boolean execAiCmd(ExecutionContext ctx, List tasks) { logger.info("Hello! I'm your AI migration assistant and I will help you move your code"); tasks.forEach(t -> { diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiSkillsProvider.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiSkillsProvider.java new file mode 100644 index 00000000..3a40fb81 --- /dev/null +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/impl/AiSkillsProvider.java @@ -0,0 +1,157 @@ +package dev.snowdrop.mtool.transform.provider.impl; + +import dev.langchain4j.model.chat.ChatModel; +import dev.langchain4j.model.chat.response.*; +import dev.langchain4j.service.AiServices; +import dev.langchain4j.skills.FileSystemSkillLoader; +import dev.langchain4j.skills.Skills; +import dev.snowdrop.mtool.model.analyze.MigrationTask; +import dev.snowdrop.mtool.model.analyze.Rule; +import dev.snowdrop.mtool.transform.provider.MigrationProvider; +import dev.snowdrop.mtool.transform.provider.ai.FileSystemTool; +import dev.snowdrop.mtool.transform.provider.ai.SkillsAssistant; +import dev.snowdrop.mtool.transform.provider.model.ExecutionContext; +import dev.snowdrop.mtool.transform.provider.model.ExecutionResult; +import io.quarkiverse.langchain4j.vertexai.runtime.anthropic.VertexAiAnthropicChatModel; +import org.jboss.logging.Logger; + +import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static dev.langchain4j.model.LambdaStreamingResponseHandler.onPartialResponse; + +public class AiSkillsProvider implements MigrationProvider { + private static final Logger logger = Logger.getLogger(AiSkillsProvider.class); + private ChatModel model; + + public AiSkillsProvider() { + String projectId = getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_PROJECT_ID", "dummy"); + String location = getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_LOCATION", "dummy"); + String modelId = getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_MODEL_ID", "claude-opus-4-6"); + String publisher = getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_PUBLISHER", "anthropic"); + int duration = Integer.parseInt(getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_DURATION", "30")); + int maxTokens = Integer.parseInt(getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_MAX_TOKENS", "1000")); + Boolean logRequests = Boolean.valueOf(getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_LOG_REQUESTS", "false")); + Boolean logResponses = Boolean.valueOf(getEnv("QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_LOG_RESPONSES", "false")); + + validateRequired(projectId, "QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_PROJECT_ID"); + validateRequired(location, "QUARKUS_LANGCHAIN4J_VERTEXAI_ANTHROPIC_LOCATION"); + + model = VertexAiAnthropicChatModel.builder() + .projectId(projectId) + .location(location) + .modelId(modelId) + .publisher(publisher) + .maxOutputTokens(maxTokens) + .timeout(Duration.ofSeconds(duration)) + .logRequests(logRequests) + .logResponses(logResponses) + .build(); + } + + @Override + public String getProviderType() { + return "ai-skills"; + } + + @Override + public ExecutionResult execute(MigrationTask task, ExecutionContext context) { + + // We only process until now only one instruction/rule ! + var ai = Arrays.stream(task.getRule().instructions().ai()).findFirst().orElse(null); + + assert ai != null; + if (ai.skills() == null || ai.skills().isEmpty()) { + return ExecutionResult + .warning(String.format("No AI Skills defined part of the rule: %s. Skipping", task.getRule().ruleID())); + } + + try { + ExecutionResult result = executeAiInstruction(ai, task.getRule(), context); + + if (!result.success()) { + return ExecutionResult.failure(result.message(), result.details(), null); + } + + return ExecutionResult.success("AI SKILL execution completed successfully", result.details()); + } catch (Exception e) { + logger.errorf("Error executing AI SKILL: %s", e.getMessage()); + if (context.verbose()) { + e.printStackTrace(); + } + return ExecutionResult.failure("Error executing AI SKILL !", e); + } + } + + private ExecutionResult executeAiInstruction(Rule.Ai ai, Rule rule, ExecutionContext context) { + List details = new ArrayList<>(); + + details.add("Processing rule : " + "" + rule.ruleID()); + + var skills = ai.skills(); + + if (skills == null || skills.isEmpty()) { + return ExecutionResult.failure( + String.format("No AI SKILL defined for rule %s, skipping", rule.ruleID()), null); + } + + // Get the list of SKILL + skills.forEach(skill -> { + logger.infof("Skill: %s", skill); + details.add("- " + skill); + }); + + boolean success = execAiSkillCmd(context, skills); + details.add("AI SKILL cmd executed successfully"); + + if (success) { + return ExecutionResult.success("AI instruction executed successfully", details); + } else { + return ExecutionResult.failure("AI's chat command execution failed", details, null); + } + } + + private boolean execAiSkillCmd(ExecutionContext ctx, List skills) { + logger.info("Hello! I'm your AI SKILL migration assistant and I will help you moving your code"); + + // TODO: Have a property to set the SKILL Agent home folder + // Claude: .claude/skills + + skills.forEach(s -> { + logger.infof("=== Processing SKILL: %S", s); + Skills agentSkill = Skills.from(FileSystemSkillLoader.loadSkill(Path.of(ctx.aiSkillsHomeDir(), s))); + SkillsAssistant service = AiServices.builder(SkillsAssistant.class) + .chatModel(model) + .systemMessage(agentSkill.formatAvailableSkills()) + .maxSequentialToolsInvocations(100) + .build(); + + String response = service + .chat(String.format("Migrate the application of the current directory using the SKILL: %s", s)); + logger.infof("=== Model response: %s", response); + }); + + return true; + } + + /** + * Helper to get Env Var or return a default. + */ + private static String getEnv(String name, String defaultValue) { + String val = System.getenv(name); + return (val != null && !val.isBlank()) ? val : defaultValue; + } + + /** + * Helper to enforce required fields. + */ + private static void validateRequired(String value, String envName) { + if (value == null || value.isBlank() || value.equals("dummy")) { + throw new IllegalStateException( + "CRITICAL ERROR: The environment variable '" + envName + "' is required but not set."); + } + } +} diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionContext.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionContext.java index 9102a41a..1d4c8986 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionContext.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionContext.java @@ -1,6 +1,7 @@ package dev.snowdrop.mtool.transform.provider.model; import dev.snowdrop.mtool.transform.provider.ai.Assistant; +import dev.snowdrop.mtool.transform.provider.ai.SkillsAssistant; import java.nio.file.Path; @@ -8,5 +9,6 @@ * Context information for provider execution including project settings and configuration. */ public record ExecutionContext(Path projectPath, boolean verbose, boolean dryRun, String provideType, - Assistant assistant, String openRewriteMavenPluginVersion, String compositeRecipeName) { + Assistant assistant, SkillsAssistant aiSkillsAssistant, String aiSkillsHomeDir, String openRewriteMavenPluginVersion, + String compositeRecipeName) { } \ No newline at end of file diff --git a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionResult.java b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionResult.java index 0d8f79d4..3d3fd1d0 100644 --- a/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionResult.java +++ b/migration-cli/src/main/java/dev/snowdrop/mtool/transform/provider/model/ExecutionResult.java @@ -5,40 +5,54 @@ /** * Result of a provider execution with success status and details. */ -public record ExecutionResult(boolean success, String message, List details, Exception exception) { +public record ExecutionResult(boolean success, String message, List details, String warning, Exception exception) { /** * Creates a successful execution result. */ public static ExecutionResult success(String message) { - return new ExecutionResult(true, message, List.of(), null); + return new ExecutionResult(true, message, List.of(), null, null); } /** * Creates a successful execution result with details. */ public static ExecutionResult success(String message, List details) { - return new ExecutionResult(true, message, details, null); + return new ExecutionResult(true, message, details, null, null); + } + + /** + * Creates an execution result with warning. + */ + public static ExecutionResult warning(String warning) { + return new ExecutionResult(false, null, List.of(), warning, null); + } + + /** + * Creates a successful execution result with details and a warning. + */ + public static ExecutionResult warning(List details, String warning) { + return new ExecutionResult(false, null, details, warning, null); } /** * Creates a failed execution result. */ public static ExecutionResult failure(String message) { - return new ExecutionResult(false, message, List.of(), null); + return new ExecutionResult(false, message, List.of(), null, null); } /** * Creates a failed execution result with exception. */ public static ExecutionResult failure(String message, Exception exception) { - return new ExecutionResult(false, message, List.of(), exception); + return new ExecutionResult(false, message, List.of(), null, exception); } /** * Creates a failed execution result with details and exception. */ public static ExecutionResult failure(String message, List details, Exception exception) { - return new ExecutionResult(false, message, details, exception); + return new ExecutionResult(false, message, details, null, exception); } } \ No newline at end of file diff --git a/migration-cli/src/main/resources/application.properties b/migration-cli/src/main/resources/application.properties index a3470378..0fadb345 100644 --- a/migration-cli/src/main/resources/application.properties +++ b/migration-cli/src/main/resources/application.properties @@ -38,6 +38,8 @@ quarkus.log.category."dev.snowdrop.mtool.transform".level=INFO quarkus.langchain4j.log-requests=false quarkus.langchain4j.log-responses=false quarkus.langchain4j.timeout=30S +quarkus.langchain4j.skills.directories=~/.claude/skills + # Default LLM enabled quarkus.langchain4j.chat-model.provider=vertexai-anthropic diff --git a/model/src/main/java/dev/snowdrop/mtool/model/analyze/Rule.java b/model/src/main/java/dev/snowdrop/mtool/model/analyze/Rule.java index 50bd2f5a..c8b75d74 100644 --- a/model/src/main/java/dev/snowdrop/mtool/model/analyze/Rule.java +++ b/model/src/main/java/dev/snowdrop/mtool/model/analyze/Rule.java @@ -14,7 +14,7 @@ public record Rule(String category, @JsonProperty("customVariables") List tasks) { + public record Ai(@Deprecated String promptMessage, List tasks, List skills) { } public record Manual(String todo) { diff --git a/pom.xml b/pom.xml index de5822b8..2a5be57c 100644 --- a/pom.xml +++ b/pom.xml @@ -25,14 +25,13 @@ 2.13.2 1.46.0 2.18.0 - 1.13.0 - 1.13.0-beta23 + 1.13.0 1.18.44 0.24.0 3.27.1 5.12.0 0.20.3 - 1.8.4 + 1.9.0.CR2 3.31.3 1.6.1 0.3.4 @@ -100,6 +99,14 @@ import + + dev.langchain4j + langchain4j-bom + ${langchain4j-bom.version} + pom + import + + org.openrewrite.recipe rewrite-recipe-bom @@ -107,6 +114,7 @@ pom import + org.projectlombok lombok @@ -175,16 +183,6 @@ quarkus-langchain4j-agentic ${quarkus-langchain4j.version} - - dev.langchain4j - langchain4j-anthropic - ${langchain4j-anthropic.version} - - - dev.langchain4j - langchain4j-vertex-ai-anthropic - ${langchain4j-vertex-ai-anthropic.version} - io.quarkiverse.langchain4j quarkus-langchain4j-testing-internal diff --git a/tests/src/test/java/dev/snowdrop/mtool/tests/analyze/RulesTest.java b/tests/src/test/java/dev/snowdrop/mtool/tests/analyze/RulesTest.java index 69cf952a..cf6bf331 100644 --- a/tests/src/test/java/dev/snowdrop/mtool/tests/analyze/RulesTest.java +++ b/tests/src/test/java/dev/snowdrop/mtool/tests/analyze/RulesTest.java @@ -20,10 +20,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -144,7 +141,8 @@ private Rule createRule001_ReplaceBomQuarkus() { // promptMessage (deprecated en favor de tasks) Arrays.asList( "Add to the pom.xml file the Quarkus BOM dependency within the dependencyManagement section and the following dependencies: quarkus-arc, quarkus-core", - "The version of quarkus to be used and to included within the pom.xml properties is 3.31.3.")) }; + "The version of quarkus to be used and to included within the pom.xml properties is 3.31.3."), + new ArrayList<>()) }; // Manual Instructions Rule.Manual[] manualInstructions = new Rule.Manual[] { new Rule.Manual( @@ -182,7 +180,7 @@ private Rule createRule002_AddQuarkusClass() { // AI Instructions Rule.Ai[] aiInstructions = new Rule.Ai[] { new Rule.Ai(null, // promptMessage (deprecated en favor de tasks) - aiTasks) }; + aiTasks, new ArrayList<>()) }; // Manual Instructions Rule.Manual[] manualInstructions = new Rule.Manual[] { new Rule.Manual("See openrewrite instructions") }; @@ -220,7 +218,7 @@ private Rule createRule003_QuarkusMainAnnotation() { // AI Instructions Rule.Ai[] aiInstructions = new Rule.Ai[] { new Rule.Ai(null, // promptMessage (deprecated en favor de tasks) - aiTasks) }; + aiTasks, new ArrayList<>()) }; // Manual Instructions Rule.Manual[] manualInstructions = new Rule.Manual[] { new Rule.Manual("See openrewrite instructions") }; @@ -229,7 +227,7 @@ private Rule createRule003_QuarkusMainAnnotation() { Rule.Openrewrite[] openrewriteInstructions = new Rule.Openrewrite[] { new Rule.Openrewrite( "Replace the SpringBoot parent dependency with Quarkus BOM within the pom.xml file", "Replace the SpringBoot parent dependency with Quarkus BOM within the pom.xml file.", null, // preconditions - null, // recipeList (aquí podrías añadir los recipes si los necesitas) + null, // recipeList (You could add the recipes here if you need them.) new String[] { "dev.snowdrop.mtool:openrewrite-recipes:1.0.0-SNAPSHOT", "org.openrewrite:rewrite-maven:8.73.0" }) }; @@ -262,8 +260,8 @@ private Rule createRule004_RestAnnotations() { // AI Instructions Rule.Ai[] aiInstructions = new Rule.Ai[] { new Rule.Ai(null, - // promptMessage (deprecated en favor de tasks) - List.of("TODO")) }; + // promptMessage (deprecated in favor of tasks) + List.of("TODO"), new ArrayList<>()) }; // Manual Instructions Rule.Manual[] manualInstructions = new Rule.Manual[] { new Rule.Manual("See openrewrite instructions") };