From b1a22b98bfb7c3f11c50923a095ff0d90472ce55 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Tue, 14 Jan 2025 23:59:50 +0000 Subject: [PATCH] add option to open view in vscode --- packages/cli/src/server.ts | 43 +++++++++++++------ packages/sample/genaiscript.config.yml | 4 +- packages/vscode/package.json | 5 +++ packages/vscode/src/extension.ts | 2 + packages/vscode/src/fragmentcommands.ts | 2 + .../vscode/src/markdowndocumentprovider.ts | 2 - packages/vscode/src/promptcommands.ts | 6 +++ packages/vscode/src/webview.ts | 16 +++++-- packages/web/src/App.tsx | 6 ++- 9 files changed, 65 insertions(+), 21 deletions(-) diff --git a/packages/cli/src/server.ts b/packages/cli/src/server.ts index 2d30ed2506..bd341c9f61 100644 --- a/packages/cli/src/server.ts +++ b/packages/cli/src/server.ts @@ -94,6 +94,9 @@ export async function startServer(options: { const wss = new WebSocketServer({ noServer: true }) // Stores active script runs with their cancellation controllers and traces. + let lastRunResult: PromptScriptEndResponseEvent & { + trace: string + } = undefined const runs: Record< string, { @@ -284,25 +287,38 @@ export async function startServer(options: { } // send traces of in-flight runs - for (const [runId, run] of Object.entries(runs)) { - chunkString(run.outputTrace.content).forEach((c) => + const activeRuns = Object.entries(runs) + if (activeRuns.length) { + for (const [runId, run] of activeRuns) { ws.send( JSON.stringify({ type: "script.progress", runId, - trace: c, + output: run.outputTrace.content, } satisfies PromptScriptProgressResponseEvent) ) - ) - chunkString(run.trace.content).forEach((c) => + chunkString(run.trace.content).forEach((c) => + ws.send( + JSON.stringify({ + type: "script.progress", + runId, + trace: c, + } satisfies PromptScriptProgressResponseEvent) + ) + ) + } + } else if (lastRunResult) { + const { trace, ...restResult } = lastRunResult + chunkString(trace).forEach((c) => ws.send( JSON.stringify({ type: "script.progress", - runId, + runId: lastRunResult.runId, trace: c, } satisfies PromptScriptProgressResponseEvent) ) ) + ws.send(JSON.stringify(restResult)) } // Handle incoming messages based on their type. @@ -420,12 +436,15 @@ export async function startServer(options: { logVerbose( `\nrun ${runId}: completed with ${exitCode}` ) - send({ - type: "script.end", - runId, - exitCode, - result, - } satisfies PromptScriptEndResponseEvent) + send( + (lastRunResult = { + type: "script.end", + runId, + exitCode, + result, + trace: trace.content, + }) + ) }) .catch((e) => { if (canceller.controller.signal.aborted) return diff --git a/packages/sample/genaiscript.config.yml b/packages/sample/genaiscript.config.yml index c8c950cf6e..62ea9d874d 100644 --- a/packages/sample/genaiscript.config.yml +++ b/packages/sample/genaiscript.config.yml @@ -1,3 +1,3 @@ modelAliases: - large: google:gemini-exp-1206 - vision: google:gemini-exp-1206 + gemini: google:gemini-exp-1206 + video: google:gemini-exp-1206 diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 2286442f53..3d6de75131 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -379,6 +379,11 @@ "title": "Open request or response", "category": "GenAIScript" }, + { + "command": "genaiscript.request.open.view", + "title": "View request", + "category": "GenAIScript" + }, { "command": "genaiscript.request.open.trace", "title": "Open Trace", diff --git a/packages/vscode/src/extension.ts b/packages/vscode/src/extension.ts index ef6021c60c..986e7c9a42 100644 --- a/packages/vscode/src/extension.ts +++ b/packages/vscode/src/extension.ts @@ -23,6 +23,7 @@ import { activateConnectionInfoTree } from "./connectioninfotree" import { activeTaskProvider } from "./taskprovider" import { activateSamplesCommands } from "./samplescommands" import { activateChatParticipant } from "./chatparticipant" +import { activeWebview } from "./webview" export async function activate(context: ExtensionContext) { const state = new ExtensionState(context) @@ -39,6 +40,7 @@ export async function activate(context: ExtensionContext) { activateDocsNotebook(state) activeTaskProvider(state) activateChatParticipant(state) + activeWebview(state) context.subscriptions.push( registerCommand("genaiscript.request.abort", async () => { diff --git a/packages/vscode/src/fragmentcommands.ts b/packages/vscode/src/fragmentcommands.ts index f4684098a0..4a73661018 100644 --- a/packages/vscode/src/fragmentcommands.ts +++ b/packages/vscode/src/fragmentcommands.ts @@ -260,6 +260,8 @@ export function activateFragmentCommands(state: ExtensionState) { ) } + + subscriptions.push( registerCommand("genaiscript.fragment.prompt", fragmentPrompt), registerCommand("genaiscript.fragment.debug", fragmentDebug) diff --git a/packages/vscode/src/markdowndocumentprovider.ts b/packages/vscode/src/markdowndocumentprovider.ts index 4af40cc75e..e2ff152ddd 100644 --- a/packages/vscode/src/markdowndocumentprovider.ts +++ b/packages/vscode/src/markdowndocumentprovider.ts @@ -26,7 +26,6 @@ import { topLogprobsToMarkdown, } from "../../core/src/logprob" import { fenceMD } from "../../core/src/mkmd" -import { createWebview } from "./webview" const SCHEME = "genaiscript" @@ -233,7 +232,6 @@ export function activateMarkdownTextDocumentContentProvider( ) ), registerCommand("genaiscript.request.open.output", async () => { - //await createWebview(state) return vscode.commands.executeCommand( "genaiscript.request.open", REQUEST_OUTPUT_FILENAME diff --git a/packages/vscode/src/promptcommands.ts b/packages/vscode/src/promptcommands.ts index ffc6e9416b..dec8b80c8f 100644 --- a/packages/vscode/src/promptcommands.ts +++ b/packages/vscode/src/promptcommands.ts @@ -80,11 +80,17 @@ export function commandButtons(state: ExtensionState) { const request = state.aiRequest const { computing } = request || {} const abort = "Abort" + const view = "View" const output = "Output" const trace = "Trace" const cmds: { label: string; description?: string; cmd: string }[] = [] if (computing) cmds.push({ label: abort, cmd: "genaiscript.request.abort" }) if (request) { + cmds.push({ + label: view, + description: "View GenAIScript request.", + cmd: "genaiscript.request.open.view", + }) cmds.push({ label: output, description: "Preview AI response.", diff --git a/packages/vscode/src/webview.ts b/packages/vscode/src/webview.ts index 84f8c4d57c..2fb2eb9633 100644 --- a/packages/vscode/src/webview.ts +++ b/packages/vscode/src/webview.ts @@ -1,10 +1,9 @@ import * as vscode from "vscode" import { TOOL_ID, TOOL_NAME } from "../../core/src/constants" import { ExtensionState } from "./state" +import { registerCommand } from "./commands" -export async function createWebview( - state: ExtensionState -): Promise { +async function createWebview(state: ExtensionState): Promise { const { host, sessionApiKey, context } = state await host.server.client() @@ -16,6 +15,7 @@ export async function createWebview( { localResourceRoots: [vscode.Uri.parse(authority)], enableScripts: true, + retainContextWhenHidden: true, } ) context.subscriptions.push(webview) @@ -39,3 +39,13 @@ export async function createWebview( ` return webview.webview } + +export function activeWebview(state: ExtensionState) { + const { context } = state + const { subscriptions } = context + subscriptions.push( + registerCommand("genaiscript.request.open.view", async () => { + await createWebview(state) + }) + ) +} diff --git a/packages/web/src/App.tsx b/packages/web/src/App.tsx index 2090cd4f3b..24d003c95e 100644 --- a/packages/web/src/App.tsx +++ b/packages/web/src/App.tsx @@ -134,12 +134,14 @@ class RunClient extends WebSocketClient { console.log(`script: end`, data.result) this.updateRunId(data) this.result = cleanedClone(data.result) + this.output = data.result.text this.dispatchEvent( new CustomEvent(RunClient.SCRIPT_END_EVENT, { detail: this.result, }) ) this.dispatchEvent(new Event(RunClient.RESULT_EVENT)) + this.dispatchEvent(new Event(RunClient.PROGRESS_EVENT)) break } case "script.start": @@ -1281,8 +1283,8 @@ function ResultsTabs() { onVscTabsSelect={(e) => setSelected(e.detail.selectedIndex)} panel > - - + +