feat:修复多面板任务管理和历史会话加载问题

主要改进:
1. 修复面板ID唯一性问题,为每个面板生成唯一ID
2. 修改任务创建时机,改为首次发送消息时创建
3. 修复面板任务映射,同时存储taskId和projectPath
4. 修复历史会话加载后继续对话的保存问题
5. 移除ensureCurrentTask的自动创建逻辑,避免创建多余任务

技术细节:
- 为面板添加__uniqueId属性,确保多窗口独立性
- 修改panelTaskMap数据结构,存储完整任务信息
- 在selectConversation中更新面板任务映射
- 优化任务创建流程,避免空任务目录
This commit is contained in:
Roe-xin
2025-12-28 11:31:28 +08:00
parent 9bdaf34471
commit 3daa66ea01
3 changed files with 86 additions and 14 deletions

View File

@ -13,16 +13,16 @@ export function activate(context: vscode.ExtensionContext) {
// 注册命令:打开助手面板
const openPanelCommand = vscode.commands.registerCommand(
"ic-coder.openPanel",
() => {
showICHelperPanel(context);
async () => {
await showICHelperPanel(context);
}
);
// 注册命令:打开聊天(用于侧边栏)
const openChatCommand = vscode.commands.registerCommand(
"ic-coder.openChat",
() => {
showICHelperPanel(context);
async () => {
await showICHelperPanel(context);
}
);

View File

@ -17,7 +17,7 @@ import { MessageType } from "../types/chatHistory";
/**
* 创建并显示 IC 助手面板
*/
export function showICHelperPanel(
export async function showICHelperPanel(
context: vscode.ExtensionContext,
viewColumn?: vscode.ViewColumn
) {
@ -33,6 +33,10 @@ export function showICHelperPanel(
}
);
// 为面板生成唯一ID
const panelId = `panel_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
(panel as any).__uniqueId = panelId;
// 设置标签页图标
panel.iconPath = vscode.Uri.joinPath(
context.extensionUri,
@ -50,7 +54,27 @@ export function showICHelperPanel(
// 处理消息
panel.webview.onDidReceiveMessage(
(message) => {
async (message) => {
const historyManager = ChatHistoryManager.getInstance();
const panelId = (panel as any).__uniqueId;
// 在处理消息前,确保面板有任务上下文
// 如果没有,则创建新任务(仅在首次发送消息时)
if (!historyManager.getPanelTask(panelId)) {
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
if (workspacePath) {
try {
const taskMeta = await historyManager.createTask(workspacePath, "新对话");
historyManager.setPanelTask(panelId, taskMeta.taskId, workspacePath);
} catch (error) {
console.error("创建任务失败:", error);
}
}
}
// 切换到当前面板的任务上下文
historyManager.switchToPanelTask(panelId);
switch (message.command) {
case "sendMessage":
handleUserMessage(panel, message.text, context.extensionPath);
@ -124,6 +148,17 @@ export function showICHelperPanel(
undefined,
context.subscriptions
);
// 面板关闭时清理任务映射
panel.onDidDispose(
() => {
const historyManager = ChatHistoryManager.getInstance();
const panelId = (panel as any).__uniqueId;
historyManager.removePanelTask(panelId);
},
undefined,
context.subscriptions
);
}
/**
@ -386,6 +421,10 @@ async function selectConversation(
return;
}
// 更新面板的任务映射,确保后续对话保存到正确的任务中
const panelId = (panel as any).__uniqueId;
historyManager.setPanelTask(panelId, taskId, workspacePath);
// 清空当前聊天界面
panel.webview.postMessage({
command: "clearChat"

View File

@ -21,6 +21,8 @@ export class ChatHistoryManager {
private baseDir: string; // ~/.iccoder
private currentTaskId: string | null = null;
private currentProjectPath: string | null = null;
// 存储每个面板的任务信息taskId 和 projectPath
private panelTaskMap: Map<string, { taskId: string; projectPath: string }> = new Map();
private constructor() {
// 设置存储路径: ~/.iccoder
@ -109,6 +111,43 @@ export class ChatHistoryManager {
return ChatHistoryManager.instance;
}
/**
* 为面板设置任务ID
*/
public setPanelTask(panelId: string, taskId: string, projectPath: string): void {
this.panelTaskMap.set(panelId, { taskId, projectPath });
this.currentTaskId = taskId;
this.currentProjectPath = projectPath;
}
/**
* 获取面板的任务ID
*/
public getPanelTask(panelId: string): string | null {
const taskInfo = this.panelTaskMap.get(panelId);
return taskInfo ? taskInfo.taskId : null;
}
/**
* 切换到指定面板的任务上下文
*/
public switchToPanelTask(panelId: string): boolean {
const taskInfo = this.panelTaskMap.get(panelId);
if (taskInfo) {
this.currentTaskId = taskInfo.taskId;
this.currentProjectPath = taskInfo.projectPath;
return true;
}
return false;
}
/**
* 移除面板的任务映射
*/
public removePanelTask(panelId: string): void {
this.panelTaskMap.delete(panelId);
}
/**
* 创建新任务
*/
@ -266,17 +305,11 @@ export class ChatHistoryManager {
}
/**
* 确保有当前任务,如果没有则自动创建
* 确保有当前任务,如果没有则抛出错误
*/
private async ensureCurrentTask(): Promise<void> {
if (!this.currentTaskId || !this.currentProjectPath) {
// 获取当前工作区路径
const workspacePath = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath;
if (workspacePath) {
await this.createTask(workspacePath, "默认任务");
} else {
throw new Error("没有打开的工作区,无法创建任务");
}
throw new Error("没有当前任务上下文,请确保已正确初始化面板任务");
}
}