From 16b9a21a34f4f91b2758458e16d35252eafeb1f0 Mon Sep 17 00:00:00 2001 From: Fred Bricon Date: Wed, 15 Jan 2025 19:07:24 +0100 Subject: [PATCH] Intercept Ollama errors before Webview, to display Download/Start options Signed-off-by: Fred Bricon --- core/util/ollamaHelper.ts | 8 +++--- .../src/autocomplete/completionProvider.ts | 6 ++--- extensions/vscode/src/commands.ts | 4 +++ extensions/vscode/src/webviewProtocol.ts | 25 ++++++++++++++++++- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/core/util/ollamaHelper.ts b/core/util/ollamaHelper.ts index 1e9c524908..a00e869dd0 100644 --- a/core/util/ollamaHelper.ts +++ b/core/util/ollamaHelper.ts @@ -11,7 +11,7 @@ export async function isOllamaInstalled(): Promise { }); } -export async function startLocalOllama(ide: IDE): Promise { +export async function startLocalOllama(ide: IDE): Promise { let startCommand: string | undefined; switch (process.platform) { @@ -20,16 +20,16 @@ export async function startLocalOllama(ide: IDE): Promise { break; case "win32"://Windows - startCommand = `& "ollama app.exe"\n`; + startCommand = "& \"ollama app.exe\"\n"; break; default: //Linux... - const start_script_path = path.resolve(__dirname, './start_ollama.sh'); + const start_script_path = path.resolve(__dirname, "./start_ollama.sh"); if (await ide.fileExists(`file:/${start_script_path}`)) { startCommand = `set -e && chmod +x ${start_script_path} && ${start_script_path}\n`; console.log(`Ollama Linux startup script at : ${start_script_path}`); } else { - ide.showToast("error", `Cannot start Ollama: could not find ${start_script_path}!`) + return ide.showToast("error", `Cannot start Ollama: could not find ${start_script_path}!`) } } if (startCommand) { diff --git a/extensions/vscode/src/autocomplete/completionProvider.ts b/extensions/vscode/src/autocomplete/completionProvider.ts index c10d4d5f18..b7680b6868 100644 --- a/extensions/vscode/src/autocomplete/completionProvider.ts +++ b/extensions/vscode/src/autocomplete/completionProvider.ts @@ -44,11 +44,11 @@ export class ContinueCompletionProvider implements vscode.InlineCompletionItemProvider { private onError(e: any) { - const options = ["Documentation"]; + let options = ["Documentation"]; if (e.message.includes("Ollama may not be installed")) { options.push("Download Ollama"); } else if (e.message.includes("Ollama may not be running")) { - options.unshift("Start Ollama"); // We want "Start" to be the default choice + options = ["Start Ollama"]; // We want "Start" to be the only choice } if (e.message.includes("Please sign in with GitHub")) { @@ -70,7 +70,7 @@ export class ContinueCompletionProvider ); } else if (val === "Download Ollama") { vscode.env.openExternal(vscode.Uri.parse("https://ollama.ai/download")); - } else if (val == "Start Ollama") { + } else if (val === "Start Ollama") { startLocalOllama(this.ide); } }); diff --git a/extensions/vscode/src/commands.ts b/extensions/vscode/src/commands.ts index d8019cfe17..bbf1cfd749 100644 --- a/extensions/vscode/src/commands.ts +++ b/extensions/vscode/src/commands.ts @@ -33,6 +33,7 @@ import { Battery } from "./util/battery"; import { VsCodeIde } from "./VsCodeIde"; import type { VsCodeWebviewProtocol } from "./webviewProtocol"; +import { startLocalOllama } from "core/util/ollamaHelper"; let fullScreenPanel: vscode.WebviewPanel | undefined; @@ -1000,6 +1001,9 @@ const getCommandsMap: ( "continue.openAccountDialog": () => { sidebar.webviewProtocol?.request("openDialogMessage", "account"); }, + "continue.startLocalOllama": () => { + startLocalOllama(ide); + }, }; }; diff --git a/extensions/vscode/src/webviewProtocol.ts b/extensions/vscode/src/webviewProtocol.ts index bfbb37ce60..c5853d12ad 100644 --- a/extensions/vscode/src/webviewProtocol.ts +++ b/extensions/vscode/src/webviewProtocol.ts @@ -81,6 +81,30 @@ export class VsCodeWebviewProtocol respond({ done: true, content: response ?? {}, status: "success" }); } } catch (e: any) { + let message = e.message; + //Intercept Ollama errors for special handling + if (message.includes("Ollama may not")) { + const options = []; + if (message.includes("be installed")) { + options.push("Download Ollama"); + } else if (message.includes("be running")) { + options.push("Start Ollama"); + } + if (options.length > 0) { + // Respond without an error, so the UI doesn't show the error component + respond({ done: true, status: "error" }); + // Show native vscode error message instead, with options to download/start Ollama + vscode.window.showErrorMessage(e.message, ...options).then(async (val) => { + if (val === "Download Ollama") { + vscode.env.openExternal(vscode.Uri.parse("https://ollama.ai/download")); + } else if (val === "Start Ollama") { + vscode.commands.executeCommand("continue.startLocalOllama"); + } + }); + return; + } + } + respond({ done: true, error: e.message, status: "error" }); const stringified = JSON.stringify({ msg }, null, 2); @@ -96,7 +120,6 @@ export class VsCodeWebviewProtocol return; } - let message = e.message; if (e.cause) { if (e.cause.name === "ConnectTimeoutError") { message = `Connection timed out. If you expect it to take a long time to connect, you can increase the timeout in config.json by setting "requestOptions": { "timeout": 10000 }. You can find the full config reference here: https://docs.continue.dev/reference/config`;