2023-05-05 21:27:40 +08:00
|
|
|
|
|
|
|
import * as vscode from 'vscode';
|
2023-05-09 10:34:33 +08:00
|
|
|
import { MessageHandler } from './messageHandler';
|
2023-05-10 17:56:56 +08:00
|
|
|
import { regInMessage, regOutMessage } from '../util/reg_messages';
|
2023-07-17 18:56:56 +08:00
|
|
|
import { stopDevChatBase, sendMessageBase, deleteChatMessageBase } from './sendMessageBase';
|
|
|
|
import { UiUtilWrapper } from '../util/uiUtil';
|
2023-07-27 08:11:40 +08:00
|
|
|
import * as fs from 'fs';
|
|
|
|
import * as os from 'os';
|
|
|
|
import * as path from 'path';
|
2023-08-21 11:52:00 +08:00
|
|
|
import { ApiKeyManager } from '../util/apiKey';
|
|
|
|
import { logger } from '../util/logger';
|
|
|
|
import { exec as execCb } from 'child_process';
|
|
|
|
import { promisify } from 'util';
|
|
|
|
import { CommandRun, createTempSubdirectory } from '../util/commonUtil';
|
2023-05-10 17:56:56 +08:00
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
const exec = promisify(execCb);
|
2023-05-05 21:27:40 +08:00
|
|
|
|
2023-05-31 16:10:53 +08:00
|
|
|
let _lastMessage: any = undefined;
|
2023-05-09 16:05:49 +08:00
|
|
|
|
2023-07-27 08:11:40 +08:00
|
|
|
export function createTempFile(content: string): string {
|
|
|
|
// Generate a unique file name
|
|
|
|
const fileName = path.join(os.tmpdir(), `temp_${Date.now()}.txt`);
|
|
|
|
|
|
|
|
// Write the content to the file
|
|
|
|
fs.writeFileSync(fileName, content);
|
|
|
|
|
|
|
|
return fileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function deleteTempFiles(fileName: string): void {
|
|
|
|
// Delete the file
|
|
|
|
fs.unlinkSync(fileName);
|
|
|
|
}
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
regInMessage({command: 'askCode', text: '', parent_hash: undefined});
|
|
|
|
regOutMessage({ command: 'receiveMessage', text: 'xxxx', hash: 'xxx', user: 'xxx', date: 'xxx'});
|
|
|
|
export async function askCode(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
2023-08-21 11:52:00 +08:00
|
|
|
_lastMessage = [message];
|
|
|
|
_lastMessage[0]['askCode'] = true;
|
2023-08-21 11:52:00 +08:00
|
|
|
|
2023-10-11 23:51:57 +08:00
|
|
|
const port = await UiUtilWrapper.getLSPBrigePort();
|
|
|
|
|
2023-08-21 11:52:00 +08:00
|
|
|
let pythonVirtualEnv: string|undefined = vscode.workspace.getConfiguration('DevChat').get('PythonVirtualEnv');
|
2023-08-21 11:52:00 +08:00
|
|
|
if (!pythonVirtualEnv) {
|
2023-08-21 11:52:00 +08:00
|
|
|
try {
|
|
|
|
await vscode.commands.executeCommand('DevChat.AskCodeIndexStart');
|
|
|
|
} catch (error) {
|
|
|
|
logger.channel()?.error(`Failed to execute command ${message.content[0]}: ${error}`);
|
|
|
|
logger.channel()?.show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pythonVirtualEnv = vscode.workspace.getConfiguration('DevChat').get('PythonVirtualEnv');
|
|
|
|
if (!pythonVirtualEnv) {
|
|
|
|
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: "Index code fail.", hash: "", user: "", date: 0, isError: true });
|
|
|
|
return ;
|
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
let envs = {};
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
const llmModelData = await ApiKeyManager.llmModel();
|
|
|
|
if (!llmModelData) {
|
|
|
|
logger.channel()?.error('No valid llm model is selected!');
|
|
|
|
logger.channel()?.show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let openaiApiKey = llmModelData.api_key;
|
2023-08-21 11:52:00 +08:00
|
|
|
if (!openaiApiKey) {
|
|
|
|
logger.channel()?.error('The OpenAI key is invalid!');
|
|
|
|
logger.channel()?.show();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
envs['OPENAI_API_KEY'] = openaiApiKey;
|
|
|
|
|
2023-09-13 10:08:16 +08:00
|
|
|
const openAiApiBase = llmModelData.api_base;
|
2023-08-21 11:52:00 +08:00
|
|
|
if (openAiApiBase) {
|
|
|
|
envs['OPENAI_API_BASE'] = openAiApiBase;
|
|
|
|
}
|
|
|
|
|
|
|
|
const workspaceDir = UiUtilWrapper.workspaceFoldersFirstPath();
|
|
|
|
|
|
|
|
try {
|
2023-10-11 23:51:57 +08:00
|
|
|
let outputResult = "";
|
2023-08-21 11:52:00 +08:00
|
|
|
const commandRun = new CommandRun();
|
|
|
|
const command = pythonVirtualEnv.trim();
|
2023-10-11 23:51:57 +08:00
|
|
|
const args = [UiUtilWrapper.extensionPath() + "/tools/askcode_index_query.py", "query", message.text, `${port}`];
|
2023-08-21 11:52:00 +08:00
|
|
|
const result = await commandRun.spawnAsync(command, args, { env: envs, cwd: workspaceDir }, (data) => {
|
2023-10-11 23:51:57 +08:00
|
|
|
outputResult += data;
|
|
|
|
MessageHandler.sendMessage(panel, { command: 'receiveMessagePartial', text: outputResult, hash:"", user:"", isError: false });
|
|
|
|
logger.channel()?.info(data);
|
2023-08-21 11:52:00 +08:00
|
|
|
}, (data) => {
|
|
|
|
logger.channel()?.error(data);
|
|
|
|
}, undefined, undefined);
|
|
|
|
|
2023-10-11 23:51:57 +08:00
|
|
|
if (result.exitCode === 0) {
|
|
|
|
MessageHandler.sendMessage(panel, { command: 'receiveMessagePartial', text: result.stdout, hash:"", user:"", isError: false });
|
|
|
|
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: result.stdout, hash:"", user:"", date:0, isError: false });
|
|
|
|
} else {
|
|
|
|
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: result.stdout + result.stderr, hash: "", user: "", date: 0, isError: true });
|
|
|
|
}
|
2023-08-21 11:52:00 +08:00
|
|
|
} catch (error) {
|
|
|
|
if (error instanceof Error) {
|
|
|
|
logger.channel()?.error(`error: ${error.message}`);
|
|
|
|
} else {
|
|
|
|
logger.channel()?.error(`An unknown error occurred: ${error}`);
|
|
|
|
}
|
|
|
|
logger.channel()?.show();
|
|
|
|
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: "Did not get relevant context from AskCode.", hash: "", user: "", date: 0, isError: true });
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2023-07-17 20:31:01 +08:00
|
|
|
regInMessage({command: 'sendMessage', text: '', parent_hash: undefined});
|
2023-05-10 17:56:56 +08:00
|
|
|
regOutMessage({ command: 'receiveMessage', text: 'xxxx', hash: 'xxx', user: 'xxx', date: 'xxx'});
|
|
|
|
regOutMessage({ command: 'receiveMessagePartial', text: 'xxxx', user: 'xxx', date: 'xxx'});
|
2023-05-09 16:05:49 +08:00
|
|
|
// message: { command: 'sendMessage', text: 'xxx', hash: 'xxx'}
|
2023-05-09 13:24:33 +08:00
|
|
|
// return message:
|
|
|
|
// { command: 'receiveMessage', text: 'xxxx', hash: 'xxx', user: 'xxx', date: 'xxx'}
|
|
|
|
// { command: 'receiveMessagePartial', text: 'xxxx', user: 'xxx', date: 'xxx'}
|
2023-07-24 00:11:56 +08:00
|
|
|
export async function sendMessage(message: any, panel: vscode.WebviewPanel|vscode.WebviewView, function_name: string|undefined = undefined): Promise<void> {
|
2023-08-31 15:15:12 +08:00
|
|
|
if (function_name !== undefined && function_name !== "") {
|
|
|
|
const messageText = _lastMessage[0].text.trim();
|
|
|
|
if (messageText[0] === '/' && message.text[0] !== '/') {
|
|
|
|
const indexS = messageText.indexOf(' ');
|
|
|
|
let preCommand = messageText;
|
|
|
|
if (indexS !== -1) {
|
|
|
|
preCommand = messageText.substring(0, indexS);
|
|
|
|
}
|
|
|
|
|
|
|
|
message.text = preCommand + ' ' + message.text;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_lastMessage = [message, function_name];
|
2023-07-27 08:11:40 +08:00
|
|
|
|
2023-07-27 12:47:56 +08:00
|
|
|
// Add a new field to store the names of temporary files
|
|
|
|
let tempFiles: string[] = [];
|
|
|
|
|
2023-07-27 08:11:40 +08:00
|
|
|
// Handle the contextInfo field in the message
|
|
|
|
if (Array.isArray(message.contextInfo)) {
|
|
|
|
for (let context of message.contextInfo) {
|
|
|
|
if (typeof context === 'object' && context !== null && 'context' in context) {
|
|
|
|
// If the file name is not present, create a temporary file
|
|
|
|
if (!context.file) {
|
|
|
|
try {
|
|
|
|
const contextStr = JSON.stringify(context.context);
|
|
|
|
context.file = createTempFile(contextStr);
|
2023-07-27 12:47:56 +08:00
|
|
|
// Add the file name to the tempFiles array
|
|
|
|
tempFiles.push(context.file);
|
2023-07-27 08:11:40 +08:00
|
|
|
} catch (err) {
|
|
|
|
console.error('Failed to create temporary file:', err);
|
|
|
|
throw err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Insert the file name into the text field
|
|
|
|
message.text += ` [context|${context.file}]`;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-08-21 08:31:52 +08:00
|
|
|
// clear message.contextInfo
|
|
|
|
message.contextInfo = undefined;
|
2023-07-27 08:11:40 +08:00
|
|
|
|
|
|
|
const responseMessage = await sendMessageBase(message, (data: { command: string, text: string, user: string, date: string}) => {
|
|
|
|
MessageHandler.sendMessage(panel, data, false);
|
|
|
|
}, function_name);
|
|
|
|
if (responseMessage) {
|
|
|
|
MessageHandler.sendMessage(panel, responseMessage);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete all temporary files created
|
2023-07-27 12:47:56 +08:00
|
|
|
for (let file of tempFiles) {
|
|
|
|
deleteTempFiles(file);
|
2023-07-27 08:11:40 +08:00
|
|
|
}
|
2023-05-05 21:27:40 +08:00
|
|
|
}
|
|
|
|
|
2023-07-27 08:11:40 +08:00
|
|
|
|
2023-05-23 11:16:48 +08:00
|
|
|
// regeneration last message again
|
|
|
|
regInMessage({command: 'regeneration'});
|
|
|
|
export async function regeneration(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
|
|
|
// call sendMessage to send last message again
|
|
|
|
if (_lastMessage) {
|
2023-08-21 11:52:00 +08:00
|
|
|
if (_lastMessage[0]['askCode']) {
|
|
|
|
await askCode(_lastMessage[0], panel);
|
|
|
|
} else {
|
|
|
|
await sendMessage(_lastMessage[0], panel, _lastMessage[1]);
|
|
|
|
}
|
2023-05-23 11:16:48 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-10 17:56:56 +08:00
|
|
|
regInMessage({command: 'stopDevChat'});
|
2023-05-16 14:35:01 +08:00
|
|
|
export async function stopDevChat(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
2023-05-31 16:10:53 +08:00
|
|
|
stopDevChatBase(message);
|
2023-05-09 14:08:18 +08:00
|
|
|
}
|
|
|
|
|
2023-07-17 18:56:56 +08:00
|
|
|
regInMessage({command: 'deleteChatMessage', hash: 'xxx'});
|
|
|
|
regOutMessage({ command: 'deletedChatMessage', hash: 'xxxx'});
|
|
|
|
export async function deleteChatMessage(message: any, panel: vscode.WebviewPanel|vscode.WebviewView): Promise<void> {
|
|
|
|
// prompt user to confirm
|
|
|
|
const confirm = await vscode.window.showWarningMessage(
|
|
|
|
`Are you sure to delete this message?`,
|
|
|
|
{ modal: true },
|
|
|
|
'Delete'
|
|
|
|
);
|
|
|
|
if (confirm !== 'Delete') {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-07-18 22:54:08 +08:00
|
|
|
const deleted = await deleteChatMessageBase(message);
|
|
|
|
if (deleted) {
|
2023-07-17 18:56:56 +08:00
|
|
|
MessageHandler.sendMessage(panel, { command: 'deletedChatMessage', hash: message.hash });
|
|
|
|
} else {
|
|
|
|
UiUtilWrapper.showErrorMessage('Delete message failed!');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-05-08 12:09:52 +08:00
|
|
|
|
2023-05-05 21:27:40 +08:00
|
|
|
|