From de91bd0406caf25f2e8b4f13fd1b6e7994fc79a7 Mon Sep 17 00:00:00 2001 From: "Rossdan Craig rossdan@lastmileai.dev" <> Date: Wed, 21 Feb 2024 17:42:17 -0500 Subject: [PATCH 1/2] [vscode][2/n] Setup Env Variables: Define env path Opening a window for user to enter in an `.env` path. Using the home dir for now, but can change to workspace if you want, not a big deal. Next diffs will implement a static file template and use that when env path doesn't exist. Diff after that I'll deal with existing env path situation ## Test Plan https://github.com/lastmile-ai/aiconfig/assets/151060367/cceadc3a-cd20-4164-b8b2-c8d11b36b5bb --- vscode-extension/src/extension.ts | 91 ++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/vscode-extension/src/extension.ts b/vscode-extension/src/extension.ts index 507da634f..a2bddca6b 100644 --- a/vscode-extension/src/extension.ts +++ b/vscode-extension/src/extension.ts @@ -59,7 +59,7 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand( COMMANDS.SETUP_ENVIRONMENT_VARIABLES, () => { - vscode.window.showInformationMessage("Will implement next PR"); + setupEnvironmentVariables(); } ) ); @@ -716,6 +716,95 @@ async function checkPip() { }); } +/** + * Creates an .env file (or opens it if it already exists) to define environment variables + * 1) If .env file exists: + * a) Add helper lines on how to add common API keys (if not currently present) + * 2) If .env file doesn't exist + * b) Add template file containing helper lines from 1a above + */ +async function setupEnvironmentVariables() { + // Use home dir because env variables should be global. I get the argument + // for having in the workspace dir. I personally feel this is more + // annoying to setup every time you create a new project when using the + // same API keys, but I can do whatever option you want, not hard to + // implement + const homedir = require("os").homedir(); // This is cross-platform: https://stackoverflow.com/a/9081436 + const defaultEnvPath = path.join(homedir, ".env"); + + const envPath = await vscode.window.showInputBox({ + prompt: "Enter the path of your .env file", + value: defaultEnvPath, + validateInput: (text) => { + if (!text) { + return "File path is required"; + } else if (!text.endsWith(".env")) { + return "File path must end in .env file"; + } + // TODO: Check that env path is contained within workspace hierarchy + // (Ex: can't have .env file in a sibling dir otherwise AIConfig + // loadenv can't read it) + return null; + }, + }); + + if (!envPath) { + vscode.window.showInformationMessage( + "Environment variable setup cancelled" + ); + return; + } + + if (fs.existsSync(envPath)) { + // Append some lines in code to help guide users + // https://ai.google.dev/tutorials/setup + // https://platform.openai.com/api-keys + // Also add HF one + vscode.window.showInformationMessage( + "Env file already exists, will implement next PR" + ); + } else { + // File doesn't exist in path + vscode.window.showInformationMessage( + "Env file does not already, will implement next PR" + ); + } + + // // Create the model registry file from the sample + // const sampleModelRegistryPath = vscode.Uri.joinPath( + // context.extensionUri, + // "static", + // "example_aiconfig_model_registry.py" + // ); + + // try { + // await vscode.workspace.fs.copy( + // sampleModelRegistryPath, + // vscode.Uri.file(modelRegistryPath), + // { overwrite: false } + // ); + // } catch (err) { + // vscode.window.showErrorMessage( + // `Error creating new file ${modelRegistryPath}. Error is ${err}` + // ); + // } + + // const doc = await vscode.workspace.openTextDocument(modelRegistryPath); + // if (doc) { + // vscode.window.showTextDocument(doc); + // vscode.window.showInformationMessage( + // "Please customize your new model registry." + // ); + // } + + // let config = vscode.workspace.getConfiguration(EXTENSION_NAME); + // await handleCustomModelRegistryUpdate( + // config, + // aiconfigEditorManager, + // modelRegistryPath + // ); +} + async function shareAIConfig( context: vscode.ExtensionContext, aiconfigEditorManager: AIConfigEditorManager From 70a73b0bc63f7b1638b946fd0c810f4409aedead Mon Sep 17 00:00:00 2001 From: "Rossdan Craig rossdan@lastmileai.dev" <> Date: Wed, 21 Feb 2024 19:02:11 -0500 Subject: [PATCH 2/2] [vscode][3/n] Setup Env Variables: Use env template file for new files If the file does not exist, created a template file with some helper text to help guide people on how to set their environment variables. Next PR I will handle the use case for when the env file already exists ## Test Plan https://github.com/lastmile-ai/aiconfig/assets/151060367/4608833c-d64f-4906-a7ed-94af12174c6d --- vscode-extension/src/extension.ts | 75 +++++++++++------------- vscode-extension/static/env_template.env | 15 +++++ 2 files changed, 48 insertions(+), 42 deletions(-) create mode 100644 vscode-extension/static/env_template.env diff --git a/vscode-extension/src/extension.ts b/vscode-extension/src/extension.ts index a2bddca6b..5eececff7 100644 --- a/vscode-extension/src/extension.ts +++ b/vscode-extension/src/extension.ts @@ -59,7 +59,7 @@ export function activate(context: vscode.ExtensionContext) { vscode.commands.registerCommand( COMMANDS.SETUP_ENVIRONMENT_VARIABLES, () => { - setupEnvironmentVariables(); + setupEnvironmentVariables(context); } ) ); @@ -723,7 +723,7 @@ async function checkPip() { * 2) If .env file doesn't exist * b) Add template file containing helper lines from 1a above */ -async function setupEnvironmentVariables() { +async function setupEnvironmentVariables(context: vscode.ExtensionContext) { // Use home dir because env variables should be global. I get the argument // for having in the workspace dir. I personally feel this is more // annoying to setup every time you create a new project when using the @@ -741,6 +741,8 @@ async function setupEnvironmentVariables() { } else if (!text.endsWith(".env")) { return "File path must end in .env file"; } + // TODO: Check that file path is a "/.env" file (linux) or "\.env" (Windows) + // TODO: Check that env path is contained within workspace hierarchy // (Ex: can't have .env file in a sibling dir otherwise AIConfig // loadenv can't read it) @@ -756,53 +758,42 @@ async function setupEnvironmentVariables() { } if (fs.existsSync(envPath)) { - // Append some lines in code to help guide users - // https://ai.google.dev/tutorials/setup - // https://platform.openai.com/api-keys - // Also add HF one vscode.window.showInformationMessage( "Env file already exists, will implement next PR" ); } else { - // File doesn't exist in path - vscode.window.showInformationMessage( - "Env file does not already, will implement next PR" + // Create the .env file from the sample + const envTemplatePath = vscode.Uri.joinPath( + context.extensionUri, + "static", + "env_template.env" ); - } - // // Create the model registry file from the sample - // const sampleModelRegistryPath = vscode.Uri.joinPath( - // context.extensionUri, - // "static", - // "example_aiconfig_model_registry.py" - // ); + try { + await vscode.workspace.fs.copy( + envTemplatePath, + vscode.Uri.file(envPath), + { overwrite: false } + ); + } catch (err) { + vscode.window.showErrorMessage( + `Error creating new file ${envTemplatePath}: ${err}` + ); + } - // try { - // await vscode.workspace.fs.copy( - // sampleModelRegistryPath, - // vscode.Uri.file(modelRegistryPath), - // { overwrite: false } - // ); - // } catch (err) { - // vscode.window.showErrorMessage( - // `Error creating new file ${modelRegistryPath}. Error is ${err}` - // ); - // } - - // const doc = await vscode.workspace.openTextDocument(modelRegistryPath); - // if (doc) { - // vscode.window.showTextDocument(doc); - // vscode.window.showInformationMessage( - // "Please customize your new model registry." - // ); - // } - - // let config = vscode.workspace.getConfiguration(EXTENSION_NAME); - // await handleCustomModelRegistryUpdate( - // config, - // aiconfigEditorManager, - // modelRegistryPath - // ); + const doc = await vscode.workspace.openTextDocument(envPath); + if (doc) { + vscode.window.showTextDocument(doc, { + preview: false, + // Tried using vscode.ViewColumn.Active but that overrides existing + // walkthrough window + viewColumn: vscode.ViewColumn.Beside, + }); + vscode.window.showInformationMessage( + "Please define your environment variables." + ); + } + } } async function shareAIConfig( diff --git a/vscode-extension/static/env_template.env b/vscode-extension/static/env_template.env new file mode 100644 index 000000000..d75aee355 --- /dev/null +++ b/vscode-extension/static/env_template.env @@ -0,0 +1,15 @@ +# Uncomment the following lines to set these common env variables for +# accessing generative AI models. If your model requires other env variables +# you can also set those in this file + +## Used for models from OpenAI such as Chat GPT and Dall-E +## You can get your api key from https://platform.openai.com/api-keys +# OPENAI_API_KEY= + +## Used for models from Google such as Gemini and Gemma +## You can get your api key from https://ai.google.dev/tutorials/setup +# GOOGLE_API_KEY= + +## Used for models hosted on Hugging Face: https://huggingface.co/models +## You can get your token from https://huggingface.co/settings/tokens +# HUGGING_FACE_API_TOKEN=