From 64890a0527fe30beb9f0c9e1546142215abe47f2 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 16:30:56 +0000 Subject: [PATCH 1/8] Add GenAIScript task provider and CLI configuration in VSCode extension --- packages/vscode/package.json | 22 ++++++++++++++ packages/vscode/src/config.ts | 22 ++++++++++++++ packages/vscode/src/extension.ts | 2 ++ packages/vscode/src/taskprovider.ts | 47 +++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 packages/vscode/src/config.ts create mode 100644 packages/vscode/src/taskprovider.ts diff --git a/packages/vscode/package.json b/packages/vscode/package.json index ff52f0bc63..afc2e00a11 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -53,6 +53,28 @@ }, "contributes": { "markdown.markdownItPlugins": true, + "taskDefinitions": [ + { + "type": "genaiscript", + "required": [ + "script" + ], + "properties": { + "script": { + "type": "string", + "description": "GenAIScript script to run" + }, + "files": { + "type": "array", + "description": "Files to include in the script", + "items": { + "type": "string", + "description": "File or glob to include in the script" + } + } + } + } + ], "walkthroughs": [ { "id": "genaiscript.tutorial", diff --git a/packages/vscode/src/config.ts b/packages/vscode/src/config.ts new file mode 100644 index 0000000000..a0bfe1696a --- /dev/null +++ b/packages/vscode/src/config.ts @@ -0,0 +1,22 @@ +import * as vscode from "vscode" +import { + TOOL_ID, + VSCODE_CONFIG_CLI_PATH, + VSCODE_CONFIG_CLI_VERSION, +} from "../../core/src/constants" +import { CORE_VERSION } from "../../core/src/version" +import { semverParse, semverSatisfies } from "../../core/src/semver" + +export async function resolveCli() { + const config = vscode.workspace.getConfiguration(TOOL_ID) + const cliPath = config.get(VSCODE_CONFIG_CLI_PATH) as string + const cliVersion = + (config.get(VSCODE_CONFIG_CLI_VERSION) as string) || CORE_VERSION + const gv = semverParse(CORE_VERSION) + if (!semverSatisfies(cliVersion, ">=" + gv.major + "." + gv.minor)) + vscode.window.showWarningMessage( + TOOL_ID + + ` - genaiscript cli version (${cliVersion}) outdated, please update to ${CORE_VERSION}` + ) + return { cliPath, cliVersion } +} diff --git a/packages/vscode/src/extension.ts b/packages/vscode/src/extension.ts index d6714a6533..85ba94cc02 100644 --- a/packages/vscode/src/extension.ts +++ b/packages/vscode/src/extension.ts @@ -23,6 +23,7 @@ import { activateConnectionInfoTree } from "./connectioninfotree" import { updateConnectionConfiguration } from "../../core/src/connection" import { APIType } from "../../core/src/host" import { openUrlInTab } from "./browser" +import { activeTaskProvider } from "./taskprovider" export async function activate(context: ExtensionContext) { const state = new ExtensionState(context) @@ -36,6 +37,7 @@ export async function activate(context: ExtensionContext) { activateTraceTreeDataProvider(state) activateStatusBar(state) activateDocsNotebook(state) + activeTaskProvider(state) context.subscriptions.push( registerCommand( diff --git a/packages/vscode/src/taskprovider.ts b/packages/vscode/src/taskprovider.ts new file mode 100644 index 0000000000..1997cb84b3 --- /dev/null +++ b/packages/vscode/src/taskprovider.ts @@ -0,0 +1,47 @@ +import * as vscode from "vscode" +import { ExtensionState } from "./state" +import { resolveCli } from "./config" +import { TOOL_ID } from "../../core/src/constants" + +export async function activeTaskProvider(state: ExtensionState) { + const { context, host } = state + const { subscriptions } = context + + const taskProvider: vscode.TaskProvider = { + provideTasks: async () => { + const { cliPath, cliVersion } = await resolveCli() + const exec = cliPath + ? cliPath + : `npx --yes genaiscript@${cliVersion}` + const scripts = state.project.templates.filter((t) => !t.isSystem) + const tasks = scripts.map((script) => { + const scriptp = host.path.relative( + host.projectFolder(), + script.filename + ) + const task = new vscode.Task( + { type: TOOL_ID, script: script.id }, + vscode.TaskScope.Workspace, + script.id, + TOOL_ID, + new vscode.ShellExecution(`${exec} run "${scriptp}"`) + ) + task.detail = `${script.title ?? script.description} - ${scriptp}` + task.problemMatchers = ["$tsc"] + task.presentationOptions = { + echo: true, + focus: true, + showReuseMessage: false, + clear: true, + } + return task + }) + return tasks + }, + async resolveTask(task): Promise { + return task + }, + } + + subscriptions.push(vscode.tasks.registerTaskProvider(TOOL_ID, taskProvider)) +} From cf74d4dca11da19ee2ab670bd95f6f93c3973cac Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 16:47:12 +0000 Subject: [PATCH 2/8] Add relative file path to shell execution in task provider --- packages/vscode/src/taskprovider.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/vscode/src/taskprovider.ts b/packages/vscode/src/taskprovider.ts index 1997cb84b3..001254794a 100644 --- a/packages/vscode/src/taskprovider.ts +++ b/packages/vscode/src/taskprovider.ts @@ -24,7 +24,9 @@ export async function activeTaskProvider(state: ExtensionState) { vscode.TaskScope.Workspace, script.id, TOOL_ID, - new vscode.ShellExecution(`${exec} run "${scriptp}"`) + new vscode.ShellExecution( + `${exec} run "${scriptp}" $\{relativeFile\}` + ) ) task.detail = `${script.title ?? script.description} - ${scriptp}` task.problemMatchers = ["$tsc"] From d4d80670177483374d4fd085d7bf75aa1bf3a659 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 16:48:14 +0000 Subject: [PATCH 3/8] Add quoteify utility function and refactor task provider and nodehost code --- .vscode/settings.json | 1 + packages/cli/src/nodehost.ts | 3 +-- packages/core/src/util.ts | 4 ++++ packages/vscode/package.json | 8 -------- packages/vscode/src/taskprovider.ts | 13 ++++++++----- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 2b2612b92e..476405440e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -38,6 +38,7 @@ "promptdom", "promptfoo", "prompty", + "quoteify", "stringifying", "sysr", "tabletojson", diff --git a/packages/cli/src/nodehost.ts b/packages/cli/src/nodehost.ts index ff9acb3f22..5be9105d90 100644 --- a/packages/cli/src/nodehost.ts +++ b/packages/cli/src/nodehost.ts @@ -39,7 +39,7 @@ import { ResponseStatus, } from "../../core/src/host" import { AbortSignalOptions, TraceOptions } from "../../core/src/trace" -import { logVerbose, unique } from "../../core/src/util" +import { logVerbose, quoteify, unique } from "../../core/src/util" import { parseModelIdentifier } from "../../core/src/models" import { AuthenticationToken, @@ -300,7 +300,6 @@ export class NodeHost implements RuntimeHost { if (command === "python" && process.platform !== "win32") command = "python3" - const quoteify = (a: string) => (/\s/.test(a) ? `"${a}"` : a) logVerbose( `${cwd ? `${cwd}> ` : ""}${quoteify(command)} ${args.map(quoteify).join(" ")}` ) diff --git a/packages/core/src/util.ts b/packages/core/src/util.ts index 791a016ab4..c076dddaa3 100644 --- a/packages/core/src/util.ts +++ b/packages/core/src/util.ts @@ -196,6 +196,10 @@ export function logError(msg: string | Error | SerializedError) { if (!/^\s*\{\s*\}\s*$/.test(se)) host.log(LogLevel.Verbose, se) } } +export function quoteify(a: string) { + return /\s/.test(a) ? `"${a}"` : a +} + export function concatArrays(...arrays: T[][]): T[] { if (arrays.length == 0) return [] return arrays[0].concat(...arrays.slice(1)) diff --git a/packages/vscode/package.json b/packages/vscode/package.json index afc2e00a11..68b0c25112 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -63,14 +63,6 @@ "script": { "type": "string", "description": "GenAIScript script to run" - }, - "files": { - "type": "array", - "description": "Files to include in the script", - "items": { - "type": "string", - "description": "File or glob to include in the script" - } } } } diff --git a/packages/vscode/src/taskprovider.ts b/packages/vscode/src/taskprovider.ts index 001254794a..5d268208c3 100644 --- a/packages/vscode/src/taskprovider.ts +++ b/packages/vscode/src/taskprovider.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode" import { ExtensionState } from "./state" import { resolveCli } from "./config" import { TOOL_ID } from "../../core/src/constants" +import { quoteify } from "../../core/src/util" export async function activeTaskProvider(state: ExtensionState) { const { context, host } = state @@ -11,7 +12,7 @@ export async function activeTaskProvider(state: ExtensionState) { provideTasks: async () => { const { cliPath, cliVersion } = await resolveCli() const exec = cliPath - ? cliPath + ? quoteify(cliPath) : `npx --yes genaiscript@${cliVersion}` const scripts = state.project.templates.filter((t) => !t.isSystem) const tasks = scripts.map((script) => { @@ -20,13 +21,15 @@ export async function activeTaskProvider(state: ExtensionState) { script.filename ) const task = new vscode.Task( - { type: TOOL_ID, script: script.id }, + { type: TOOL_ID, script: script.filename }, vscode.TaskScope.Workspace, script.id, TOOL_ID, - new vscode.ShellExecution( - `${exec} run "${scriptp}" $\{relativeFile\}` - ) + new vscode.ShellExecution(exec, [ + "run", + scriptp, + "${relativeFile}", + ]) ) task.detail = `${script.title ?? script.description} - ${scriptp}` task.problemMatchers = ["$tsc"] From f6c424070ed972f5569f702f00ae988fe3bcc608 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 17:06:01 +0000 Subject: [PATCH 4/8] Refactor CLI configuration handling by integrating resolveCli function --- packages/vscode/src/fragmentcommands.ts | 27 +++++-------------------- packages/vscode/src/servermanager.ts | 14 +++---------- 2 files changed, 8 insertions(+), 33 deletions(-) diff --git a/packages/vscode/src/fragmentcommands.ts b/packages/vscode/src/fragmentcommands.ts index fb000ea1c0..3147614274 100644 --- a/packages/vscode/src/fragmentcommands.ts +++ b/packages/vscode/src/fragmentcommands.ts @@ -3,19 +3,12 @@ import { ExtensionState } from "./state" import { checkDirectoryExists, checkFileExists } from "./fs" import { registerCommand } from "./commands" import { templateGroup } from "../../core/src/ast" -import { - GENAI_ANY_REGEX, - TOOL_ID, - TOOL_NAME, - VSCODE_CONFIG_CLI_PATH, - VSCODE_CONFIG_CLI_VERSION, -} from "../../core/src/constants" +import { GENAI_ANY_REGEX, TOOL_ID, TOOL_NAME } from "../../core/src/constants" import { NotSupportedError } from "../../core/src/error" import { promptParameterTypeToJSONSchema } from "../../core/src/parameters" import { Fragment } from "../../core/src/generation" import { assert, dotGenaiscriptPath, groupBy } from "../../core/src/util" -import { CORE_VERSION } from "../../core/src/version" -import { semverParse, semverSatisfies } from "../../core/src/semver" +import { resolveCli } from "./config" type TemplateQuickPickItem = { template?: PromptScript @@ -188,8 +181,7 @@ export function activateFragmentCommands(state: ExtensionState) { files = [file] } - const config = vscode.workspace.getConfiguration(TOOL_ID) - const program = config.get(VSCODE_CONFIG_CLI_PATH) as string + const { cliPath, cliVersion } = await resolveCli() const args = [ "run", vscode.workspace.asRelativePath(template.filename), @@ -197,19 +189,10 @@ export function activateFragmentCommands(state: ExtensionState) { vscode.workspace.asRelativePath(file.fsPath) ), ] - const cliVersion = - (config.get(VSCODE_CONFIG_CLI_VERSION) as string) || CORE_VERSION - const gv = semverParse(CORE_VERSION) - if (!semverSatisfies(cliVersion, ">=" + gv.major + "." + gv.minor)) - vscode.window.showWarningMessage( - TOOL_ID + - ` - genaiscript cli version (${cliVersion}) outdated, please update to ${CORE_VERSION}` - ) - - const configuration = program + const configuration = cliPath ? { name: TOOL_NAME, - program, + cliPath, request: "launch", skipFiles: ["/**", dotGenaiscriptPath("**")], type: "node", diff --git a/packages/vscode/src/servermanager.ts b/packages/vscode/src/servermanager.ts index ee5a27898b..356fd9c1a8 100644 --- a/packages/vscode/src/servermanager.ts +++ b/packages/vscode/src/servermanager.ts @@ -6,10 +6,7 @@ import { OPEN, TOOL_NAME, ICON_LOGO_NAME, - CLIENT_RECONNECT_MAX_ATTEMPTS, TOOL_ID, - VSCODE_CONFIG_CLI_VERSION, - VSCODE_CONFIG_CLI_PATH, } from "../../core/src/constants" import { ServerManager, host } from "../../core/src/host" import { logError, logVerbose } from "../../core/src/util" @@ -17,6 +14,7 @@ import { WebSocketClient } from "../../core/src/server/client" import { CORE_VERSION } from "../../core/src/version" import { createChatModelRunner } from "./lmaccess" import { semverParse, semverSatisfies } from "../../core/src/semver" +import { resolveCli } from "./config" export class TerminalServerManager implements ServerManager { private _terminal: vscode.Terminal @@ -86,15 +84,9 @@ export class TerminalServerManager implements ServerManager { isTransient: true, iconPath: new vscode.ThemeIcon(ICON_LOGO_NAME), }) - const config = vscode.workspace.getConfiguration(TOOL_ID) - const cliPath = config.get(VSCODE_CONFIG_CLI_PATH) as string + const { cliPath, cliVersion } = await resolveCli() if (cliPath) this._terminal.sendText(`node "${cliPath}" serve`) - else { - const cliVersion = - (config.get(VSCODE_CONFIG_CLI_VERSION) as string) || - CORE_VERSION - this._terminal.sendText(`npx --yes ${TOOL_ID}@${cliVersion} serve`) - } + else this._terminal.sendText(`npx --yes ${TOOL_ID}@${cliVersion} serve`) this._terminal.show() } From b936768799bf4ea63a537fb815664c6011ea59de Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 17:51:38 +0000 Subject: [PATCH 5/8] Add TypeScript annotation parsing and improve annotation handling in tests --- packages/core/src/annotations.test.ts | 19 ++++++++++++++- packages/core/src/annotations.ts | 35 +++++++++++++++++++++------ 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/packages/core/src/annotations.test.ts b/packages/core/src/annotations.test.ts index b034af8f12..e1c6a1759e 100644 --- a/packages/core/src/annotations.test.ts +++ b/packages/core/src/annotations.test.ts @@ -3,7 +3,7 @@ import { parseAnnotations } from "./annotations" import assert from "assert/strict" describe("annotations", () => { - test("error", () => { + test("github", () => { const output = ` ::error file=packages/core/src/github.ts,line=71,endLine=71,code=concatenation_override::The change on line 71 may lead to the original \`text\` content being overridden instead of appending the footer. Consider using \`text = appendGeneratedComment(script, info, text)\` to ensure the original text is preserved and the footer is appended. 😇 @@ -25,4 +25,21 @@ describe("annotations", () => { "The change on line 71 may lead to the original `text` content being overridden instead of appending the footer. Consider using `text = appendGeneratedComment(script, info, text)` to ensure the original text is preserved and the footer is appended. 😇" ) }) + + test("tsc", () => { + const output = ` + +src/annotations.ts:11:28 - error TS1005: ',' expected. + ` + + const diags = parseAnnotations(output) + // console.log(diags) + assert.strictEqual(diags.length, 1) + assert.strictEqual(diags[0].severity, "error") + assert.strictEqual(diags[0].filename, "src/annotations.ts") + assert.strictEqual(diags[0].range[0][0], 10) + assert.strictEqual(diags[0].range[1][0], 27) + assert.strictEqual(diags[0].code, "TS1005") + assert.strictEqual(diags[0].message, "',' expected.") + }) }) diff --git a/packages/core/src/annotations.ts b/packages/core/src/annotations.ts index 1ac67d1171..38b2b39226 100644 --- a/packages/core/src/annotations.ts +++ b/packages/core/src/annotations.ts @@ -1,3 +1,4 @@ +// https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-error-message const GITHUB_ANNOTATIONS_RX = /^\s*::(?notice|warning|error)\s*file=(?[^,]+),\s*line=(?\d+),\s*endLine=(?\d+)\s*(,\s*code=(?[^,:]+)?\s*)?::(?.*)$/gim // ##vso[task.logissue type=warning;sourcepath=consoleap @@ -6,18 +7,38 @@ const GITHUB_ANNOTATIONS_RX = const AZURE_DEVOPS_ANNOTATIONS_RX = /^\s*##vso\[task.logissue\s+type=(?error|warning);sourcepath=(?);linenumber=(?\d+)(;code=(?\d+);)?[^\]]*\](?.*)$/gim +// https://code.visualstudio.com/docs/editor/tasks#_background-watching-tasks +const TYPESCRIPT_ANNOTATIONS_RX = + /^(?[^:\s].*?):(?\d+)(?::(?\d+))?(?::\d+)?\s+-\s+(?error|warning)\s+(?[^:]+)\s*:\s*(?.*)$/gim + /** - * Matches ::(notice|warning|error) file=,line=:: + * Matches TypeScript, GitHub Actions and Azure DevOps annotations * @param line + * @link https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-error-message */ export function parseAnnotations(text: string): Diagnostic[] { if (!text) return [] const sevMap: Record = { + ["info"]: "info", ["notice"]: "info", ["warning"]: "warning", ["error"]: "error", } - const annotations: Record = {} + const annotations = new Set() + for (const m of text.matchAll(TYPESCRIPT_ANNOTATIONS_RX)) { + const { file, line, endLine, severity, code, message } = m.groups + const annotation: Diagnostic = { + severity: sevMap[severity], + filename: file, + range: [ + [parseInt(line) - 1, 0], + [parseInt(endLine) - 1, Number.MAX_VALUE], + ], + message, + code, + } + annotations.add(annotation) + } text.replace( GITHUB_ANNOTATIONS_RX, (_, severity, file, line, endLine, __, code, message) => { @@ -31,12 +52,11 @@ export function parseAnnotations(text: string): Diagnostic[] { message, code, } - const key = JSON.stringify(annotation) - annotations[key] = annotation + annotations.add(annotation) return "" } ) - text?.replace( + text.replace( AZURE_DEVOPS_ANNOTATIONS_RX, (_, severity, file, line, __, code, message) => { const annotation: Diagnostic = { @@ -49,12 +69,11 @@ export function parseAnnotations(text: string): Diagnostic[] { message, code, } - const key = JSON.stringify(annotation) - annotations[key] = annotation + annotations.add(annotation) return "" } ) - return Object.values(annotations) + return Array.from(annotations.values()) } export function convertDiagnosticToGitHubActionCommand(d: Diagnostic) { From d27926c8ca3d0686ec61826b8cd5ce00d7a47a66 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 17:53:28 +0000 Subject: [PATCH 6/8] Refactor annotation parsing by consolidating logic into a single function --- packages/core/src/annotations.ts | 42 +++++--------------------------- 1 file changed, 6 insertions(+), 36 deletions(-) diff --git a/packages/core/src/annotations.ts b/packages/core/src/annotations.ts index 38b2b39226..edb18d5ce2 100644 --- a/packages/core/src/annotations.ts +++ b/packages/core/src/annotations.ts @@ -24,8 +24,7 @@ export function parseAnnotations(text: string): Diagnostic[] { ["warning"]: "warning", ["error"]: "error", } - const annotations = new Set() - for (const m of text.matchAll(TYPESCRIPT_ANNOTATIONS_RX)) { + const addAnnotation = (m: RegExpMatchArray) => { const { file, line, endLine, severity, code, message } = m.groups const annotation: Diagnostic = { severity: sevMap[severity], @@ -39,40 +38,11 @@ export function parseAnnotations(text: string): Diagnostic[] { } annotations.add(annotation) } - text.replace( - GITHUB_ANNOTATIONS_RX, - (_, severity, file, line, endLine, __, code, message) => { - const annotation: Diagnostic = { - severity: sevMap[severity] || severity, - filename: file, - range: [ - [parseInt(line) - 1, 0], - [parseInt(endLine) - 1, Number.MAX_VALUE], - ], - message, - code, - } - annotations.add(annotation) - return "" - } - ) - text.replace( - AZURE_DEVOPS_ANNOTATIONS_RX, - (_, severity, file, line, __, code, message) => { - const annotation: Diagnostic = { - severity: sevMap[severity] || severity, - filename: file, - range: [ - [parseInt(line) - 1, 0], - [parseInt(line) - 1, Number.MAX_VALUE], - ], - message, - code, - } - annotations.add(annotation) - return "" - } - ) + + const annotations = new Set() + for (const m of text.matchAll(TYPESCRIPT_ANNOTATIONS_RX)) addAnnotation(m) + for (const m of text.matchAll(GITHUB_ANNOTATIONS_RX)) addAnnotation(m) + for (const m of text.matchAll(AZURE_DEVOPS_ANNOTATIONS_RX)) addAnnotation(m) return Array.from(annotations.values()) } From 821808d33fda5dbb7c060907910bab54f95c5554 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 17:53:52 +0000 Subject: [PATCH 7/8] Set default severity to "info" in parseAnnotations function --- packages/core/src/annotations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/annotations.ts b/packages/core/src/annotations.ts index edb18d5ce2..adc97c7ead 100644 --- a/packages/core/src/annotations.ts +++ b/packages/core/src/annotations.ts @@ -27,7 +27,7 @@ export function parseAnnotations(text: string): Diagnostic[] { const addAnnotation = (m: RegExpMatchArray) => { const { file, line, endLine, severity, code, message } = m.groups const annotation: Diagnostic = { - severity: sevMap[severity], + severity: sevMap[severity] ?? "info", filename: file, range: [ [parseInt(line) - 1, 0], From 3548b28bcaf7ad54bef5540d8e4a0230cdfdf589 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Fri, 13 Sep 2024 18:03:26 +0000 Subject: [PATCH 8/8] Add documentation for running scripts as tasks in VS Code --- .../docs/getting-started/running-scripts.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/src/content/docs/getting-started/running-scripts.md b/docs/src/content/docs/getting-started/running-scripts.md index 579eb7f72e..c5733048f3 100644 --- a/docs/src/content/docs/getting-started/running-scripts.md +++ b/docs/src/content/docs/getting-started/running-scripts.md @@ -63,10 +63,28 @@ Use the [run](/genaiscript/reference/cli/run) command to execute a script from t npx genaiscript run proofreader path/to/files*.md ``` +## Tasks + +The GenAIScript extension exposes each script as a [Task](https://code.visualstudio.com/docs/editor/tasks) automatically. + +The task launches the [cli](/genaiscript/reference/cli) and runs the selected script and pass the path to the current opened editor. + +- Open the command palette `Ctrl+Shift+P` and search "Tasks: Run Task" +- Select the `genaiscript` task provider +- Select the script you want to run + +:::note + +When running a script as a task, the result will not be visible in the GenAIScript. + +::: + ## Analyze results By default, GenAIScript opens the output preview which shows a rendered view of the LLM output (assuming the LLM produces markdown). +The GenAIScript view provides an overview of the trace of the latest run. + You can also use the **Trace** to review the each transformation step of the script execution. - Click on the GenAIScript status bar icon and select **Trace**