diff --git a/sema4ai-code/codegen/commands.py b/sema4ai-code/codegen/commands.py index cedce921..9b425b90 100644 --- a/sema4ai-code/codegen/commands.py +++ b/sema4ai-code/codegen/commands.py @@ -694,13 +694,6 @@ def __init__( hide_from_command_palette=True, icon="$(type-hierarchy-sub)", ), - Command( - "sema4ai.convertProject", - "Conversion Accelerator from third party RPA to Robocorp Task Package (Robot)", - add_to_package_json=True, - server_handled=False, - hide_from_command_palette=False, - ), Command( "sema4ai.profileImport", "Import Profile", diff --git a/sema4ai-code/package.json b/sema4ai-code/package.json index b6f3e364..409183cb 100644 --- a/sema4ai-code/package.json +++ b/sema4ai-code/package.json @@ -113,7 +113,6 @@ "onCommand:sema4ai.showOutput", "onCommand:sema4ai.showInterpreterEnvError", "onCommand:sema4ai.openFlowExplorerTreeSelection", - "onCommand:sema4ai.convertProject", "onCommand:sema4ai.profileImport", "onCommand:sema4ai.profileImport.internal", "onCommand:sema4ai.profileSwitch", @@ -750,11 +749,6 @@ "category": "Sema4.ai", "icon": "$(type-hierarchy-sub)" }, - { - "command": "sema4ai.convertProject", - "title": "Conversion Accelerator from third party RPA to Robocorp Task Package (Robot)", - "category": "Sema4.ai" - }, { "command": "sema4ai.profileImport", "title": "Import Profile", diff --git a/sema4ai-code/src/sema4ai_code/commands.py b/sema4ai-code/src/sema4ai_code/commands.py index 40b102b9..0fb99364 100644 --- a/sema4ai-code/src/sema4ai_code/commands.py +++ b/sema4ai-code/src/sema4ai_code/commands.py @@ -95,7 +95,6 @@ SEMA4AI_SHOW_OUTPUT = "sema4ai.showOutput" # Show Sema4.ai Code > Output logs SEMA4AI_SHOW_INTERPRETER_ENV_ERROR = "sema4ai.showInterpreterEnvError" # Show error related to interpreter env creation SEMA4AI_OPEN_FLOW_EXPLORER_TREE_SELECTION = "sema4ai.openFlowExplorerTreeSelection" # Open Flow Explorer -SEMA4AI_CONVERT_PROJECT = "sema4ai.convertProject" # Conversion Accelerator from third party RPA to Robocorp Task Package (Robot) SEMA4AI_PROFILE_IMPORT = "sema4ai.profileImport" # Import Profile SEMA4AI_PROFILE_IMPORT_INTERNAL = "sema4ai.profileImport.internal" # Import Profile (internal) SEMA4AI_PROFILE_SWITCH = "sema4ai.profileSwitch" # Switch Profile diff --git a/sema4ai-code/vscode-client/src/conversion.ts b/sema4ai-code/vscode-client/src/conversion.ts deleted file mode 100644 index ab772c0b..00000000 --- a/sema4ai-code/vscode-client/src/conversion.ts +++ /dev/null @@ -1,575 +0,0 @@ -import * as AdmZip from "adm-zip"; -import * as rimraf from "rimraf"; - -import * as path from "path"; - -import { window, Progress, ProgressLocation, CancellationToken, Uri, workspace } from "vscode"; -import { - fileExists, - findNextBasenameIn, - getExtensionRelativeFile, - makeDirs, - readFromFile, - verifyFileExists, - writeToFile, -} from "./files"; -import { download, feedback, Metrics } from "./rcc"; -import { basename, join } from "path"; -import { logError, OUTPUT_CHANNEL } from "./channel"; -import { TextDecoder } from "util"; -import { - CommandType, - ConversionFailure, - ConversionResult, - ConversionSuccess, - Format, - isSuccessful, - RPAConversionCommand, -} from "./protocols"; -import { readdirSync, rmSync, statSync, existsSync } from "fs"; - -export const CONVERSION_STATUS = { - alreadyCheckedVersion: false, -}; - -export enum RPATypes { - uipath = "uipath", - blueprism = "blueprism", - a360 = "a360", - aav11 = "aav11", -} - -export enum TargetLanguages { - RF = "RF", - PYTHON = "PYTHON", - DOT = "DOT", -} - -export const DEFAULT_TARGET_LANGUAGE = TargetLanguages.RF; - -export const RPA_TYPE_TO_CAPTION = { - "uipath": "UiPath", - "blueprism": "Blue Prism", - "a360": "Automation Anywhere 360", - "aav11": "Automation Anywhere 11", -}; - -export async function conversionMain(converterBundle, command: RPAConversionCommand): Promise { - return await converterBundle.main(command); -} - -export const getConverterBundleVersion = async (): Promise<{ - currentVersion?: string; - newVersion?: string; - currentVersionLocation?: string; -}> => { - const versionURL = "https://downloads.robocorp.com/converter/latest/version-with-commons.txt"; - const currentVersionLocation = getExtensionRelativeFile("../../vscode-client/out/converterBundle.version", false); - const newVersionLocation = getExtensionRelativeFile("../../vscode-client/out/converterBundle.version.new", false); - - // downloading & reading the new version - const currentVersion = await readFromFile(currentVersionLocation); - let newVersion = undefined; - await window.withProgress( - { - location: ProgressLocation.Notification, - title: "Checking converter version", - cancellable: false, - }, - async ( - progress: Progress<{ message?: string; increment?: number }>, - token: CancellationToken - ): Promise => { - const result = await download( - versionURL, - progress, - token, - currentVersion ? newVersionLocation : currentVersionLocation - ); - newVersion = await readFromFile(currentVersion ? newVersionLocation : currentVersionLocation); - return result; - } - ); - return { currentVersion: currentVersion, newVersion: newVersion, currentVersionLocation: currentVersionLocation }; -}; - -export async function ensureConvertBundle(): Promise<{ - pathToExecutable: string; - pathToConvertYaml?: string; -}> { - const bundleURL = "https://downloads.robocorp.com/converter/latest/converter-with-commons.zip"; - const bundleRelativeLocation = "../../vscode-client/out/converter-with-commons.zip"; - const bundleLocation = getExtensionRelativeFile(bundleRelativeLocation, false); - const bundleFolderRelativeLocation = "../../vscode-client/out/converter-with-commons"; - const bundleFolderLocation = getExtensionRelativeFile(bundleFolderRelativeLocation, false); - - // downloading the bundle - const downloadBundle = async () => - await window.withProgress( - { - location: ProgressLocation.Notification, - title: "Downloading converter bundle", - cancellable: false, - }, - async ( - progress: Progress<{ message?: string; increment?: number }>, - token: CancellationToken - ): Promise => await download(bundleURL, progress, token, bundleLocation) - ); - - const unzipBundle = async () => { - // remove previous bundle if it exists - if (verifyFileExists(bundleFolderLocation, false)) { - rimraf.sync(bundleFolderLocation); - } - - const zip = new AdmZip(bundleLocation); - zip.extractAllTo(bundleFolderLocation); - }; - - // if the bundle file doesn't exit or isn't marked as being downloaded, force download - const warnUser: boolean = false; - if (!verifyFileExists(bundleLocation, warnUser)) { - await downloadBundle(); - await unzipBundle(); - } else if (!CONVERSION_STATUS.alreadyCheckedVersion) { - CONVERSION_STATUS.alreadyCheckedVersion = true; - const { currentVersion, newVersion, currentVersionLocation } = await getConverterBundleVersion(); - if (currentVersion && newVersion && currentVersion !== newVersion) { - // ask user if we should download the new version of the bundle or use old one - const items = ["Yes", "No"]; - const shouldUpgrade = await window.showQuickPick(items, { - "placeHolder": `Would you like to update the converter to version: ${newVersion}?`, - "canPickMany": false, - "ignoreFocusOut": true, - }); - if (shouldUpgrade && shouldUpgrade !== "No") { - await writeToFile(currentVersionLocation, newVersion); - await downloadBundle(); - await unzipBundle(); - } - } - } - - const executable = path.join(bundleFolderLocation, "bundle.js"); - const convertYaml = path.join(bundleFolderLocation, "robocorp-commons", "convert.yaml"); - - return { - pathToExecutable: executable, - pathToConvertYaml: verifyFileExists(convertYaml) ? convertYaml : undefined, - }; -} - -export async function convertAndSaveResults( - convertBundlePromise: Promise<{ - pathToExecutable: string; - pathToConvertYaml?: string; - }>, - opts: { - inputType: RPATypes; - input: string[]; - outputFolder: string; - targetLanguage: string; - adapterFolderPath: string; - } -): Promise<{ - success: boolean; - message: string; -}> { - const converterLocation = await convertBundlePromise; - if (!converterLocation) { - return { - "success": false, - "message": "There was an issue downloading the converter bundle. Please try again.", - }; - } - const converterBundle = require(converterLocation.pathToExecutable); - let rpaConversionCommands: RPAConversionCommand[] = []; - - if (!opts.input || opts.input.length === 0) { - return { - "success": false, - "message": "Unable to do conversion because input was not specified.", - }; - } - - // We want to create a structure such as: - // - // Just for conversions: - // /output_folder/converted-uipath/... - // /output_folder/converted-uipath-1/... - // ... - // - // For analysis + conversion: - // /output_folder/converted-uipath-1/analysis - // /output_folder/converted-uipath-1/generated - - const cleanups = []; - - feedback(Metrics.CONVERTER_USED, opts.inputType); - - try { - let nextBasename: string; - const targetLanguage = opts.targetLanguage; - switch (opts.inputType) { - case RPATypes.uipath: { - nextBasename = await findNextBasenameIn(opts.outputFolder, "converted-uipath"); - const projects: Array = opts.input; - const tempDir: string = join(opts.outputFolder, nextBasename, "temp"); - await makeDirs(tempDir); - - cleanups.push(() => { - try { - rmSync(tempDir, { recursive: true, force: true, maxRetries: 1 }); - } catch (err) { - OUTPUT_CHANNEL.appendLine("Error deleting: " + tempDir + ": " + err.message); - } - }); - - rpaConversionCommands.push({ - command: CommandType.Schema, - vendor: Format.UIPATH, - projects: projects, - onProgress: undefined, - outputRelativePath: join(nextBasename, "schema"), - }); - - rpaConversionCommands.push({ - command: CommandType.Analyse, - vendor: Format.UIPATH, - projects: projects, - onProgress: undefined, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "analysis"), - }); - for (const it of opts.input) { - rpaConversionCommands.push({ - vendor: Format.UIPATH, - command: CommandType.Convert, - projectFolderPath: it, - targetLanguage, - onProgress: undefined, - outputRelativePath: join(nextBasename, basename(it)), - }); - } - break; - } - case RPATypes.blueprism: { - nextBasename = await findNextBasenameIn(opts.outputFolder, "converted-blueprism"); - const projects: Array = opts.input; - const tempDir: string = join(opts.outputFolder, nextBasename, "temp"); - await makeDirs(tempDir); - - cleanups.push(() => { - try { - rmSync(tempDir, { recursive: true, force: true, maxRetries: 1 }); - } catch (err) { - OUTPUT_CHANNEL.appendLine("Error deleting: " + tempDir + ": " + err.message); - } - }); - rpaConversionCommands.push({ - command: CommandType.Analyse, - vendor: Format.BLUEPRISM, - projects: projects, - onProgress: undefined, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "analysis"), - }); - for (const it of opts.input) { - let contents = ""; - try { - if (!(await fileExists(it))) { - return { - "success": false, - "message": `${it} does not exist.`, - }; - } - const uri = Uri.file(it); - const bytes = await workspace.fs.readFile(uri); - contents = new TextDecoder("utf-8").decode(bytes); - } catch (err) { - const message = "Unable to read: " + it + "\n" + err.message; - logError(message, err, "ERROR_READ_BLUEPRISM_FILE"); - return { - "success": false, - "message": message, - }; - } - - rpaConversionCommands.push({ - vendor: Format.BLUEPRISM, - command: CommandType.Convert, - releaseFileContent: contents, - apiImplementationFolderPath: converterLocation.pathToConvertYaml, - targetLanguage, - onProgress: undefined, - outputRelativePath: join(nextBasename, basename(it)), - }); - } - break; - } - case RPATypes.a360: { - nextBasename = await findNextBasenameIn(opts.outputFolder, "converted-a360"); - const projects: Array = opts.input; - const tempDir: string = join(opts.outputFolder, nextBasename, "temp"); - await makeDirs(tempDir); - - cleanups.push(() => { - try { - rmSync(tempDir, { recursive: true, force: true, maxRetries: 1 }); - } catch (err) { - OUTPUT_CHANNEL.appendLine("Error deleting: " + tempDir + ": " + err.message); - } - }); - - rpaConversionCommands.push({ - command: CommandType.Schema, - vendor: Format.A360, - projects: projects, - onProgress: undefined, - outputRelativePath: join(nextBasename, "schema"), - }); - rpaConversionCommands.push({ - command: CommandType.Analyse, - vendor: Format.A360, - projects: projects, - onProgress: undefined, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "analysis"), - }); - - const adapterFilePaths = []; - if (existsSync(opts.adapterFolderPath)) { - const stat = statSync(opts.adapterFolderPath); - if (stat.isDirectory()) { - const files = readdirSync(opts.adapterFolderPath); - for (const file of files) { - const filepath = path.join(opts.adapterFolderPath, file); - const fileStat = statSync(filepath); - if (fileStat.isFile()) { - adapterFilePaths.push(filepath); - } - } - } - } - - for (const it of opts.input) { - rpaConversionCommands.push({ - vendor: Format.A360, - command: CommandType.Convert, - projectFolderPath: it, - adapterFilePaths, - targetLanguage, - onProgress: undefined, - outputRelativePath: join(nextBasename, basename(it)), - }); - } - break; - } - case RPATypes.aav11: - nextBasename = await findNextBasenameIn(opts.outputFolder, "converted-aav11"); - const projects: Array = opts.input; - const tempDir: string = join(opts.outputFolder, nextBasename, "temp"); - await makeDirs(tempDir); - - cleanups.push(() => { - try { - rmSync(tempDir, { recursive: true, force: true, maxRetries: 1 }); - } catch (err) { - OUTPUT_CHANNEL.appendLine("Error deleting: " + tempDir + ": " + err.message); - } - }); - - rpaConversionCommands.push({ - vendor: Format.AAV11, - command: CommandType.Analyse, - projects: projects, - onProgress: undefined, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "analysis"), - }); - - rpaConversionCommands.push({ - vendor: Format.AAV11, - command: CommandType.Generate, - projects: projects, - onProgress: undefined, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "api"), - }); - - rpaConversionCommands.push({ - command: CommandType.Schema, - vendor: Format.AAV11, - projects: projects, - onProgress: undefined, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "schema"), - }); - - for (const it of opts.input) { - rpaConversionCommands.push({ - vendor: Format.AAV11, - command: CommandType.Convert, - projects: [it], - onProgress: undefined, - targetLanguage, - tempFolder: tempDir, - outputRelativePath: join(nextBasename, "conversion", basename(it)), - }); - } - break; - } - - return await window.withProgress( - { - location: ProgressLocation.Notification, - title: `${RPA_TYPE_TO_CAPTION[opts.inputType]} conversion`, - cancellable: true, - }, - - async (progress: Progress<{ message?: string; increment?: number }>, token: CancellationToken) => { - const COMMAND_TO_LABEL = { - "Generate": "Generate API", - "Convert": "Convert", - "Analyse": "Analyse", - "Schema": "Generate Schema", - }; - // If we got here, things worked, let's write it to the filesystem. - const outputDirsWrittenTo = new Set(); - - const results: ConversionResult[] = []; - const steps: number = rpaConversionCommands.length; - const errors: Array<[RPAConversionCommand, string]> = []; - let incrementStep: number = 0; - let currStep: number = 0; - - // execute commands in sequence, but not fail all if one fails - for (const command of rpaConversionCommands) { - currStep += 1; - progress.report({ - message: `Step (${currStep}/${steps}): ${COMMAND_TO_LABEL[command.command]}`, - increment: incrementStep, - }); - incrementStep = 100 / steps; - // Give the UI a chance to show the progress. - await new Promise((r) => setTimeout(r, 5)); - - const conversionResult: ConversionResult = await conversionMain(converterBundle, command); - - if (!isSuccessful(conversionResult)) { - const message = (conversionResult).error; - logError( - `Error processing ${command.command} command`, - new Error(message), - "EXT_CONVERT_PROJECT" - ); - feedback(Metrics.CONVERTER_ERROR, command.vendor); - errors.push([command, message]); - - // skip and process next command - continue; - } - conversionResult.outputDir = join(opts.outputFolder, command.outputRelativePath); - results.push(conversionResult); - - if (token.isCancellationRequested) { - return { - "success": false, - "message": "Operation cancelled.", - }; - } - } - - const filesWritten: string[] = []; - - async function handleOutputFile( - file: string, - content: string, - encoding: BufferEncoding = "utf-8" - ): Promise { - filesWritten.push(file); - const { dir } = path.parse(file); - if (dir) { - await makeDirs(dir); - } - await writeToFile(file, content, { encoding }); - } - - const tasks: Promise[] = []; - for (const result of results) { - const okResult: ConversionSuccess = result; - const files = okResult?.files; - - await makeDirs(result.outputDir); - outputDirsWrittenTo.add(result.outputDir); - if (files && files.length > 0) { - for (const f of files) { - tasks.push( - handleOutputFile( - join(result.outputDir, f.filename), - f.content, - f.encoding as BufferEncoding - ) - ); - } - } - } - - await Promise.all(tasks); - - progress.report({ increment: incrementStep }); - - const outputDirsWrittenToStr: string[] = []; - for (const s of outputDirsWrittenTo) { - outputDirsWrittenToStr.push(s); - } - const d: Date = new Date(); - - const readmePath = join(opts.outputFolder, nextBasename, "README.md"); - await writeToFile( - readmePath, - `Generated: ${d.toISOString()} ----------------------------------- - -Sources ----------------------------------- -${opts.input.join("\n")} - -Created Directories ----------------------------------- -${outputDirsWrittenToStr.join("\n")} - -Created Files ----------------------------------- -${filesWritten.join("\n")} - -Errors ----------------------------------- -${ - errors.length > 0 - ? errors.map(([cmd, error]) => `Cannot process command ${cmd.command}, reason ${error}`).join("\n") - : "No errors" -} -` - ); - - while (cleanups.length > 0) { - const c = cleanups.pop(); - c.call(); - } - - return { - "success": false, - "message": - `Conversion succeeded.\n\nFinished: ${d.toISOString()}.\n\nWritten to directories:\n\n` + - outputDirsWrittenToStr.join("\n"), - }; - } - ); - } finally { - for (const c of cleanups) { - c.call(); - } - } -} diff --git a/sema4ai-code/vscode-client/src/conversionView.ts b/sema4ai-code/vscode-client/src/conversionView.ts deleted file mode 100644 index 83fdfb4d..00000000 --- a/sema4ai-code/vscode-client/src/conversionView.ts +++ /dev/null @@ -1,285 +0,0 @@ -/** - * Interesting docs related to webviews: - * https://code.visualstudio.com/api/extension-guides/webview - */ -import { readFileSync } from "fs"; -import { dirname, join } from "path"; -import * as vscode from "vscode"; -import { logError } from "./channel"; -import { - ensureConvertBundle, - convertAndSaveResults, - RPATypes, - RPA_TYPE_TO_CAPTION, - TargetLanguages, - DEFAULT_TARGET_LANGUAGE, -} from "./conversion"; -import { getExtensionRelativeFile } from "./files"; -import { getRobocorpHome } from "./rcc"; - -interface ConversionInfoLastOptions { - input: string[]; - generationResults: string; - outputFolder: string; - targetLanguage: TargetLanguages; -} - -interface ConversionInfo { - inputType: RPATypes; - input: string[]; - generationResults: string; - outputFolder: string; - typeToLastOptions: Map; - targetLanguage: TargetLanguages; -} - -let panel: vscode.WebviewPanel | undefined = undefined; -let globalState: vscode.Memento = undefined; - -export async function showConvertUI(context: vscode.ExtensionContext) { - const convertBundlePromise: Promise<{ - pathToExecutable: string; - pathToConvertYaml?: string; - }> = ensureConvertBundle(); - - globalState = context.globalState; - - if (!panel) { - panel = vscode.window.createWebviewPanel( - "robocorpCodeConvert", - "Conversion Accelerator", - vscode.ViewColumn.One, - { - enableScripts: true, - } - ); - panel.onDidDispose(() => { - panel = undefined; - }); - } else { - panel.reveal(); - return; - } - - const wsFolders: ReadonlyArray = vscode.workspace.workspaceFolders; - let ws: vscode.WorkspaceFolder; - let outputFolder = ""; - if (wsFolders !== undefined && wsFolders.length >= 1) { - ws = wsFolders[0]; - outputFolder = ws.uri.fsPath; - } else { - throw new Error("Conversion Accelerator can work only in a workspace"); - } - - const typeToLastOptions = new Map(); - - function generateDefaultOptions(): ConversionInfoLastOptions { - return { - "input": [], // files for BP, folders for others. - "generationResults": "", - "outputFolder": outputFolder, - "targetLanguage": DEFAULT_TARGET_LANGUAGE, - }; - } - - typeToLastOptions[RPATypes.uipath] = generateDefaultOptions(); - typeToLastOptions[RPATypes.blueprism] = generateDefaultOptions(); - typeToLastOptions[RPATypes.a360] = generateDefaultOptions(); - typeToLastOptions[RPATypes.aav11] = generateDefaultOptions(); - - let conversionInfo: ConversionInfo = { - "inputType": RPATypes.uipath, - "input": [], - "generationResults": "", - "outputFolder": outputFolder, - "typeToLastOptions": typeToLastOptions, - "targetLanguage": DEFAULT_TARGET_LANGUAGE, - }; - - const oldState = context.globalState.get("robocorpConversionViewState"); - if (oldState) { - conversionInfo = oldState; - - // Validate that what we had saved is valid for new versions. - // i.e.: Backward-compatibility. - - if (conversionInfo.typeToLastOptions[RPATypes.aav11] === undefined) { - conversionInfo.typeToLastOptions[RPATypes.aav11] = generateDefaultOptions(); - } - - // if previous old state, target language might not be defined - if (conversionInfo.typeToLastOptions[RPATypes.a360].targetLanguage === undefined) { - conversionInfo.typeToLastOptions[RPATypes.a360].targetLanguage = DEFAULT_TARGET_LANGUAGE; - } - if (conversionInfo.typeToLastOptions[RPATypes.blueprism].targetLanguage === undefined) { - conversionInfo.typeToLastOptions[RPATypes.blueprism].targetLanguage = DEFAULT_TARGET_LANGUAGE; - } - if (conversionInfo.typeToLastOptions[RPATypes.uipath].targetLanguage === undefined) { - conversionInfo.typeToLastOptions[RPATypes.uipath].targetLanguage = DEFAULT_TARGET_LANGUAGE; - } - if (conversionInfo.typeToLastOptions[RPATypes.aav11].targetLanguage === undefined) { - conversionInfo.typeToLastOptions[RPATypes.aav11].targetLanguage = DEFAULT_TARGET_LANGUAGE; - } - } - - panel.webview.html = getWebviewContent(conversionInfo); - panel.webview.onDidReceiveMessage( - async (message) => { - switch (message.command) { - case "persistState": - const stateToPersist = message.contents; - context.globalState.update("robocorpConversionViewState", stateToPersist); - return; - case "onClickOutputFolder": - let outputFolder: string = ""; - try { - const currentOutputFolder = message.currentOutputFolder; - outputFolder = await onClickOutputFolder(currentOutputFolder); - } finally { - panel.webview.postMessage({ command: "setOutputFolder", "outputFolder": outputFolder }); - } - return; - case "onClickAdd": - let input: string[] = []; - try { - input = await onClickAdd(message.contents); - } finally { - panel.webview.postMessage({ command: "addFileOrFolder", "input": input }); - } - return; - case "onClickConvert": - let result: { - success: boolean; - message: string; - } = { success: false, message: "Unexpected error doing conversion." }; - try { - const contents = message.contents; - const outputFolder = contents["outputFolder"]; - const targetLanguage = contents["targetLanguage"]; - const inputType = contents["inputType"]; - const input = contents["input"]; - // adapter files are at the machine level and location cannot be changed by converter webview - const home = await getRobocorpHome(); - const adapterFolderPath = join(home, "rca", inputType, "adapters"); - - result = await onClickConvert(convertBundlePromise, { - outputFolder, - targetLanguage, - inputType, - input, - adapterFolderPath, - }); - } finally { - panel.webview.postMessage({ command: "conversionFinished", result: result }); - } - return; - } - }, - undefined, - context.subscriptions - ); -} - -async function onClickOutputFolder(currentOutputFolder: any): Promise { - const defaultUri = vscode.Uri.file(currentOutputFolder); - let uris: vscode.Uri[] = await vscode.window.showOpenDialog({ - "canSelectFolders": true, - "canSelectFiles": false, - "canSelectMany": false, - "openLabel": `Select output folder`, - "defaultUri": defaultUri, - }); - if (uris && uris.length > 0) { - return uris[0].fsPath; - } - return ""; -} - -async function onClickAdd(contents: { type: RPATypes }): Promise { - const MEMENTO_KEY = `lastFolderFor${contents.type}`; - const stored: string | undefined = globalState.get(MEMENTO_KEY); - const lastFolder: vscode.Uri | undefined = stored ? vscode.Uri.file(stored) : undefined; - - let uris: vscode.Uri[]; - let input: string[] = []; - const type: RPATypes = contents["type"]; - const vendor = RPA_TYPE_TO_CAPTION[type]; - if (!vendor) { - vscode.window.showErrorMessage("Error: unable to handle type: " + type); - return input; - } - - if (type === RPATypes.blueprism || type === RPATypes.aav11) { - // select files - uris = await vscode.window.showOpenDialog({ - "canSelectFolders": false, - "canSelectFiles": true, - "canSelectMany": true, - "openLabel": `Select a ${vendor} file project to convert`, - "defaultUri": lastFolder, - }); - if (uris && uris.length > 0) { - globalState.update(MEMENTO_KEY, dirname(uris[0].fsPath)); - for (const uri of uris) { - input.push(uri.fsPath); - } - } - } else { - // select folders - uris = await vscode.window.showOpenDialog({ - "canSelectFolders": true, - "canSelectFiles": false, - "canSelectMany": true, - "openLabel": `Select a ${vendor} folder project to convert`, - "defaultUri": lastFolder, - }); - if (uris && uris.length > 0) { - globalState.update(MEMENTO_KEY, uris[0].fsPath); - for (const uri of uris) { - input.push(uri.fsPath); - } - } - } - return input; -} - -async function onClickConvert( - convertBundlePromise: Promise<{ - pathToExecutable: string; - pathToConvertYaml?: string; - }>, - opts: { - inputType: RPATypes; - input: string[]; - outputFolder: string; - targetLanguage: string; - adapterFolderPath: string; - } -): Promise<{ - success: boolean; - message: string; -}> { - try { - return await convertAndSaveResults(convertBundlePromise, opts); - } catch (error) { - logError("Error making conversion.", error, "ERROR_CONVERTING_INTERNAL"); - return { - "success": false, - "message": "Error making conversion: " + error.message, - }; - } -} - -function getWebviewContent(jsonData: ConversionInfo): string { - const jsonDataStr = JSON.stringify(jsonData, null, 4); - const templateFile = getExtensionRelativeFile("../../vscode-client/templates/converter.html", true); - const data = readFileSync(templateFile, "utf8"); - - const start = '"; - const endI = data.indexOf(end, startI); - - const ret: string = data.substring(0, startI) + jsonDataStr + data.substring(endI); - return ret; -} diff --git a/sema4ai-code/vscode-client/src/extension.ts b/sema4ai-code/vscode-client/src/extension.ts index 4fd5f9ee..039c4324 100644 --- a/sema4ai-code/vscode-client/src/extension.ts +++ b/sema4ai-code/vscode-client/src/extension.ts @@ -133,7 +133,6 @@ import { SEMA4AI_OPEN_FLOW_EXPLORER_TREE_SELECTION, SEMA4AI_OPEN_LOCATORS_JSON, SEMA4AI_OPEN_ROBOT_CONDA_TREE_SELECTION, - SEMA4AI_CONVERT_PROJECT, SEMA4AI_PROFILE_IMPORT, SEMA4AI_PROFILE_SWITCH, SEMA4AI_RUN_ROBOCORPS_PYTHON_TASK, @@ -165,7 +164,6 @@ import { Mutex } from "./mutex"; import { mergeEnviron } from "./subprocess"; import { feedback } from "./rcc"; import { showSubmitIssueUI } from "./submitIssue"; -import { showConvertUI } from "./conversionView"; import { profileImport, profileSwitch } from "./profiles"; import { registerLinkProviders } from "./robo/linkProvider"; import { runRobocorpTasks } from "./robo/runRobocorpTasks"; @@ -415,7 +413,6 @@ function registerRobocorpCodeCommands(C: CommandRegistry, context: ExtensionCont C.register(SEMA4AI_OPEN_FLOW_EXPLORER_TREE_SELECTION, (robot: RobotEntry) => commands.executeCommand("robot.openFlowExplorer", Uri.file(robot.robot.directory).toString()) ); - C.register(SEMA4AI_CONVERT_PROJECT, async () => await showConvertUI(context)); C.register(SEMA4AI_RCC_TERMINAL_CREATE_ROBOT_TREE_SELECTION, (robot: RobotEntry) => views.createRccTerminalTreeSelection(robot) ); diff --git a/sema4ai-code/vscode-client/src/protocols.ts b/sema4ai-code/vscode-client/src/protocols.ts index be95a189..bf6e2022 100644 --- a/sema4ai-code/vscode-client/src/protocols.ts +++ b/sema4ai-code/vscode-client/src/protocols.ts @@ -103,52 +103,12 @@ export interface LibraryVersionInfoDict { message?: string; } -// these declarations are a superficial variant of the implemented ones in the converter bundle -// they might need changes if the Converter API is changed -export enum ConversionResultType { - SUCCESS = "Success", - FAILURE = "Failure", -} - export interface File { content: string; filename: string; encoding?: string; } -export interface ConversionSuccess { - type: ConversionResultType.SUCCESS; - /** - * @deprecated use files - */ - robotFileContent: string; - files: Array; - report?: File; - images?: Array; - outputDir: string; // Used internally in Sema4.ai Code -} - -export interface ConversionFailure { - type: ConversionResultType.FAILURE; - error: string; - report?: File; - images?: Array; - outputDir: string; // Used internally in Sema4.ai Code -} - -export type ConversionResult = ConversionSuccess | ConversionFailure; - -export function isSuccessful(result: ConversionResult): result is ConversionSuccess { - return result.type === ConversionResultType.SUCCESS; -} - -export enum Format { - BLUEPRISM = "blueprism", - A360 = "a360", - UIPATH = "uipath", - AAV11 = "aav11", -} - export enum ValidationStatus { ValidationSuccess = "ValidationSuccess", ValidationError = "ValidationError", @@ -175,136 +135,3 @@ export interface Options { export interface Progress { (amount: number, message: string): void; } - -export enum CommandType { - Analyse = "Analyse", - Convert = "Convert", - Generate = "Generate", - Schema = "Schema", -} - -export interface A360ConvertCommand { - command: CommandType.Convert; - vendor: Format.A360; - projectFolderPath: string; - targetLanguage: string; - adapterFilePaths: Array; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface A360SchemaCommand { - command: CommandType.Schema; - vendor: Format.A360; - projects: Array; - /** properties that should be considered as ENUM */ - types?: Array; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface A360AnalyseCommand { - command: CommandType.Analyse; - vendor: Format.A360; - projects: Array; - tempFolder: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface UiPathConvertCommand { - command: CommandType.Convert; - vendor: Format.UIPATH; - projectFolderPath: string; - targetLanguage: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface UiPathSchemaCommand { - command: CommandType.Schema; - vendor: Format.UIPATH; - projects: Array; - /** properties that should be considered as ENUM */ - types?: Array; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface UiPathAnalyseCommand { - command: CommandType.Analyse; - vendor: Format.UIPATH; - projects: Array; - tempFolder: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface BlueprismConvertCommand { - command: CommandType.Convert; - vendor: Format.BLUEPRISM; - releaseFileContent: string; - targetLanguage: string; - apiImplementationFolderPath?: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface BlueprismAnalyseCommand { - command: CommandType.Analyse; - vendor: Format.BLUEPRISM; - projects: Array; - tempFolder: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface AAV11ConvertCommand { - command: CommandType.Convert; - vendor: Format.AAV11; - /* path to aapkg files */ - projects: Array; - tempFolder: string; - targetLanguage: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface AAV11GenerateCommand { - command: CommandType.Generate; - vendor: Format.AAV11; - /* path to aapkg files */ - projects: Array; - tempFolder: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface AAV11AnalyseCommand { - command: CommandType.Analyse; - vendor: Format.AAV11; - /* path to aapkg files */ - projects: Array; - tempFolder: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export interface AAV11SchemaCommand { - command: CommandType.Schema; - vendor: Format.AAV11; - /* path to aapkg files */ - projects: Array; - /** properties that should be considered as ENUM */ - types?: Array; - tempFolder: string; - onProgress: Progress; - outputRelativePath: string; // Used internally in Sema4.ai Code -} - -export type BlueprismCommand = BlueprismConvertCommand | BlueprismAnalyseCommand; -export type UiPathCommand = UiPathConvertCommand | UiPathSchemaCommand | UiPathAnalyseCommand; -export type A360Command = A360ConvertCommand | A360SchemaCommand | A360AnalyseCommand; -export type AAV11Command = AAV11ConvertCommand | AAV11GenerateCommand | AAV11AnalyseCommand | AAV11SchemaCommand; - -export type RPAConversionCommand = BlueprismCommand | UiPathCommand | A360Command | AAV11Command; diff --git a/sema4ai-code/vscode-client/src/robocorpCommands.ts b/sema4ai-code/vscode-client/src/robocorpCommands.ts index 4572802a..3c8916d3 100644 --- a/sema4ai-code/vscode-client/src/robocorpCommands.ts +++ b/sema4ai-code/vscode-client/src/robocorpCommands.ts @@ -94,7 +94,6 @@ export const SEMA4AI_CLEAR_ENV_AND_RESTART = "sema4ai.clearEnvAndRestart"; // C export const SEMA4AI_SHOW_OUTPUT = "sema4ai.showOutput"; // Show Sema4.ai Code > Output logs export const SEMA4AI_SHOW_INTERPRETER_ENV_ERROR = "sema4ai.showInterpreterEnvError"; // Show error related to interpreter env creation export const SEMA4AI_OPEN_FLOW_EXPLORER_TREE_SELECTION = "sema4ai.openFlowExplorerTreeSelection"; // Open Flow Explorer -export const SEMA4AI_CONVERT_PROJECT = "sema4ai.convertProject"; // Conversion Accelerator from third party RPA to Robocorp Task Package (Robot) export const SEMA4AI_PROFILE_IMPORT = "sema4ai.profileImport"; // Import Profile export const SEMA4AI_PROFILE_IMPORT_INTERNAL = "sema4ai.profileImport.internal"; // Import Profile (internal) export const SEMA4AI_PROFILE_SWITCH = "sema4ai.profileSwitch"; // Switch Profile