diff --git a/vscode/media/walkthroughs/enable-generativeAI.md b/vscode/media/walkthroughs/enable-generativeAI.md new file mode 100644 index 00000000..aa88964f --- /dev/null +++ b/vscode/media/walkthroughs/enable-generativeAI.md @@ -0,0 +1,3 @@ +# Enable GenerativeAI + +Configure Generative AI by enabling its functionality. The package includes a default binary, but you can override it using the override command. \ No newline at end of file diff --git a/vscode/media/walkthroughs/override-analyzer.md b/vscode/media/walkthroughs/override-analyzer.md index 409f3ceb..e064ce83 100644 --- a/vscode/media/walkthroughs/override-analyzer.md +++ b/vscode/media/walkthroughs/override-analyzer.md @@ -1,6 +1,5 @@ # Override Analyzer Binary -The Konveyor extension comes packaged with a default analyzer binary. However, -you may want to use a custom or updated version of the analyzer. +The Konveyor extension comes packaged with default analyzer and Generative AI binaries. However, you may want to use a custom or updated version of these binaries. -To override the default analyzer run the [Konveyor: Override Analyzer Binaries](command:konveyor.overrideAnalyzerBinaries) command. +To override the default analyzer, run the [Konveyor: Override Analyzer Binaries](command:konveyor.overrideAnalyzerBinaries) command, and to override the Generative AI binary, run the[Konveyor: Override Generative AI Binaries](command:konveyor.overriderpcServerBinaries) command. \ No newline at end of file diff --git a/vscode/package.json b/vscode/package.json index 55f6c5af..195ac487 100644 --- a/vscode/package.json +++ b/vscode/package.json @@ -39,6 +39,12 @@ "category": "Konveyor", "icon": "$(gear)" }, + { + "command": "konveyor.overriderpcServerBinaries", + "title": "Override Generative AI Binaries", + "category": "Konveyor", + "icon": "$(gear)" + }, { "command": "konveyor.configureCustomRules", "title": "Configure Custom Rules", @@ -68,6 +74,12 @@ "title": "Run Analysis", "category": "Konveyor", "icon": "$(play}" + }, + { + "command": "konveyor.toggleGenerativeAI", + "title": "Toggle GenerativeAI", + "category": "Konveyor", + "icon": "$(gear}" } ], "submenus": [ @@ -129,6 +141,13 @@ "scope": "machine", "order": 0 }, + "konveyor.rpcServerPath": { + "type": "string", + "default": "", + "description": "Path to the rpc-server binary. If not set, the extension will use the bundled binary.", + "scope": "machine", + "order": 0 + }, "konveyor.incidentLimit": { "type": "number", "default": 10000, @@ -194,6 +213,13 @@ "description": "Whether analysis of file should be run when saved", "scope": "window", "order": 9 + }, + "konveyor.enableGenerativeAI": { + "type": "boolean", + "default": true, + "description": "Enable Generative AI set ", + "scope": "window", + "order": 10 } } }, @@ -203,10 +229,21 @@ "title": "Set up Konveyor", "description": "Configure Konveyor for your project", "steps": [ + { + "id": "enable-generativeAI", + "title": "Configure GenerativeAI", + "description": "Generative AI is enabled by default. Use the buttons to toggle. \n[Enable](command:konveyor.toggleGenerativeAI)", + "completionEvents": [ + "onCommand:konveyor.toggleGenerativeAI" + ], + "media": { + "markdown": "media/walkthroughs/enable-generativeAI.md" + } + }, { "id": "override-analyzer", "title": "Override Analyzer Binary", - "description": "Specify a custom path for the analyzer binary\n[Override Analyzer Binary](command:konveyor.overrideAnalyzerBinaries)", + "description": "Specify a custom path for the analyzer binary\n[Override Analyzer Binary](command:konveyor.overrideAnalyzerBinaries)\n[Override GenerativeAI Binary](command:konveyor.overriderpcServerBinaries)", "completionEvents": [], "media": { "markdown": "media/walkthroughs/override-analyzer.md" diff --git a/vscode/src/client/analyzerClient.ts b/vscode/src/client/analyzerClient.ts index 47bb728b..42a30002 100644 --- a/vscode/src/client/analyzerClient.ts +++ b/vscode/src/client/analyzerClient.ts @@ -24,7 +24,7 @@ export class AnalyzerClient { } public start(): void { - if (!this.canAnalyze) { + if (!this.canAnalyze()) { return; } exec("java -version", (err) => { @@ -40,17 +40,33 @@ export class AnalyzerClient { } }); - this.analyzerServer = spawn(this.getAnalyzerPath(), this.getAnalyzerArgs(), { - cwd: this.extContext!.extensionPath, - }); - + let serverType: string; + // Determine the server type and path + if (this.isGenAiEnabled()) { + serverType = "Generative AI (rpcServer)"; + this.analyzerServer = spawn(this.getRpcServerPath(), { + cwd: this.extContext!.extensionPath, + }); + } else { + serverType = "Analyzer"; + this.analyzerServer = spawn(this.getAnalyzerPath(), this.getAnalyzerArgs(), { + cwd: this.extContext!.extensionPath, + }); + } this.analyzerServer.stderr.on("data", (data) => { - this.outputChannel.appendLine(`${data.toString()}`); + this.outputChannel.appendLine(`${serverType} Error: ${data.toString()}`); }); this.analyzerServer.on("exit", (code) => { - this.outputChannel.appendLine(`Analyzer exited with code ${code}`); + this.outputChannel.appendLine(`${serverType} server exited with code ${code}`); }); + + this.outputChannel.appendLine(`${serverType} server started successfully.`); + } + + // Check if Generative AI is enabled + public isGenAiEnabled(): boolean { + return this.config?.get("enableGenerativeAI", true) || false; } // Stops the analyzer server @@ -223,6 +239,11 @@ export class AnalyzerClient { } public getAnalyzerPath(): string { + const analyzerPath = this.config?.get("analyzerPath"); + if (analyzerPath && fs.existsSync(analyzerPath)) { + return analyzerPath; + } + const platform = os.platform(); const arch = os.arch(); @@ -232,14 +253,52 @@ export class AnalyzerClient { } // Full path to the analyzer binary - const analyzerPath = path.join(this.extContext!.extensionPath, "assets", "bin", binaryName); + const defaultAnalyzerPath = path.join( + this.extContext!.extensionPath, + "assets", + "bin", + binaryName, + ); // Check if the binary exists - if (!fs.existsSync(analyzerPath)) { - vscode.window.showErrorMessage(`Analyzer binary doesn't exist at ${analyzerPath}`); + if (!fs.existsSync(defaultAnalyzerPath)) { + vscode.window.showErrorMessage(`Analyzer binary doesn't exist at ${defaultAnalyzerPath}`); + } + + return defaultAnalyzerPath; + } + public getRpcServerPath(): string { + // Retrieve the rpcServerPath + const rpcServerPath = this.config?.get("rpcServerPath"); + if (rpcServerPath && fs.existsSync(rpcServerPath)) { + return rpcServerPath; + } + + // Fallback to default rpc-server binary path if user did not provid path + const platform = os.platform(); + const arch = os.arch(); + + let binaryName = `kai-rpc-server.${platform}.${arch}`; + if (platform === "win32") { + binaryName += ".exe"; + } + + // Construct the full path + const defaultRpcServerPath = path.join( + this.extContext!.extensionPath, + "assets", + "bin", + binaryName, + ); + + // Check if the default rpc-server binary exists, else show an error message + if (!fs.existsSync(defaultRpcServerPath)) { + vscode.window.showErrorMessage(`RPC server binary doesn't exist at ${defaultRpcServerPath}`); + throw new Error(`RPC server binary not found at ${defaultRpcServerPath}`); } - return analyzerPath; + // Return the default path + return defaultRpcServerPath; } public getAnalyzerArgs(): string[] { diff --git a/vscode/src/commands.ts b/vscode/src/commands.ts index 0787aa35..cc2c5564 100644 --- a/vscode/src/commands.ts +++ b/vscode/src/commands.ts @@ -146,6 +146,30 @@ const commandsMap: (state: ExtensionState) => { window.showInformationMessage("No analyzer binary selected."); } }, + "konveyor.overriderpcServerBinaries": async () => { + const options: OpenDialogOptions = { + canSelectMany: false, + openLabel: "Select GenAI Binary", + filters: { + "Executable Files": ["exe", "sh", "bat", ""], + "All Files": ["*"], + }, + }; + + const fileUri = await window.showOpenDialog(options); + + if (fileUri && fileUri[0]) { + const filePath = fileUri[0].fsPath; + + // Update the user settings + const config = workspace.getConfiguration("konveyor"); + await config.update("rpcServerPath", filePath, ConfigurationTarget.Global); + + window.showInformationMessage(`rpc server binary path updated to: ${filePath}`); + } else { + window.showInformationMessage("No rpc-server binary selected."); + } + }, "konveyor.configureCustomRules": async () => { const options: OpenDialogOptions = { canSelectMany: true, @@ -303,6 +327,22 @@ const commandsMap: (state: ExtensionState) => { // Update the user settings await config.update("labelSelector", modifiedLabelSelector, ConfigurationTarget.Workspace); }, + "konveyor.toggleGenerativeAI": async () => { + const options = ["Yes", "No"]; + const selection = await window.showQuickPick(options, { + placeHolder: "Enable Generative AI?", + }); + + if (selection === "Yes") { + const config = workspace.getConfiguration("konveyor"); + await config.update("enableGenerativeAI", true, ConfigurationTarget.Workspace); + window.showInformationMessage("Generative AI is now enabled."); + } else if (selection === "No") { + const config = workspace.getConfiguration("konveyor"); + await config.update("enableGenerativeAI", false, ConfigurationTarget.Workspace); + window.showInformationMessage("Generative AI is now disabled."); + } + }, }; };