fix: chat history persistence and webview state restoration
This commit is contained in:
+2
-3
@@ -119,7 +119,7 @@ export class AgentExecutor {
|
||||
}
|
||||
|
||||
public getHistory() {
|
||||
return this.chatHistory.filter(message => !message.internal);
|
||||
return this.chatHistory.filter(message => !message.internal || message.role === 'assistant');
|
||||
}
|
||||
|
||||
public setHistory(history: ChatMessage[]) {
|
||||
@@ -394,7 +394,7 @@ export class AgentExecutor {
|
||||
|
||||
// 5. Execute Actions
|
||||
const rationale = this.parseRationale(aiResponseText);
|
||||
const assistantMessage: ChatMessage = { role: 'assistant', content: aiResponseText, internal: true, rationale };
|
||||
const assistantMessage: ChatMessage = { role: 'assistant', content: aiResponseText, internal: false, rationale };
|
||||
this.chatHistory.push(assistantMessage);
|
||||
|
||||
this.statusBarManager.updateStatus(AgentStatus.Executing);
|
||||
@@ -443,7 +443,6 @@ export class AgentExecutor {
|
||||
return;
|
||||
}
|
||||
|
||||
assistantMessage.internal = false;
|
||||
this.emitHistoryChanged();
|
||||
this.statusBarManager.updateStatus(AgentStatus.Success);
|
||||
this.webview.postMessage({ type: 'streamChunk', value: aiResponseText });
|
||||
|
||||
+45
-10
@@ -200,7 +200,9 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
if (!this._view) return;
|
||||
|
||||
const blankChatActive = this._context.globalState.get<boolean>(SidebarChatProvider.blankChatStateKey, false);
|
||||
if (blankChatActive) {
|
||||
const currentHistory = this._agent.getHistory();
|
||||
|
||||
if (blankChatActive && currentHistory.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -212,7 +214,6 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
await this._context.globalState.update(SidebarChatProvider.activeSessionStateKey, null);
|
||||
}
|
||||
|
||||
const currentHistory = this._agent.getHistory();
|
||||
if (currentHistory.length > 0) {
|
||||
this._view.webview.postMessage({ type: 'restoreHistory', value: currentHistory });
|
||||
await this._persistLastVisibleChat(currentHistory);
|
||||
@@ -1893,6 +1894,29 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
const vscode = acquireVsCodeApi();
|
||||
const chat = document.getElementById('chat');
|
||||
const input = document.getElementById('input');
|
||||
|
||||
// [State Persistence - Tier 0] 즉시 복원 (Instant Restore from WebView State)
|
||||
const previousState = vscode.getState();
|
||||
if (previousState && previousState.history && previousState.history.length > 0) {
|
||||
console.log('[G1nation] Restoring from Webview State...');
|
||||
renderHistory(previousState.history);
|
||||
}
|
||||
|
||||
function saveWebviewState(history) {
|
||||
vscode.setState({ history });
|
||||
}
|
||||
|
||||
function renderHistory(history) {
|
||||
if (!history || history.length === 0) return;
|
||||
chat.innerHTML = '';
|
||||
history.forEach(m => {
|
||||
if (!m) return;
|
||||
// Only skip truly internal system messages, keep assistant thoughts
|
||||
if (m.role === 'system' && m.internal) return;
|
||||
addMsg(m.content, m.role === 'assistant' ? 'assistant' : 'user', m.rationale);
|
||||
});
|
||||
chat.scrollTop = chat.scrollHeight;
|
||||
}
|
||||
const sendBtn = document.getElementById('sendBtn');
|
||||
const stopBtn = document.getElementById('stopBtn');
|
||||
const cancelBtn = document.getElementById('cancelBtn');
|
||||
@@ -2112,6 +2136,10 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
switch(msg.type) {
|
||||
case 'addMessage':
|
||||
addMsg(msg.value, msg.role, msg.rationale);
|
||||
// Update state for non-streamed messages
|
||||
const s = vscode.getState() || { history: [] };
|
||||
s.history.push({ role: msg.role === 'assistant' ? 'assistant' : 'user', content: msg.value, rationale: msg.rationale });
|
||||
saveWebviewState(s.history);
|
||||
break;
|
||||
case 'streamStart':
|
||||
thinkingBar.classList.remove('active');
|
||||
@@ -2128,9 +2156,15 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
}
|
||||
break;
|
||||
case 'streamEnd':
|
||||
if (streamBody) streamBody.classList.remove('stream-active');
|
||||
if (streamBody) {
|
||||
streamBody.classList.remove('stream-active');
|
||||
// Update state after stream finishes
|
||||
const state = vscode.getState() || { history: [] };
|
||||
state.history.push({ role: 'assistant', content: streamBody._parent._raw });
|
||||
saveWebviewState(state.history);
|
||||
}
|
||||
streamBody = null;
|
||||
// \uc0dd\uc131 \uc644\ub8cc \uc2dc Stop \ubc84\ud2bc \uc228\uae30\uace0 Send \ubcf5\uad50
|
||||
// 생성 완료 시 Stop 버튼 숨기고 Send 복구
|
||||
setGenerating(false);
|
||||
resetStepper();
|
||||
Sound.success();
|
||||
@@ -2143,12 +2177,8 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
: (Array.isArray(historyPayload?.history) ? historyPayload.history : []);
|
||||
|
||||
if (history && history.length > 0) {
|
||||
chat.innerHTML = '';
|
||||
history.forEach(m => {
|
||||
if (!m || m.internal) return;
|
||||
addMsg(m.content, m.role === 'assistant' ? 'assistant' : 'user', m.rationale);
|
||||
});
|
||||
chat.scrollTop = chat.scrollHeight;
|
||||
renderHistory(history);
|
||||
saveWebviewState(history);
|
||||
}
|
||||
if (historyPayload?.negativePrompt !== undefined) {
|
||||
negativePrompt.value = historyPayload.negativePrompt;
|
||||
@@ -2358,6 +2388,11 @@ export class SidebarChatProvider implements vscode.WebviewViewProvider, BridgeIn
|
||||
setDraftActive(false);
|
||||
setGenerating(true);
|
||||
thinkingBar.classList.add('active');
|
||||
|
||||
// Save state after sending
|
||||
const currentState = vscode.getState() || { history: [] };
|
||||
currentState.history.push({ role: 'user', content: val });
|
||||
saveWebviewState(currentState.history);
|
||||
}
|
||||
|
||||
sendBtn.onclick = send;
|
||||
|
||||
Reference in New Issue
Block a user