From ceb6647ac111cbda382ae570dc39274c5c3ef9b5 Mon Sep 17 00:00:00 2001 From: JackyFTW Date: Fri, 21 Feb 2025 09:52:32 -0500 Subject: [PATCH 1/4] Figured out how to read terminal output --- src/extension.ts | 7 +++++++ src/test/workspace/test.js | 8 +++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index 97e71a4..503bf0e 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -19,6 +19,13 @@ export function activate(context: vscode.ExtensionContext) { inline.show(); }); + vscode.window.onDidStartTerminalShellExecution(async (e) => { + const stream = e.execution.read(); + for await (const data of stream) { + console.log(data); + } + }); + context.subscriptions.push(callAI); context.subscriptions.push(sendError); } diff --git a/src/test/workspace/test.js b/src/test/workspace/test.js index 30e1e73..58fabe5 100644 --- a/src/test/workspace/test.js +++ b/src/test/workspace/test.js @@ -1,5 +1,11 @@ function init() { - + let i = 0; + setInterval(() => { + console.log("Test: " + (i++)); + if(i > 10) { + throw new Error("Crashed"); + } + }, 1000); } init(); \ No newline at end of file From e920c990d299ca384d6e861af0f50fd187607af7 Mon Sep 17 00:00:00 2001 From: JackyFTW Date: Mon, 24 Feb 2025 09:52:12 -0500 Subject: [PATCH 2/4] Work on terminal output --- package-lock.json | 7 +++++++ package.json | 5 +---- src/ai/FakeCaller.ts | 4 ++-- src/ai/OpenAICaller.ts | 26 +++++++++++++++++++++++--- src/extension.ts | 18 ++---------------- src/terminal.ts | 20 ++++++++++++++++++++ src/test/workspace/test.js | 2 +- src/types/AIFeedback.d.ts | 4 ++-- src/types/AIRequest.d.ts | 5 ++--- src/types/Terminal.d.ts | 5 +++++ 10 files changed, 65 insertions(+), 31 deletions(-) create mode 100644 src/terminal.ts create mode 100644 src/types/Terminal.d.ts diff --git a/package-lock.json b/package-lock.json index e687fad..42cdffc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "dependencies": { "debugging-ai-assistant": "file:", + "linked-list-typescript": "^1.0.15", "openai": "^4.83.0" }, "devDependencies": { @@ -2203,6 +2204,12 @@ "immediate": "~3.0.5" } }, + "node_modules/linked-list-typescript": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/linked-list-typescript/-/linked-list-typescript-1.0.15.tgz", + "integrity": "sha512-RIyUu9lnJIyIaMe63O7/aFv/T2v3KsMFuXMBbUQCHX+cgtGro86ETDj5ed0a8gQL2+DFjzYYsgVG4I36/cUwgw==", + "license": "MIT" + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", diff --git a/package.json b/package.json index d298f1e..f5bde06 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,6 @@ "main": "./out/extension.js", "contributes": { "commands": [ - { - "command": "debuggingAiAssistant.callAI", - "title": "Call AI" - }, { "command": "debuggingAiAssistant.sendError", "title": "Send Error" @@ -76,6 +72,7 @@ }, "dependencies": { "debugging-ai-assistant": "file:", + "linked-list-typescript": "^1.0.15", "openai": "^4.83.0" } } diff --git a/src/ai/FakeCaller.ts b/src/ai/FakeCaller.ts index 9916898..3cb4a46 100644 --- a/src/ai/FakeCaller.ts +++ b/src/ai/FakeCaller.ts @@ -21,8 +21,8 @@ export class FakeCaller implements APICaller { } followUp(response: AIFeedback): Promise { - let newRequest: AIRequest = { prompt: "Test" }; - let finalResponse: AIFeedback = {request: newRequest, filename: response.filename, line: response.line, text: ""}; + let newRequest: AIRequest = {}; + let finalResponse: AIFeedback = {request: newRequest, fileName: response.fileName, line: response.line, text: ""}; // TODO: implement this diff --git a/src/ai/OpenAICaller.ts b/src/ai/OpenAICaller.ts index e04b818..0384f6b 100644 --- a/src/ai/OpenAICaller.ts +++ b/src/ai/OpenAICaller.ts @@ -19,6 +19,26 @@ export class OpenAICaller implements APICaller { return Promise.reject(); } + // TODO: send request to see if theres an error + settings.openai.chat.completions.create({ + model: "gpt-4o-mini", + messages: [ + { + role: "system", + content: + ` + You are a helpful code debugging assistant that is knowledgable on runtime and compile-time errors. + + The user will ask for assistance by supplying a JSON object with contextual information. The format of this request is: + { + prompt: string; // This is the message of assistance sent by the user. + terminalOutput: string // This is the latest terminal output before a possible error + } + ` + } + ] + }); + // TODO: implement this return settings.openai.chat.completions.create({ model: "gpt-4o-mini", @@ -47,7 +67,7 @@ export class OpenAICaller implements APICaller { content: ` { - "prompt": "${request.prompt}" + "prompt": "" } ` } @@ -68,8 +88,8 @@ export class OpenAICaller implements APICaller { } followUp(response: AIFeedback): Promise { - let newRequest: AIRequest = { prompt: "Test" }; - let finalResponse: AIFeedback = {request: newRequest, filename: response.filename, line: response.line, text: ""}; + let newRequest: AIRequest = {}; + let finalResponse: AIFeedback = {request: newRequest, fileName: response.fileName, line: response.line, text: ""}; // TODO: implement this diff --git a/src/extension.ts b/src/extension.ts index 503bf0e..330f1a2 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,17 +1,11 @@ import * as vscode from "vscode"; -import { OpenAICaller } from "./ai/OpenAICaller"; import { initSettings } from "./settings"; import { InlineDiagnostic } from "./extension/InlineDiagnostic"; +import { initTerminal } from "./terminal"; export function activate(context: vscode.ExtensionContext) { initSettings(); - - const callAI = vscode.commands.registerCommand("debuggingAiAssistant.callAI", () => { - let caller: OpenAICaller = new OpenAICaller(); - caller.sendRequest({ prompt: "Why is print(123) not working in my file, test.js?" }).then(response => { - vscode.window.showInformationMessage(`Response: ${response.text}`); - }); - }); + initTerminal(); const sendError = vscode.commands.registerCommand("debuggingAiAssistant.sendError", () => { const file: vscode.Uri = vscode.Uri.joinPath(vscode.workspace.workspaceFolders![0].uri, "test.js"); @@ -19,14 +13,6 @@ export function activate(context: vscode.ExtensionContext) { inline.show(); }); - vscode.window.onDidStartTerminalShellExecution(async (e) => { - const stream = e.execution.read(); - for await (const data of stream) { - console.log(data); - } - }); - - context.subscriptions.push(callAI); context.subscriptions.push(sendError); } diff --git a/src/terminal.ts b/src/terminal.ts new file mode 100644 index 0000000..081d655 --- /dev/null +++ b/src/terminal.ts @@ -0,0 +1,20 @@ +import vscode from "vscode" +import { Terminal } from "./types/Terminal"; +import { LinkedList } from "linked-list-typescript"; + +const MAX_NUMBER_LINES = 10; +let terminal: Terminal; + +export function initTerminal() { + terminal = { lines: new LinkedList() }; + + vscode.window.onDidStartTerminalShellExecution(async (e) => { + const stream = e.execution.read(); + for await (const data of stream) { + terminal.lines.append(data); + if(terminal.lines.length > MAX_NUMBER_LINES) { + terminal.lines.removeHead(); + } + } + }); +} \ No newline at end of file diff --git a/src/test/workspace/test.js b/src/test/workspace/test.js index 58fabe5..2dfc465 100644 --- a/src/test/workspace/test.js +++ b/src/test/workspace/test.js @@ -2,7 +2,7 @@ function init() { let i = 0; setInterval(() => { console.log("Test: " + (i++)); - if(i > 10) { + if(i > 100) { throw new Error("Crashed"); } }, 1000); diff --git a/src/types/AIFeedback.d.ts b/src/types/AIFeedback.d.ts index 958b8e8..6c5f832 100644 --- a/src/types/AIFeedback.d.ts +++ b/src/types/AIFeedback.d.ts @@ -2,7 +2,7 @@ import { AIRequest } from "./AIRequest"; export interface AIFeedback { request: AIRequest; - filename?: String; - line?: number; text: string; + fileName?: string; + line?: number; } \ No newline at end of file diff --git a/src/types/AIRequest.d.ts b/src/types/AIRequest.d.ts index db7b8e6..15288fc 100644 --- a/src/types/AIRequest.d.ts +++ b/src/types/AIRequest.d.ts @@ -1,6 +1,5 @@ export interface AIRequest { - prompt: string; - errorMessage?: string; // no clue how this would actually be send format wise. change later. - fileStructure?: string[]; // maybe stored like this, but doesn't give file contents so who knows :D terminalOutput?: string; + fileName?: string; + fileContent?: string; } \ No newline at end of file diff --git a/src/types/Terminal.d.ts b/src/types/Terminal.d.ts new file mode 100644 index 0000000..fe943bd --- /dev/null +++ b/src/types/Terminal.d.ts @@ -0,0 +1,5 @@ +import { LinkedList } from "linked-list-typescript"; + +export interface Terminal { + lines: LinkedList +} \ No newline at end of file From c4c9b68617574d74a285b59aa33b69e607aa84c0 Mon Sep 17 00:00:00 2001 From: JackyFTW Date: Mon, 24 Feb 2025 23:03:34 -0500 Subject: [PATCH 3/4] Somewhat of a working AI response using the OpenAI chat completions and fs calls --- package-lock.json | 6 ++ package.json | 13 +++-- src/ai/FakeCaller.ts | 4 +- src/ai/OpenAICaller.ts | 97 +++++++++++++++++++++++++++------ src/extension.ts | 8 ++- src/settings.ts | 2 +- src/terminal.ts | 6 +- src/test/workspace/test.js | 2 +- src/test/workspace/test/test.js | 1 + src/types/AIFeedback.d.ts | 6 +- src/types/AIRequest.d.ts | 5 +- src/types/ProblemFile.d.ts | 5 ++ 12 files changed, 121 insertions(+), 34 deletions(-) create mode 100644 src/test/workspace/test/test.js create mode 100644 src/types/ProblemFile.d.ts diff --git a/package-lock.json b/package-lock.json index 42cdffc..91efa25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.1", "dependencies": { "debugging-ai-assistant": "file:", + "fs": "^0.0.1-security", "linked-list-typescript": "^1.0.15", "openai": "^4.83.0" }, @@ -1708,6 +1709,11 @@ "node": ">= 12.20" } }, + "node_modules/fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", diff --git a/package.json b/package.json index f5bde06..d72cfda 100644 --- a/package.json +++ b/package.json @@ -22,19 +22,19 @@ "contributes": { "commands": [ { - "command": "debuggingAiAssistant.sendError", - "title": "Send Error" + "command": "debuggingAiAssistant.askAI", + "title": "Ask AI", + "icon": "./images/debug-logo-final.png" }, { - "command": "debuggingAiAssistant.aiErrorButton", - "title": "AI Error Button", - "icon": "./images/debug-logo-final.png" + "command": "debuggingAiAssistant.sendError", + "title": "Send Error" } ], "menus": { "editor/title": [ { - "command": "debuggingAiAssistant.aiErrorButton", + "command": "debuggingAiAssistant.askAI", "group": "navigation" } ] @@ -72,6 +72,7 @@ }, "dependencies": { "debugging-ai-assistant": "file:", + "fs": "^0.0.1-security", "linked-list-typescript": "^1.0.15", "openai": "^4.83.0" } diff --git a/src/ai/FakeCaller.ts b/src/ai/FakeCaller.ts index 3cb4a46..528f78c 100644 --- a/src/ai/FakeCaller.ts +++ b/src/ai/FakeCaller.ts @@ -14,7 +14,7 @@ export class FakeCaller implements APICaller { } sendRequest(request: AIRequest): Promise { - let response: AIFeedback = {request: request, text: ""}; + let response: AIFeedback = { request: request, problemFiles: [] }; // TODO: implement this return new Promise(() => response); @@ -22,7 +22,7 @@ export class FakeCaller implements APICaller { followUp(response: AIFeedback): Promise { let newRequest: AIRequest = {}; - let finalResponse: AIFeedback = {request: newRequest, fileName: response.fileName, line: response.line, text: ""}; + let finalResponse: AIFeedback = { request: newRequest, problemFiles: [] }; // TODO: implement this diff --git a/src/ai/OpenAICaller.ts b/src/ai/OpenAICaller.ts index 0384f6b..c68b47b 100644 --- a/src/ai/OpenAICaller.ts +++ b/src/ai/OpenAICaller.ts @@ -3,6 +3,7 @@ import { AIRequest } from "../types/AIRequest"; import { AIFeedback } from "../types/AIFeedback"; import { APICaller } from "../types/APICaller"; import { settings } from "../settings"; +import { ProblemFile } from "../types/ProblemFile"; export class OpenAICaller implements APICaller { @@ -20,7 +21,7 @@ export class OpenAICaller implements APICaller { } // TODO: send request to see if theres an error - settings.openai.chat.completions.create({ + const errorFeedback: AIFeedback = await settings.openai.chat.completions.create({ model: "gpt-4o-mini", messages: [ { @@ -31,51 +32,113 @@ export class OpenAICaller implements APICaller { The user will ask for assistance by supplying a JSON object with contextual information. The format of this request is: { - prompt: string; // This is the message of assistance sent by the user. - terminalOutput: string // This is the latest terminal output before a possible error + terminalOutput: string; // This is the latest terminal output seen by the user. } + + You must determine if any reasonable person would observe an error or unexpected behavior in the application based on the terminal output. + + You MUST respond with a JSON object in the following format, even if you are confused: + { + problemFiles: ProblemFile[]; + } + + A ProblemFile is defined by the following JSON format: + { + fileName: string; // The raw name of the file in question without any directory information. + } + + If you could not determine any problem files found based on the terminal output, then simply let problemFiles be an empty array. + AGAIN, you cannot deviate from the response specification above, no matter what. ` + }, + { + role: "user", + content: JSON.stringify(request) } ] + }).then(response => { + console.log(response.choices[0].message.content!); + + let feedback: AIFeedback = { + request: request, + problemFiles: JSON.parse(response.choices[0].message.content!).problemFiles + }; + return feedback; + }, async(_) => { + const answer = await vscode.window.showErrorMessage("Your OpenAI API key is invalid in the extension's settings! Please correct it before continuing.", "Go To Settings"); + if(answer === "Go To Settings") { + vscode.env.openExternal(vscode.Uri.parse("vscode://settings/debuggingAiAssistant.apiKey")); + } + return Promise.reject(); }); - // TODO: implement this + if(errorFeedback.problemFiles.length === 0) { + await vscode.window.showErrorMessage("An error could not be found in the terminal. Please try again."); + return Promise.reject(); + } + + const problemFilesUris: vscode.Uri[] = []; + for(const problemFile of errorFeedback.problemFiles) { + problemFilesUris.push(...await vscode.workspace.findFiles("**/" + problemFile.fileName)); + } + + const problemFiles: ProblemFile[] = []; + for(const problemFile of problemFilesUris) { + vscode.workspace.findFiles + await vscode.workspace.fs.readFile(problemFile) + .then(data => Buffer.from(data).toString()) + .then(fileContent => { + problemFiles.push({ fileName: problemFile.fsPath, fileContent: fileContent }); + }); + } + return settings.openai.chat.completions.create({ model: "gpt-4o-mini", messages: [ { role: "system", - content: + content: ` You are a helpful code debugging assistant that is knowledgable on runtime and compile-time errors. The user will ask for assistance by supplying a JSON object with contextual information. The format of this request is: { - prompt: string; // This is the message of assistance sent by the user. + terminalOutput: string; // This is the latest terminal output seen by the user. + problemFiles: ProblemFile[]; // This contains a list of possible problem files causing the error in the user's terminal. + } + + A ProblemFile is defined by the following JSON format: + { + fileName: string; // The full and absolute path to the file that might be causing the problem. + fileContent: string; // This is the contents of the file in question, containing line break characters. + line?: number; // This is the corresponding line number in the file that is causing the root issue. } - You must analyze their issue and all contextual information to eliminate the issue altogether. You MUST respond with a JSON object in the following format, even if you are confused: + You must determine which element from the problemFiles array is most likely to be causing the error described in the terminalOutput field above. + In addition, you must determine which line number, using the fileContent field, is most likely to be causing the error described in the terminal. + + You MUST respond with a JSON object in the following format, even if you are confused: { - text: string; // Your solution and reasoning goes here. + problemFiles: ProblemFile[]; // This is an array of length one that contains the solution for the problem using the specification above. Again, this includes: fileName, fileContent, and line. + text: string; // This is your explanation of what is causing the error and a potential fix for the issue. Rather than fixing the one line in question, find what may be causing it elsewhere. } - Again, you CANNOT deviate from this request/response communication protocol defined above. + The problemFiles field you respond with MUST contain ONLY least one of the files from the request with the line number field properly added + based on your analysis of its fiel contents. + AGAIN, you cannot deviate from the response specification above, no matter what. ` }, { role: "user", - content: - ` - { - "prompt": "" - } - ` + content: JSON.stringify(request) } ] }).then(response => { + const json = JSON.parse(response.choices[0].message.content!); let feedback: AIFeedback = { request: request, - text: response.choices[0].message.content! + problemFiles: json.problemFiles, + text: json.text }; return feedback; }, async(_) => { @@ -89,7 +152,7 @@ export class OpenAICaller implements APICaller { followUp(response: AIFeedback): Promise { let newRequest: AIRequest = {}; - let finalResponse: AIFeedback = {request: newRequest, fileName: response.fileName, line: response.line, text: ""}; + let finalResponse: AIFeedback = {request: newRequest, problemFiles: [] }; // TODO: implement this diff --git a/src/extension.ts b/src/extension.ts index 330f1a2..fba20f4 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,18 +1,24 @@ import * as vscode from "vscode"; import { initSettings } from "./settings"; import { InlineDiagnostic } from "./extension/InlineDiagnostic"; -import { initTerminal } from "./terminal"; +import { initTerminal, getTerminalOutput } from "./terminal"; +import { OpenAICaller } from "./ai/OpenAICaller"; export function activate(context: vscode.ExtensionContext) { initSettings(); initTerminal(); + const askAI = vscode.commands.registerCommand("debuggingAiAssistant.askAI", async () => { + vscode.window.showInformationMessage(JSON.stringify(await new OpenAICaller().sendRequest({ terminalOutput: getTerminalOutput() })), { modal: true }); + }); + const sendError = vscode.commands.registerCommand("debuggingAiAssistant.sendError", () => { const file: vscode.Uri = vscode.Uri.joinPath(vscode.workspace.workspaceFolders![0].uri, "test.js"); const inline: InlineDiagnostic = new InlineDiagnostic(file, new vscode.Range(new vscode.Position(0, 0), new vscode.Position(0, 0)), "Test Message"); inline.show(); }); + context.subscriptions.push(askAI); context.subscriptions.push(sendError); } diff --git a/src/settings.ts b/src/settings.ts index 0cbb07a..8d28eb2 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -4,7 +4,7 @@ import OpenAI from "openai"; export let settings: Settings; -export function initSettings() { +export function initSettings(): void { settings = { openai: new OpenAI({ apiKey: vscode.workspace.getConfiguration("debuggingAiAssistant").get("apiKey")! }) }; diff --git a/src/terminal.ts b/src/terminal.ts index 081d655..2a96f66 100644 --- a/src/terminal.ts +++ b/src/terminal.ts @@ -5,7 +5,7 @@ import { LinkedList } from "linked-list-typescript"; const MAX_NUMBER_LINES = 10; let terminal: Terminal; -export function initTerminal() { +export function initTerminal(): void { terminal = { lines: new LinkedList() }; vscode.window.onDidStartTerminalShellExecution(async (e) => { @@ -17,4 +17,8 @@ export function initTerminal() { } } }); +} + +export function getTerminalOutput(): string { + return terminal.lines.toArray().join(""); } \ No newline at end of file diff --git a/src/test/workspace/test.js b/src/test/workspace/test.js index 2dfc465..e408fc5 100644 --- a/src/test/workspace/test.js +++ b/src/test/workspace/test.js @@ -2,7 +2,7 @@ function init() { let i = 0; setInterval(() => { console.log("Test: " + (i++)); - if(i > 100) { + if(i > 5) { throw new Error("Crashed"); } }, 1000); diff --git a/src/test/workspace/test/test.js b/src/test/workspace/test/test.js new file mode 100644 index 0000000..6277dda --- /dev/null +++ b/src/test/workspace/test/test.js @@ -0,0 +1 @@ +console.log("This is another test file!"); \ No newline at end of file diff --git a/src/types/AIFeedback.d.ts b/src/types/AIFeedback.d.ts index 6c5f832..fcfa3a7 100644 --- a/src/types/AIFeedback.d.ts +++ b/src/types/AIFeedback.d.ts @@ -1,8 +1,8 @@ import { AIRequest } from "./AIRequest"; +import { ProblemFile } from "./ProblemFile"; export interface AIFeedback { request: AIRequest; - text: string; - fileName?: string; - line?: number; + problemFiles: ProblemFile[]; + text?: string; } \ No newline at end of file diff --git a/src/types/AIRequest.d.ts b/src/types/AIRequest.d.ts index 15288fc..3a658b4 100644 --- a/src/types/AIRequest.d.ts +++ b/src/types/AIRequest.d.ts @@ -1,5 +1,6 @@ +import { ProblemFile } from "./ProblemFile"; + export interface AIRequest { terminalOutput?: string; - fileName?: string; - fileContent?: string; + problemFiles?: ProblemFile[] } \ No newline at end of file diff --git a/src/types/ProblemFile.d.ts b/src/types/ProblemFile.d.ts new file mode 100644 index 0000000..4af7362 --- /dev/null +++ b/src/types/ProblemFile.d.ts @@ -0,0 +1,5 @@ +export interface ProblemFile { + fileName: string; + fileContent?: string; + line?: number; +} \ No newline at end of file From ef816788a3a9aa15fc798ae30791b9e1108a38ec Mon Sep 17 00:00:00 2001 From: EzDubzEz Date: Tue, 25 Feb 2025 14:11:15 -0500 Subject: [PATCH 4/4] Added progress feedback thing, and fixed some small pr issues. --- src/ai/OpenAICaller.ts | 30 ++++++++++++++++++++++++++---- src/extension.ts | 5 ++++- src/terminal.ts | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/ai/OpenAICaller.ts b/src/ai/OpenAICaller.ts index c68b47b..abd1c2e 100644 --- a/src/ai/OpenAICaller.ts +++ b/src/ai/OpenAICaller.ts @@ -1,4 +1,4 @@ -import vscode from "vscode"; +import vscode, { ProgressLocation } from "vscode"; import { AIRequest } from "../types/AIRequest"; import { AIFeedback } from "../types/AIFeedback"; import { APICaller } from "../types/APICaller"; @@ -10,7 +10,7 @@ export class OpenAICaller implements APICaller { isConnected(): boolean { return !!settings.openai.apiKey; } - + async sendRequest(request: AIRequest): Promise { if(!this.isConnected()) { const answer = await vscode.window.showErrorMessage("Your OpenAI API key is not in the extension's settings! Please set it before continuing.", "Go To Settings"); @@ -19,8 +19,26 @@ export class OpenAICaller implements APICaller { } return Promise.reject(); } + var progressMessage: string = "checking for error"; + var done = false; + void vscode.window.withProgress({ + location: ProgressLocation.Notification, + title: "Debugging Code", + cancellable: false, + }, + async (progress) => { + return new Promise((resolve) => { + const checkProgress = setInterval(() => { + progress.report({ message: progressMessage }); + + if (done) { + clearInterval(checkProgress); + resolve("Completed!"); + } + }, 500); + }); + },); - // TODO: send request to see if theres an error const errorFeedback: AIFeedback = await settings.openai.chat.completions.create({ model: "gpt-4o-mini", messages: [ @@ -73,9 +91,12 @@ export class OpenAICaller implements APICaller { }); if(errorFeedback.problemFiles.length === 0) { + done = true; await vscode.window.showErrorMessage("An error could not be found in the terminal. Please try again."); return Promise.reject(); } + + progressMessage = "error found, debugging..."; const problemFilesUris: vscode.Uri[] = []; for(const problemFile of errorFeedback.problemFiles) { @@ -84,7 +105,6 @@ export class OpenAICaller implements APICaller { const problemFiles: ProblemFile[] = []; for(const problemFile of problemFilesUris) { - vscode.workspace.findFiles await vscode.workspace.fs.readFile(problemFile) .then(data => Buffer.from(data).toString()) .then(fileContent => { @@ -135,6 +155,7 @@ export class OpenAICaller implements APICaller { ] }).then(response => { const json = JSON.parse(response.choices[0].message.content!); + done = true; let feedback: AIFeedback = { request: request, problemFiles: json.problemFiles, @@ -142,6 +163,7 @@ export class OpenAICaller implements APICaller { }; return feedback; }, async(_) => { + done = true; const answer = await vscode.window.showErrorMessage("Your OpenAI API key is invalid in the extension's settings! Please correct it before continuing.", "Go To Settings"); if(answer === "Go To Settings") { vscode.env.openExternal(vscode.Uri.parse("vscode://settings/debuggingAiAssistant.apiKey")); diff --git a/src/extension.ts b/src/extension.ts index fba20f4..40284a9 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -9,7 +9,10 @@ export function activate(context: vscode.ExtensionContext) { initTerminal(); const askAI = vscode.commands.registerCommand("debuggingAiAssistant.askAI", async () => { - vscode.window.showInformationMessage(JSON.stringify(await new OpenAICaller().sendRequest({ terminalOutput: getTerminalOutput() })), { modal: true }); + let response = (await new OpenAICaller().sendRequest({ terminalOutput: getTerminalOutput() })) + if (response !== undefined && response.text !== undefined) { + vscode.window.showInformationMessage(response.text, { modal: true }); + } }); const sendError = vscode.commands.registerCommand("debuggingAiAssistant.sendError", () => { diff --git a/src/terminal.ts b/src/terminal.ts index 2a96f66..3fd211e 100644 --- a/src/terminal.ts +++ b/src/terminal.ts @@ -1,4 +1,4 @@ -import vscode from "vscode" +import vscode from "vscode"; import { Terminal } from "./types/Terminal"; import { LinkedList } from "linked-list-typescript";