Merge pull request #33 from covespace/add_message_hash

Refactor sendMessage and improve DevChat response handling
This commit is contained in:
boob.yang 2023-05-09 13:29:04 +08:00 committed by GitHub
commit da9883f7f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 69 deletions

View File

@ -2,7 +2,7 @@
import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';
import DevChat from '../toolwrapper/devchat';
import DevChat, { ChatResponse } from '../toolwrapper/devchat';
import CommandManager from '../command/commandManager';
import { logger } from '../util/logger';
import { MessageHandler } from './messageHandler';
@ -70,14 +70,22 @@ function getInstructionFiles(): string[] {
}
let lastPromptHash: string | undefined;
// message: { command: 'sendMessage', text: 'xxx', parent_hash: 'xxx'}
// return message:
// { command: 'receiveMessage', text: 'xxxx', hash: 'xxx', user: 'xxx', date: 'xxx'}
// { command: 'receiveMessagePartial', text: 'xxxx', user: 'xxx', date: 'xxx'}
export async function sendMessage(message: any, panel: vscode.WebviewPanel): Promise<void> {
const devChat = new DevChat();
const newText2 = await CommandManager.getInstance().processText(message.text);
const parsedMessage = parseMessage(newText2);
const chatOptions: any = lastPromptHash ? { parent: lastPromptHash } : {};
const chatOptions: any = {};
logger.channel()?.info(`parent_hash: ${message.parent_hash}`)
if (message.parent_hash) {
chatOptions.parent = message.parent_hash;
}
if (parsedMessage.context.length > 0) {
chatOptions.context = parsedMessage.context;
@ -92,25 +100,13 @@ export async function sendMessage(message: any, panel: vscode.WebviewPanel): Pro
chatOptions.reference = parsedMessage.reference;
}
let partialData = "";
const onData = (partialResponse: string) => {
partialData += partialResponse;
MessageHandler.sendMessage(panel, { command: 'receiveMessagePartial', text: partialData }, false);
const onData = (partialResponse: ChatResponse) => {
MessageHandler.sendMessage(panel, { command: 'receiveMessagePartial', text: partialResponse.response, user: partialResponse.user, date: partialResponse.date }, false);
};
const chatResponse = await devChat.chat(parsedMessage.text, chatOptions, onData);
if (chatResponse && typeof chatResponse === 'object' && !Array.isArray(chatResponse) && !(chatResponse instanceof String)) {
// 检查 "prompt-hash" 是否在 chatResponse 中
if ('prompt-hash' in chatResponse) {
// 检查 chatResponse['prompt-hash'] 是否不为空
if (chatResponse['prompt-hash']) {
// 如果 "prompt-hash" 在 chatResponse 中且不为空,则更新 lastPromptHash 的值
lastPromptHash = chatResponse['prompt-hash'];
}
}
}
const response = chatResponse.response;
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: response });
MessageHandler.sendMessage(panel, { command: 'receiveMessage', text: chatResponse.response, hash: chatResponse['prompt-hash'], user: chatResponse.user, date: chatResponse.date, isError: chatResponse.isError });
return;
}

View File

@ -69,7 +69,7 @@ export interface ChatResponse {
class DevChat {
async chat(content: string, options: ChatOptions = {}, onData: (data: string) => void): Promise<ChatResponse> {
async chat(content: string, options: ChatOptions = {}, onData: (data: ChatResponse) => void): Promise<ChatResponse> {
let args = ["prompt"];
if (options.reference) {
@ -123,6 +123,64 @@ class DevChat {
fs.writeFileSync(configPath, configJson);
try {
const parseOutData = (stdout: string, isPartial: boolean) => {
const responseLines = stdout.trim().split("\n");
if (responseLines.length < 2) {
return {
"prompt-hash": "",
user: "",
date: "",
response: "",
isError: isPartial ? false : true,
};
}
const userLine = responseLines.shift()!;
const user = (userLine.match(/User: (.+)/)?.[1]) ?? "";
const dateLine = responseLines.shift()!;
const date = (dateLine.match(/Date: (.+)/)?.[1]) ?? "";
let promptHashLine = "";
for (let i = responseLines.length - 1; i >= 0; i--) {
if (responseLines[i].startsWith("prompt")) {
promptHashLine = responseLines[i];
responseLines.splice(i, 1);
break;
}
}
if (!promptHashLine) {
return {
"prompt-hash": "",
user: user,
date: date,
response: responseLines.join("\n"),
isError: isPartial ? false : true,
};
}
const promptHash = promptHashLine.split(" ")[1];
const response = responseLines.join("\n");
return {
"prompt-hash": promptHash,
user,
date,
response,
isError: false,
};
};
let receviedStdout = "";
const onStdoutPartial = (stdout: string) => {
receviedStdout += stdout;
const data = parseOutData(receviedStdout, true);
onData(data);
};
logger.channel()?.info(`Running devchat with args: ${args.join(" ")}`);
const { code, stdout, stderr } = await spawnAsync('devchat', args, {
maxBuffer: 10 * 1024 * 1024, // Set maxBuffer to 10 MB
@ -131,7 +189,7 @@ class DevChat {
...process.env,
OPENAI_API_KEY: openaiApiKey,
},
}, onData);
}, onStdoutPartial);
if (stderr) {
const errorMessage = stderr.trim().match(/Error(.+)/)?.[1];
@ -144,54 +202,8 @@ class DevChat {
};
}
const responseLines = stdout.trim().split("\n");
if (responseLines.length === 0) {
return {
"prompt-hash": "",
user: "",
date: "",
response: "",
isError: true,
};
}
let promptHashLine = "";
for (let i = responseLines.length - 1; i >= 0; i--) {
if (responseLines[i].startsWith("prompt")) {
promptHashLine = responseLines[i];
responseLines.splice(i, 1);
break;
}
}
if (!promptHashLine) {
return {
"prompt-hash": "",
user: "",
date: "",
response: responseLines.join("\n"),
isError: true,
};
}
const promptHash = promptHashLine.split(" ")[1];
const userLine = responseLines.shift()!;
const user = (userLine.match(/User: (.+)/)?.[1]) ?? "";
const dateLine = responseLines.shift()!;
const date = (dateLine.match(/Date: (.+)/)?.[1]) ?? "";
const response = responseLines.join("\n");
return {
"prompt-hash": promptHash,
user,
date,
response,
isError: false,
};
const response = parseOutData(stdout, false);
return response;
} catch (error: any) {
return {
"prompt-hash": "",