diff --git a/.vscode/settings.json b/.vscode/settings.json index 594df253f9..3c36cb580b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -119,6 +119,7 @@ "networkidle", "nickyt", "nodehost", + "nodir", "nomic", "nonemodel", "nothrow", diff --git a/docs/src/content/docs/reference/vscode/index.mdx b/docs/src/content/docs/reference/vscode/index.mdx index e65f27ef90..7b6d66f869 100644 --- a/docs/src/content/docs/reference/vscode/index.mdx +++ b/docs/src/content/docs/reference/vscode/index.mdx @@ -14,5 +14,6 @@ contains the latest stable release of the [extension](https://marketplace.visual - [Download](https://marketplace.visualstudio.com/items?itemName=genaiscript.genaiscript-vscode) - [Installation instructions](/genaiscript/getting-started/installation/#visual-studio-code-extension) +- [Running Scripts](/genaiscript/reference/vscode/running-scripts/) - [Copilot Chat Integration](/genaiscript/reference/vscode/github-copilot-chat/) - [Settings](/genaiscript/reference/vscode/settings/) diff --git a/docs/src/content/docs/reference/vscode/running-scripts.mdx b/docs/src/content/docs/reference/vscode/running-scripts.mdx new file mode 100644 index 0000000000..17765c5ffb --- /dev/null +++ b/docs/src/content/docs/reference/vscode/running-scripts.mdx @@ -0,0 +1,45 @@ +--- +title: Running Scripts +sidebar: + order: 3 +description: Learn how to run GenAIScripts in Visual Studio Code using the GenAIScript extension. +keywords: GenAIScript, Visual Studio Code, run scripts, command palette, context menu +--- + +The GenAIScript extension for Visual Studio Code provides a convenient way to run scripts directly from the editor. + +There are mostly two ways of running scripts: + +- running a script "directly". This scenario is useful when debugging a script + or for a script that does not require any input files. +- running a script from input files or folders. This scenario is useful when you want to run a script on multiple files or folders. + +## Running Scripts directly + +- open a GenAIScript file in the editor +- right-click in the editor and select **Run GenAIScript\*** form the content menu +- or click on on the **Run GenAIScript** icon in the top right corner of the editor + +This will start the script execution and use the default input files specify in the `script` `files` field. + +```js 'files' +script({ + files: "...", +}) +``` + +This mode is useful when developing script or for scripts that do not require any input files. + +## Running Scripts from input files or folders + +This mode allows to run scripts on any combination of files and folders, which will populate `env.files`. + +### From the explorer window: + +- select any files or folders in the explorer. You can use the `Ctrl` or `Shift` key to select multiple files or folders. +- right-click and select **Run GenAIScript** from the context menu + +### From an editor + +- open an file in the editor (not a GenAIScript file) +- right-click and select **Run GenAIScript** from the context menu diff --git a/docs/src/content/docs/samples/awesome.mdx b/docs/src/content/docs/samples/awesome.mdx index 52ba6ea3e4..5934340d0f 100644 --- a/docs/src/content/docs/samples/awesome.mdx +++ b/docs/src/content/docs/samples/awesome.mdx @@ -22,3 +22,5 @@ These are a few scripts written by the community that are useful for various tas description="Let the grumpy senior dev review your code with this MCP server" href="https://github.com/sinedied/grumpydev-mcp/blob/main/genaisrc/review-code.genai.js" /> + +- [Submit your script](https://github.com/microsoft/genaiscript/edit/dev/docs/src/content/docs/samples/awesome.mdx). \ No newline at end of file diff --git a/packages/cli/src/nodehost.ts b/packages/cli/src/nodehost.ts index ec9b3f2e40..2f4101fd53 100644 --- a/packages/cli/src/nodehost.ts +++ b/packages/cli/src/nodehost.ts @@ -478,7 +478,8 @@ export class NodeHost extends EventTarget implements RuntimeHost { } ): Promise { const { ignore, applyGitIgnore } = options || {} - const paths = arrayify(path) + const paths = arrayify(path).filter((p) => !!p) + dbg(`finding files: ${paths}`) const negatives = paths .filter((p) => NEGATIVE_GLOB_REGEX.test(p)) .map((p) => p.replace(NEGATIVE_GLOB_REGEX, "")) diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index d4229dc2b3..e6ef0ac317 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -474,6 +474,8 @@ export async function startServer( // Cancel any active scripts const { script, files = [], options = {}, runId } = data if (!script) throw new Error("missing script") + if (files.some((f) => !f)) + throw new Error("invalid file") cancelAll() const canceller = new AbortSignalCancellationController() diff --git a/packages/core/src/systems.ts b/packages/core/src/systems.ts index 365d03426a..f897a54258 100644 --- a/packages/core/src/systems.ts +++ b/packages/core/src/systems.ts @@ -1,7 +1,3 @@ -import debug from "debug" -const dbg = debug("genaiscript:systems") -const dbgr = debug("genaiscript:systems:resolve") - // cspell: disable // This module resolves and returns a list of applicable systems based on the provided script and project. // It analyzes script options and the JavaScript source code to determine which systems to include or exclude. @@ -12,6 +8,10 @@ import type { GenerationOptions } from "./generation" import { isToolsSupported } from "./tools" import type { Project } from "./server/messages" import { deleteUndefinedValues } from "./cleaners" +import { genaiscriptDebug } from "./debug" +const dbg = genaiscriptDebug("systems") +const dbgr = dbg.extend("resolve") +dbgr.enabled = false /** * Resolves and returns a list of unique systems based on the provided script and project. diff --git a/packages/sample/genaisrc/emojify-files.genai.mts b/packages/sample/genaisrc/emojify-files.genai.mts new file mode 100644 index 0000000000..9b58859d47 --- /dev/null +++ b/packages/sample/genaisrc/emojify-files.genai.mts @@ -0,0 +1,10 @@ +script({ + title: "Converts each file to an emoji", + files: ["src/*.txt", "src/*.cpp"], +}) + +def("FILE", env.files) + +$`Your task is to summarize each file as an emoji. + +Return a list of filename: emoji using INI format.` diff --git a/packages/vscode/src/fragmentcommands.ts b/packages/vscode/src/fragmentcommands.ts index 34a5642e5f..dcc5c6456e 100644 --- a/packages/vscode/src/fragmentcommands.ts +++ b/packages/vscode/src/fragmentcommands.ts @@ -53,20 +53,14 @@ export function activateFragmentCommands(state: ExtensionState) { } else return (picked as TemplateQuickPickItem)?.template } - const resolveSpec = async (fileOrFolder: vscode.Uri) => { - if (await checkFileExists(fileOrFolder)) { - return [fileOrFolder.fsPath] - } else if (await checkDirectoryExists(fileOrFolder)) { - return [state.host.path.join(fileOrFolder.fsPath, "**")] - } else return undefined - } - - const scriptRun = async (fileOrFolder: vscode.Uri) => { + const scriptRun = async ( + fileOrFolder: vscode.Uri, + fileOrFolders: vscode.Uri[] + ) => { // editor context menu // explorer context menu (file or folder) - uri to file or folder // edit file run button: uri to genai file in editor - logVerbose(`run ${fileOrFolder}`) - + logVerbose(`run ${fileOrFolder}, ${fileOrFolders?.length || 0} files`) await state.cancelAiRequest() await state.parseWorkspace() @@ -74,7 +68,10 @@ export function activateFragmentCommands(state: ExtensionState) { let files: string[] let parameters: PromptParameters - if (GENAI_ANY_REGEX.test(fileOrFolder.path)) { + if ( + fileOrFolders?.length === 1 && + GENAI_ANY_REGEX.test(fileOrFolder.path) + ) { const script = findScript(fileOrFolder) parameters = await showPromptParametersQuickPicks(script) if (parameters === undefined) return @@ -86,7 +83,7 @@ export function activateFragmentCommands(state: ExtensionState) { parameters = await showPromptParametersQuickPicks(script) if (parameters === undefined) return scriptId = script.id - files = await resolveSpec(fileOrFolder) + files = fileOrFolders.map((f) => f.fsPath) } await state.requestAI({ fragment: { files },