|
|
|
|
@ -0,0 +1,510 @@
|
|
|
|
|
import vscode from "vscode";
|
|
|
|
|
import path from "path";
|
|
|
|
|
import {callQwenAPI} from "./utils/modelApi";
|
|
|
|
|
import {generateCodeDiff, getFileExtension} from "./utils/common";
|
|
|
|
|
|
|
|
|
|
// 定义全局变量来存储面板状态
|
|
|
|
|
let currentSessionHistory: { role: string; content: string }[] = [];
|
|
|
|
|
// 存储工作区变更的文件,包含状态信息
|
|
|
|
|
let workspaceChanges: {
|
|
|
|
|
[key: string]: {
|
|
|
|
|
original: string;
|
|
|
|
|
modified: string;
|
|
|
|
|
status: 'pending' | 'accepted' | 'rejected'
|
|
|
|
|
}
|
|
|
|
|
} = {};
|
|
|
|
|
|
|
|
|
|
export class MessageHandler {
|
|
|
|
|
private provider: any; // 这里应该使用AISidebarViewProvider类型,但由于循环依赖问题,暂时使用any
|
|
|
|
|
private context: vscode.ExtensionContext;
|
|
|
|
|
private currentReader: ReadableStreamDefaultReader<Uint8Array> | null = null; // 添加当前reader引用
|
|
|
|
|
|
|
|
|
|
constructor(provider: any, context: vscode.ExtensionContext) {
|
|
|
|
|
this.provider = provider;
|
|
|
|
|
this.context = context;
|
|
|
|
|
this.currentReader = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async handleMessage(message: any) {
|
|
|
|
|
switch (message.command) {
|
|
|
|
|
case 'ask':
|
|
|
|
|
await this.handleAsk(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'cancelRequest':
|
|
|
|
|
await this.handleCancelRequest();
|
|
|
|
|
break;
|
|
|
|
|
case 'selectContextFile':
|
|
|
|
|
await this.handleSelectContextFile();
|
|
|
|
|
break;
|
|
|
|
|
case 'getFileList':
|
|
|
|
|
await this.handleGetFileList();
|
|
|
|
|
break;
|
|
|
|
|
case 'selectFileByPath':
|
|
|
|
|
await this.handleSelectFileByPath(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'showCodeDiffInEditor':
|
|
|
|
|
await this.handleShowCodeDiffInEditor(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'acceptChanges':
|
|
|
|
|
await this.handleAcceptChanges(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'rejectChanges':
|
|
|
|
|
await this.handleRejectChanges(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'openWorkspaceFile':
|
|
|
|
|
await this.handleOpenWorkspaceFile(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'getCodeChanges':
|
|
|
|
|
this.handleGetCodeChanges();
|
|
|
|
|
break;
|
|
|
|
|
case 'createNewFile':
|
|
|
|
|
await this.handleCreateNewFile(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'restoreState':
|
|
|
|
|
this.handleRestoreState(message);
|
|
|
|
|
break;
|
|
|
|
|
case 'log' :
|
|
|
|
|
console.log( ...message.data);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleAsk(message: any) {
|
|
|
|
|
const question = message.text;
|
|
|
|
|
const fileContent = message.fileContent;
|
|
|
|
|
const fileName = message.fileContentPath ? path.basename(message.fileContentPath) : "current_file.txt";
|
|
|
|
|
const history = currentSessionHistory;
|
|
|
|
|
|
|
|
|
|
currentSessionHistory = [...history, {role: 'user', content: question}];
|
|
|
|
|
|
|
|
|
|
this.provider._postMessage({command: 'addMessage', role: 'user', content: question});
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const response = await callQwenAPI(question, history, fileContent, this.context, fileName);
|
|
|
|
|
|
|
|
|
|
// 发送开始流式传输的消息
|
|
|
|
|
this.provider._postMessage({command: 'startStream', role: 'assistant'});
|
|
|
|
|
|
|
|
|
|
// 处理流式响应
|
|
|
|
|
const reader = response.body?.getReader();
|
|
|
|
|
this.currentReader = reader; // 保存reader引用
|
|
|
|
|
const decoder = new TextDecoder('utf-8');
|
|
|
|
|
let aiMessage = '';
|
|
|
|
|
|
|
|
|
|
if (reader) {
|
|
|
|
|
try {
|
|
|
|
|
while (true) {
|
|
|
|
|
const {done, value} = await reader.read();
|
|
|
|
|
if (done) break;
|
|
|
|
|
|
|
|
|
|
const chunk = decoder.decode(value, {stream: true});
|
|
|
|
|
|
|
|
|
|
// 检查是否包含event: end事件
|
|
|
|
|
let processedChunk = chunk;
|
|
|
|
|
if (chunk.includes('event: end')) {
|
|
|
|
|
// 只处理event: end之前的内容
|
|
|
|
|
const endIndex = chunk.indexOf('event: end');
|
|
|
|
|
processedChunk = chunk.substring(0, endIndex);
|
|
|
|
|
|
|
|
|
|
// 处理截取后的内容
|
|
|
|
|
if (processedChunk.startsWith('data:')) {
|
|
|
|
|
// 移除data:前缀
|
|
|
|
|
processedChunk = processedChunk.replace(/^data:/, '');
|
|
|
|
|
// 逐个匹配换行符,当出现两个或更多连续换行符时删除多余的
|
|
|
|
|
processedChunk = processedChunk.replace(/^(\n{2,})/, (match) => {
|
|
|
|
|
// 删除所有连续的换行符
|
|
|
|
|
return '';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (processedChunk) {
|
|
|
|
|
aiMessage += processedChunk;
|
|
|
|
|
|
|
|
|
|
// 发送流式数据到前端
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'streamData',
|
|
|
|
|
data: processedChunk
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 停止继续处理
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (chunk.startsWith('data:')) {
|
|
|
|
|
// 移除data:前缀
|
|
|
|
|
processedChunk = chunk.replace(/^data:/, '');
|
|
|
|
|
// 逐个匹配换行符,当出现两个或更多连续换行符时删除多余的
|
|
|
|
|
processedChunk = processedChunk.replace(/^(\n{2,})/, (match) => {
|
|
|
|
|
// 删除所有连续的换行符
|
|
|
|
|
return '';
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aiMessage += processedChunk;
|
|
|
|
|
|
|
|
|
|
// 发送流式数据到前端
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'streamData',
|
|
|
|
|
data: processedChunk
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (readError: any) {
|
|
|
|
|
// 检查是否是由于取消请求导致的中断
|
|
|
|
|
if (readError.name === 'AbortError' || readError.message.includes('cancel')) {
|
|
|
|
|
// 通知前端请求已中断
|
|
|
|
|
this.provider._postMessage({command: 'requestCancelled'});
|
|
|
|
|
// 重置状态但不抛出错误
|
|
|
|
|
this.provider._postMessage({command: 'hideLoading'});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// 如果是网络连接中断错误,我们仍然处理已接收的数据
|
|
|
|
|
if (readError.message.includes('terminated') || readError.message.includes('other side closed') || readError.name === 'TypeError') {
|
|
|
|
|
// 继续处理已接收的数据
|
|
|
|
|
console.log("网络连接中断,但将继续处理已接收的数据");
|
|
|
|
|
aiMessage += "```"
|
|
|
|
|
} else {
|
|
|
|
|
// 如果是其他错误,重新抛出
|
|
|
|
|
throw readError;
|
|
|
|
|
}
|
|
|
|
|
} finally {
|
|
|
|
|
// 清理reader引用
|
|
|
|
|
this.currentReader = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// console.log("aiMessage:",aiMessage)
|
|
|
|
|
// 流传输完成后,更新会话历史
|
|
|
|
|
currentSessionHistory = [...currentSessionHistory, {role: 'assistant', content: aiMessage}];
|
|
|
|
|
|
|
|
|
|
// 解析AI响应中的多个代码块并生成独立的codeDiff信息
|
|
|
|
|
const codeBlocks = aiMessage.match(/```[\s\S]*?```/g) || [];
|
|
|
|
|
// console.log("codeBlocks:",codeBlocks)
|
|
|
|
|
|
|
|
|
|
// 存储所有生成的codeDiff
|
|
|
|
|
const allCodeDiffs = [];
|
|
|
|
|
|
|
|
|
|
for (const block of codeBlocks) {
|
|
|
|
|
// 生成codeDiff
|
|
|
|
|
const codeDiff = generateCodeDiff(fileContent, block);
|
|
|
|
|
|
|
|
|
|
if (codeDiff) {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
allCodeDiffs.push(codeDiff);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// console.log("allCodeDiffs:",allCodeDiffs)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 通知前端流传输完成
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'endStream',
|
|
|
|
|
content: aiMessage,
|
|
|
|
|
codeDiffs: allCodeDiffs // 传递多个codeDiff信息
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 如果有代码差异,保存到工作区变更中
|
|
|
|
|
if (allCodeDiffs.length > 0 && fileContent && message.fileContentPath) {
|
|
|
|
|
// 为每个codeDiff创建独立的workspaceChange
|
|
|
|
|
for (let i = 0; i < allCodeDiffs.length; i++) {
|
|
|
|
|
const codeDiff = allCodeDiffs[i];
|
|
|
|
|
const filePath = message.fileContentPath;
|
|
|
|
|
|
|
|
|
|
// 创建唯一的工作区变更键
|
|
|
|
|
const changeKey = `${filePath}`;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
workspaceChanges[changeKey] = {
|
|
|
|
|
original: fileContent,
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
modified: codeDiff.modifiedCode,
|
|
|
|
|
status: 'pending'
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知 WebView 更新工作区文件列表
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'updateWorkspaceFiles',
|
|
|
|
|
files: workspaceChanges
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
console.log("error:",error)
|
|
|
|
|
// 检查是否是由于取消请求导致的中断
|
|
|
|
|
if (error.name === 'AbortError' || error.message.includes('cancel') || error.message.includes('中断')) {
|
|
|
|
|
this.provider._postMessage({command: 'requestCancelled'});
|
|
|
|
|
} else if (error.message.includes('terminated') || error.message.includes('other side closed') || error.name === 'TypeError') {
|
|
|
|
|
// 处理网络连接中断错误,但仍显示已接收的内容
|
|
|
|
|
this.provider._postMessage({command: 'addMessage', role: 'ai', content: '网络连接中断,但以下为已接收的内容:'});
|
|
|
|
|
// 如果有已接收的内容,也显示出来
|
|
|
|
|
// 通知前端流传输完成
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'endStream',
|
|
|
|
|
content: '',
|
|
|
|
|
codeDiffs: []
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.provider._postMessage({command: 'addMessage', role: 'ai', content: '调用失败:' + error.message});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.provider._postMessage({command: 'hideLoading'});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleSelectContextFile() {
|
|
|
|
|
// 执行文件选择逻辑
|
|
|
|
|
const uris = await vscode.window.showOpenDialog({
|
|
|
|
|
canSelectFiles: true,
|
|
|
|
|
canSelectFolders: false,
|
|
|
|
|
canSelectMany: false,
|
|
|
|
|
title: "选择一个文件作为上下文"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (uris && uris.length > 0) {
|
|
|
|
|
const selectedFileUri = uris[0];
|
|
|
|
|
const fileContent = await vscode.workspace.fs.readFile(selectedFileUri);
|
|
|
|
|
const decodedContent = new TextDecoder("utf-8").decode(fileContent);
|
|
|
|
|
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'setContextFile',
|
|
|
|
|
fileName: selectedFileUri.fsPath,
|
|
|
|
|
fileContent: decodedContent
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleGetFileList() {
|
|
|
|
|
// 执行获取文件列表逻辑
|
|
|
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
|
|
|
if (workspaceFolders && workspaceFolders.length > 0) {
|
|
|
|
|
const fileUris = await vscode.workspace.findFiles('**/*', '**/node_modules/**');
|
|
|
|
|
|
|
|
|
|
const files = fileUris.map(uri => {
|
|
|
|
|
const relativePath = vscode.workspace.asRelativePath(uri);
|
|
|
|
|
return {
|
|
|
|
|
path: uri.fsPath,
|
|
|
|
|
relativePath: relativePath,
|
|
|
|
|
name: path.basename(uri.fsPath),
|
|
|
|
|
isDirectory: false // 简化处理,实际可以根据扩展名判断
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'fileList',
|
|
|
|
|
files: files
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleSelectFileByPath(message: any) {
|
|
|
|
|
// 根据路径选择文件
|
|
|
|
|
try {
|
|
|
|
|
const fileUri = vscode.Uri.file(message.filePath);
|
|
|
|
|
const fileContent = await vscode.workspace.fs.readFile(fileUri);
|
|
|
|
|
const decodedContent = new TextDecoder("utf-8").decode(fileContent);
|
|
|
|
|
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'setContextFile',
|
|
|
|
|
fileName: fileUri.fsPath,
|
|
|
|
|
fileContent: decodedContent
|
|
|
|
|
});
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
vscode.window.showErrorMessage(`无法读取文件: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleShowCodeDiffInEditor(message: any) {
|
|
|
|
|
// 在编辑器中显示代码差异
|
|
|
|
|
try {
|
|
|
|
|
const originalCode = message.originalCode || '';
|
|
|
|
|
const modifiedCode = message.modifiedCode || '';
|
|
|
|
|
|
|
|
|
|
// 创建原始代码的虚拟文档
|
|
|
|
|
const originalUri = vscode.Uri.parse('untitled:original-code.txt');
|
|
|
|
|
const originalDoc = await vscode.workspace.openTextDocument(originalUri);
|
|
|
|
|
const originalEditor = await vscode.window.showTextDocument(originalDoc, vscode.ViewColumn.One, true);
|
|
|
|
|
await originalEditor.edit(edit => {
|
|
|
|
|
edit.insert(new vscode.Position(0, 0), originalCode);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 创建修改后代码的虚拟文档
|
|
|
|
|
const modifiedUri = vscode.Uri.parse('untitled:modified-code.txt');
|
|
|
|
|
const modifiedDoc = await vscode.workspace.openTextDocument(modifiedUri);
|
|
|
|
|
const modifiedEditor = await vscode.window.showTextDocument(modifiedDoc, vscode.ViewColumn.Two, true);
|
|
|
|
|
await modifiedEditor.edit(edit => {
|
|
|
|
|
edit.insert(new vscode.Position(0, 0), modifiedCode);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 使用 VS Code 的 diff 命令显示差异
|
|
|
|
|
await vscode.commands.executeCommand(
|
|
|
|
|
'vscode.diff',
|
|
|
|
|
originalUri,
|
|
|
|
|
modifiedUri,
|
|
|
|
|
'Code Diff - Original ↔ Modified'
|
|
|
|
|
);
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
vscode.window.showErrorMessage(`显示代码差异失败: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleAcceptChanges(message: any) {
|
|
|
|
|
// 接受代码变更
|
|
|
|
|
try {
|
|
|
|
|
const {filePath, modifiedContent} = message;
|
|
|
|
|
const fileUri = vscode.Uri.file(filePath);
|
|
|
|
|
|
|
|
|
|
// 将修改后的内容写入文件
|
|
|
|
|
const encodedContent = new TextEncoder().encode(modifiedContent);
|
|
|
|
|
await vscode.workspace.fs.writeFile(fileUri, encodedContent);
|
|
|
|
|
|
|
|
|
|
// 更新工作区变更状态
|
|
|
|
|
if (workspaceChanges[filePath]) {
|
|
|
|
|
workspaceChanges[filePath].status = 'accepted';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知 WebView 更新工作区文件列表
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'updateWorkspaceFiles',
|
|
|
|
|
files: workspaceChanges
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
vscode.window.showInformationMessage('代码变更已应用');
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
vscode.window.showErrorMessage(`应用代码变更失败: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleRejectChanges(message: any) {
|
|
|
|
|
// 拒绝代码变更
|
|
|
|
|
try {
|
|
|
|
|
const {filePath} = message;
|
|
|
|
|
|
|
|
|
|
// 更新工作区变更状态
|
|
|
|
|
if (workspaceChanges[filePath]) {
|
|
|
|
|
workspaceChanges[filePath].status = 'rejected';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知 WebView 更新工作区文件列表
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'updateWorkspaceFiles',
|
|
|
|
|
files: workspaceChanges
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
vscode.window.showInformationMessage('代码变更已拒绝');
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
vscode.window.showErrorMessage(`拒绝代码变更失败: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleOpenWorkspaceFile(message: any) {
|
|
|
|
|
// 打开工作区文件
|
|
|
|
|
try {
|
|
|
|
|
const {filePath} = message;
|
|
|
|
|
const fileUri = vscode.Uri.file(filePath);
|
|
|
|
|
|
|
|
|
|
// 检查文件是否已经打开
|
|
|
|
|
let fileAlreadyOpen = false;
|
|
|
|
|
const openedTextDocuments = vscode.workspace.textDocuments;
|
|
|
|
|
|
|
|
|
|
for (const doc of openedTextDocuments) {
|
|
|
|
|
if (doc.uri.fsPath === fileUri.fsPath) {
|
|
|
|
|
fileAlreadyOpen = true;
|
|
|
|
|
// 激活已打开的文件
|
|
|
|
|
await vscode.window.showTextDocument(doc, {
|
|
|
|
|
viewColumn: vscode.ViewColumn.One // 切换到已打开的文件
|
|
|
|
|
});
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 如果文件未打开,则在新窗口打开
|
|
|
|
|
if (!fileAlreadyOpen) {
|
|
|
|
|
await vscode.window.showTextDocument(fileUri, {
|
|
|
|
|
viewColumn: vscode.ViewColumn.One // 在第一列打开文件
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
vscode.window.showErrorMessage(`打开文件失败: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleGetCodeChanges() {
|
|
|
|
|
// 获取代码变更
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'codeChanges',
|
|
|
|
|
changes: workspaceChanges
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private async handleCreateNewFile(message: any) {
|
|
|
|
|
// 创建新文件功能
|
|
|
|
|
try {
|
|
|
|
|
const {fileName, content, language} = message;
|
|
|
|
|
|
|
|
|
|
// 获取根工作区路径
|
|
|
|
|
const workspaceFolders = vscode.workspace.workspaceFolders;
|
|
|
|
|
if (!workspaceFolders || workspaceFolders.length === 0) {
|
|
|
|
|
vscode.window.showErrorMessage('未找到工作区');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 根据语言确定文件扩展名
|
|
|
|
|
const fileExtension = getFileExtension(language);
|
|
|
|
|
const fullFileName = fileName.endsWith(fileExtension) ? fileName : `${fileName}${fileExtension}`;
|
|
|
|
|
|
|
|
|
|
// 创建文件路径(在根目录下)
|
|
|
|
|
const filePath = path.join(workspaceFolders[0].uri.fsPath, fullFileName);
|
|
|
|
|
const fileUri = vscode.Uri.file(filePath);
|
|
|
|
|
|
|
|
|
|
// 将内容写入文件
|
|
|
|
|
const encodedContent = new TextEncoder().encode(content);
|
|
|
|
|
await vscode.workspace.fs.writeFile(fileUri, encodedContent);
|
|
|
|
|
|
|
|
|
|
// 在编辑器中打开新创建的文件
|
|
|
|
|
await vscode.window.showTextDocument(fileUri, {
|
|
|
|
|
viewColumn: vscode.ViewColumn.One
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
vscode.window.showInformationMessage(`文件 ${fullFileName} 已创建`);
|
|
|
|
|
} catch (error: any) {
|
|
|
|
|
vscode.window.showErrorMessage(`生成代码文件失败: ${error.message}`);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private handleRestoreState(message: any) {
|
|
|
|
|
// 恢复面板状态
|
|
|
|
|
currentSessionHistory = message.history || [];
|
|
|
|
|
|
|
|
|
|
// 恢复显示历史消息
|
|
|
|
|
currentSessionHistory.forEach(msg => {
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'addMessage',
|
|
|
|
|
role: msg.role,
|
|
|
|
|
content: msg.content,
|
|
|
|
|
codeDiff: null
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 恢复工作区变更
|
|
|
|
|
if (message.workspaceChanges) {
|
|
|
|
|
this.provider._postMessage({
|
|
|
|
|
command: 'updateWorkspaceFiles',
|
|
|
|
|
files: message.workspaceChanges
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 添加处理取消请求的方法
|
|
|
|
|
private async handleCancelRequest() {
|
|
|
|
|
if (this.currentReader) {
|
|
|
|
|
try {
|
|
|
|
|
await this.currentReader.cancel();
|
|
|
|
|
this.currentReader = null;
|
|
|
|
|
console.log('请求已取消');
|
|
|
|
|
} catch (error) {
|
|
|
|
|
console.error('取消请求时出错:', error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|