feat: 实现上下文使用量监控和会话压缩功能
- sseHandler: 新增 onContextUsage 回调处理上下文使用量事件 - dialogService: 集成上下文使用量回调,追踪 AI 消息用于后端重启恢复 - apiClient: 新增 compactDialog API 支持手动压缩对话历史 - messageHandler: 新增 lastTaskId 管理机制,支持会话恢复后的压缩操作,转发上下文使用量到 WebView
This commit is contained in:
@ -155,6 +155,26 @@ export async function stopDialog(taskId: string): Promise<StopDialogResponse> {
|
||||
});
|
||||
}
|
||||
|
||||
/** 压缩对话响应 */
|
||||
export interface CompactDialogResponse {
|
||||
success: boolean;
|
||||
taskId: string;
|
||||
message?: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动压缩对话历史
|
||||
* POST /api/dialog/compact
|
||||
*/
|
||||
export async function compactDialog(taskId: string): Promise<CompactDialogResponse> {
|
||||
console.log(`[API] 压缩对话: taskId=${taskId}`);
|
||||
return request<CompactDialogResponse>('/api/dialog/compact', {
|
||||
method: 'POST',
|
||||
body: { taskId }
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建成功的工具结果
|
||||
*/
|
||||
|
||||
@ -73,6 +73,8 @@ export interface DialogCallbacks {
|
||||
onError?: (message: string) => void;
|
||||
/** 通知消息 */
|
||||
onNotification?: (message: string) => void;
|
||||
/** 上下文使用量更新 */
|
||||
onContextUsage?: (data: { currentTokens: number; maxTokens: number; percentage: number }) => void;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -553,6 +555,12 @@ export class DialogSession {
|
||||
onComplete: (data) => {
|
||||
this.isActive = false;
|
||||
this.finalizeTextSegment();
|
||||
|
||||
// 追踪 AI 消息(用于后端重启后恢复)
|
||||
if (this.accumulatedText) {
|
||||
historyManager.trackAiMessage(this.accumulatedText);
|
||||
}
|
||||
|
||||
// 发送所有段落
|
||||
callbacks.onComplete?.(this.segments);
|
||||
},
|
||||
@ -639,6 +647,11 @@ export class DialogSession {
|
||||
await historyManager.saveCompactedData(data.compactedData);
|
||||
},
|
||||
|
||||
onContextUsage: (data) => {
|
||||
console.log('[DialogSession] onContextUsage:', data.currentTokens, '/', data.maxTokens);
|
||||
callbacks.onContextUsage?.(data);
|
||||
},
|
||||
|
||||
onOpen: () => {
|
||||
console.log('[DialogSession] SSE 连接已建立');
|
||||
},
|
||||
|
||||
@ -27,7 +27,8 @@ import type {
|
||||
AgentStartEvent,
|
||||
AgentProgressEvent,
|
||||
AgentCompleteEvent,
|
||||
AgentErrorEvent
|
||||
AgentErrorEvent,
|
||||
ContextUsageEvent
|
||||
} from '../types/api';
|
||||
import type { MemoryCompactedEvent } from '../types/memory';
|
||||
|
||||
@ -71,6 +72,8 @@ export interface SSECallbacks {
|
||||
onAgentError?: (data: AgentErrorEvent) => void;
|
||||
/** 记忆压缩完成 */
|
||||
onMemoryCompacted?: (data: MemoryCompactedEvent) => void;
|
||||
/** 上下文使用量更新 */
|
||||
onContextUsage?: (data: ContextUsageEvent) => void;
|
||||
/** 连接打开 */
|
||||
onOpen?: () => void;
|
||||
/** 连接关闭 */
|
||||
@ -325,6 +328,9 @@ function dispatchEvent(
|
||||
case 'memory_compacted':
|
||||
callbacks.onMemoryCompacted?.(data as MemoryCompactedEvent);
|
||||
break;
|
||||
case 'context_usage':
|
||||
callbacks.onContextUsage?.(data as ContextUsageEvent);
|
||||
break;
|
||||
default:
|
||||
console.log(`[SSE] 未知事件类型: ${eventType}`, data);
|
||||
}
|
||||
|
||||
@ -27,6 +27,9 @@ let useBackendService = true;
|
||||
/** 当前对话会话 */
|
||||
let currentSession: DialogSession | null = null;
|
||||
|
||||
/** 最后一个活跃的 taskId(用于压缩等操作) */
|
||||
let lastTaskId: string | null = null;
|
||||
|
||||
/** 待执行的计划(Plan 模式确认后自动执行) */
|
||||
let pendingPlanExecution: {
|
||||
panel: vscode.WebviewPanel;
|
||||
@ -128,6 +131,8 @@ async function handleUserMessageWithBackend(
|
||||
// 创建或复用会话
|
||||
if (!currentSession || !currentSession.active) {
|
||||
currentSession = dialogManager.createSession(extensionPath, reuseTaskId);
|
||||
// 保存 taskId 用于后续操作(如压缩)
|
||||
lastTaskId = currentSession.getTaskId();
|
||||
if (reuseTaskId) {
|
||||
console.log('[MessageHandler] 复用 taskId 创建会话:', reuseTaskId);
|
||||
}
|
||||
@ -253,6 +258,16 @@ async function handleUserMessageWithBackend(
|
||||
onNotification: (message) => {
|
||||
vscode.window.showInformationMessage(message);
|
||||
},
|
||||
|
||||
onContextUsage: (data) => {
|
||||
// 发送上下文使用量到 WebView
|
||||
panel.webview.postMessage({
|
||||
command: 'contextUsage',
|
||||
currentTokens: data.currentTokens,
|
||||
maxTokens: data.maxTokens,
|
||||
percentage: data.percentage
|
||||
});
|
||||
},
|
||||
}, mode);
|
||||
});
|
||||
}
|
||||
@ -310,7 +325,15 @@ export async function abortCurrentDialog(): Promise<void> {
|
||||
* 获取当前会话的 taskId
|
||||
*/
|
||||
export function getCurrentTaskId(): string | null {
|
||||
return currentSession?.getTaskId() || null;
|
||||
return currentSession?.getTaskId() || lastTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置最后的 taskId(加载历史会话时调用)
|
||||
*/
|
||||
export function setLastTaskId(taskId: string): void {
|
||||
lastTaskId = taskId;
|
||||
console.log('[MessageHandler] 设置 lastTaskId:', taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user