Fix close and open conversation

This commit is contained in:
andrepimenta
2025-07-28 22:09:22 +01:00
parent 2c47349282
commit 2d63eaac58
2 changed files with 59 additions and 13 deletions

View File

@@ -44,6 +44,21 @@ export function activate(context: vscode.ExtensionContext) {
export function deactivate() { } export function deactivate() { }
interface ConversationData {
sessionId: string;
startTime: string | undefined;
endTime: string;
messageCount: number;
totalCost: number;
totalTokens: {
input: number;
output: number;
};
messages: Array<{ timestamp: string, messageType: string, data: any }>;
filename: string;
isProcessing?: boolean;
}
class ClaudeChatWebviewProvider implements vscode.WebviewViewProvider { class ClaudeChatWebviewProvider implements vscode.WebviewViewProvider {
constructor( constructor(
private readonly _extensionUri: vscode.Uri, private readonly _extensionUri: vscode.Uri,
@@ -112,6 +127,7 @@ class ClaudeChatProvider {
}> = []; }> = [];
private _currentClaudeProcess: cp.ChildProcess | undefined; private _currentClaudeProcess: cp.ChildProcess | undefined;
private _selectedModel: string = 'default'; // Default model private _selectedModel: string = 'default'; // Default model
private _isProcessing: boolean | undefined;
constructor( constructor(
private readonly _extensionUri: vscode.Uri, private readonly _extensionUri: vscode.Uri,
@@ -196,18 +212,18 @@ class ClaudeChatProvider {
private _sendReadyMessage() { private _sendReadyMessage() {
// Send current session info if available // Send current session info if available
if (this._currentSessionId) { /*if (this._currentSessionId) {
this._postMessage({ this._postMessage({
type: 'sessionResumed', type: 'sessionResumed',
data: { data: {
sessionId: this._currentSessionId sessionId: this._currentSessionId
} }
}); });
} }*/
this._postMessage({ this._postMessage({
type: 'ready', type: 'ready',
data: 'Ready to chat with Claude Code! Type your message below.' data: this._isProcessing ? 'Claude is working...' : 'Ready to chat with Claude Code! Type your message below.'
}); });
// Send current model to webview // Send current model to webview
@@ -413,13 +429,15 @@ class ClaudeChatProvider {
actualMessage = thinkingPrompt + thinkingMesssage + actualMessage; actualMessage = thinkingPrompt + thinkingMesssage + actualMessage;
} }
this._isProcessing = true;
// Show original user input in chat and save to conversation (without mode prefixes) // Show original user input in chat and save to conversation (without mode prefixes)
this._sendAndSaveMessage({ this._sendAndSaveMessage({
type: 'userInput', type: 'userInput',
data: message data: message
}); });
// Set processing state // Set processing state to true
this._postMessage({ this._postMessage({
type: 'setProcessing', type: 'setProcessing',
data: true data: true
@@ -558,11 +576,14 @@ class ClaudeChatProvider {
// Clear process reference // Clear process reference
this._currentClaudeProcess = undefined; this._currentClaudeProcess = undefined;
// Clear loading indicator // Clear loading indicator and set processing to false
this._postMessage({ this._postMessage({
type: 'clearLoading' type: 'clearLoading'
}); });
// Reset processing state
this._isProcessing = false;
if (code !== 0 && errorOutput.trim()) { if (code !== 0 && errorOutput.trim()) {
// Error with output // Error with output
this._sendAndSaveMessage({ this._sendAndSaveMessage({
@@ -733,6 +754,8 @@ class ClaudeChatProvider {
return; return;
} }
this._isProcessing = false;
// Capture session ID from final result // Capture session ID from final result
if (jsonData.session_id) { if (jsonData.session_id) {
const isNewSession = !this._currentSessionId; const isNewSession = !this._currentSessionId;
@@ -837,6 +860,9 @@ class ClaudeChatProvider {
} }
private _handleLoginRequired() { private _handleLoginRequired() {
this._isProcessing = false;
// Clear processing state // Clear processing state
this._postMessage({ this._postMessage({
type: 'setProcessing', type: 'setProcessing',
@@ -1716,7 +1742,10 @@ class ClaudeChatProvider {
return path.join(configPath); return path.join(configPath);
} }
private _sendAndSaveMessage(message: { type: string, data: any }): void { private _sendAndSaveMessage(message: { type: string, data: any }, options?: { isProcessing?: boolean }): void {
console.log("--MESSAGE", message, options)
// Initialize conversation if this is the first message // Initialize conversation if this is the first message
if (this._currentConversation.length === 0) { if (this._currentConversation.length === 0) {
this._conversationStartTime = new Date().toISOString(); this._conversationStartTime = new Date().toISOString();
@@ -1744,6 +1773,8 @@ class ClaudeChatProvider {
if (!this._conversationsPath || this._currentConversation.length === 0) {return;} if (!this._conversationsPath || this._currentConversation.length === 0) {return;}
if(!this._currentSessionId) {return;} if(!this._currentSessionId) {return;}
console.log("IS PROCESSING", this._isProcessing)
try { try {
// Create filename from first user message and timestamp // Create filename from first user message and timestamp
const firstUserMessage = this._currentConversation.find(m => m.messageType === 'userInput'); const firstUserMessage = this._currentConversation.find(m => m.messageType === 'userInput');
@@ -1761,7 +1792,7 @@ class ClaudeChatProvider {
const datePrefix = startTime.substring(0, 16).replace('T', '_').replace(/:/g, '-'); const datePrefix = startTime.substring(0, 16).replace('T', '_').replace(/:/g, '-');
const filename = `${datePrefix}_${cleanMessage}.json`; const filename = `${datePrefix}_${cleanMessage}.json`;
const conversationData = { const conversationData : ConversationData = {
sessionId: sessionId, sessionId: sessionId,
startTime: this._conversationStartTime, startTime: this._conversationStartTime,
endTime: new Date().toISOString(), endTime: new Date().toISOString(),
@@ -1775,6 +1806,10 @@ class ClaudeChatProvider {
filename filename
}; };
if (this._isProcessing !== undefined){
conversationData.isProcessing = this._isProcessing || false
}
const filePath = path.join(this._conversationsPath, filename); const filePath = path.join(this._conversationsPath, filename);
const content = new TextEncoder().encode(JSON.stringify(conversationData, null, 2)); const content = new TextEncoder().encode(JSON.stringify(conversationData, null, 2));
await vscode.workspace.fs.writeFile(vscode.Uri.file(filePath), content); await vscode.workspace.fs.writeFile(vscode.Uri.file(filePath), content);
@@ -1898,7 +1933,6 @@ class ClaudeChatProvider {
// Clear process reference // Clear process reference
this._currentClaudeProcess = undefined; this._currentClaudeProcess = undefined;
// Update UI state // Update UI state
this._postMessage({ this._postMessage({
type: 'setProcessing', type: 'setProcessing',
@@ -1921,7 +1955,7 @@ class ClaudeChatProvider {
} }
} }
private _updateConversationIndex(filename: string, conversationData: any): void { private _updateConversationIndex(filename: string, conversationData: ConversationData): void {
// Extract first and last user messages // Extract first and last user messages
const userMessages = conversationData.messages.filter((m: any) => m.messageType === 'userInput'); const userMessages = conversationData.messages.filter((m: any) => m.messageType === 'userInput');
const firstUserMessage = userMessages.length > 0 ? userMessages[0].data : 'No user message'; const firstUserMessage = userMessages.length > 0 ? userMessages[0].data : 'No user message';
@@ -1931,7 +1965,7 @@ class ClaudeChatProvider {
const indexEntry = { const indexEntry = {
filename: filename, filename: filename,
sessionId: conversationData.sessionId, sessionId: conversationData.sessionId,
startTime: conversationData.startTime, startTime: conversationData.startTime || '',
endTime: conversationData.endTime, endTime: conversationData.endTime,
messageCount: conversationData.messageCount, messageCount: conversationData.messageCount,
totalCost: conversationData.totalCost, totalCost: conversationData.totalCost,
@@ -1966,7 +2000,7 @@ class ClaudeChatProvider {
const filePath = path.join(this._conversationsPath, filename); const filePath = path.join(this._conversationsPath, filename);
console.log("filePath", filePath); console.log("filePath", filePath);
let conversationData; let conversationData: ConversationData;
try { try {
const fileUri = vscode.Uri.file(filePath); const fileUri = vscode.Uri.file(filePath);
const content = await vscode.workspace.fs.readFile(fileUri); const content = await vscode.workspace.fs.readFile(fileUri);
@@ -1975,7 +2009,7 @@ class ClaudeChatProvider {
return; return;
} }
console.log("conversationData", conversationData); console.log("conversationData-----", conversationData);
// Load conversation into current state // Load conversation into current state
this._currentConversation = conversationData.messages || []; this._currentConversation = conversationData.messages || [];
this._conversationStartTime = conversationData.startTime; this._conversationStartTime = conversationData.startTime;
@@ -2010,6 +2044,14 @@ class ClaudeChatProvider {
} }
}); });
// Restore processing state if the conversation was saved while processing
if (conversationData.isProcessing) {
this._isProcessing = conversationData.isProcessing;
this._postMessage({
type: 'setProcessing',
data: conversationData.isProcessing
});
}
// Send ready message after conversation is loaded // Send ready message after conversation is loaded
this._sendReadyMessage(); this._sendReadyMessage();
}, 50); }, 50);

View File

@@ -1546,6 +1546,10 @@ const html = `<!DOCTYPE html>
messageInput.addEventListener('keydown', (e) => { messageInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter' && !e.shiftKey) { if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault(); e.preventDefault();
const sendBtn = document.getElementById('sendBtn');
if (sendBtn.disabled){
return;
}
sendMessage(); sendMessage();
} else if (e.key === '@' && !e.ctrlKey && !e.metaKey) { } else if (e.key === '@' && !e.ctrlKey && !e.metaKey) {
// Don't prevent default, let @ be typed first // Don't prevent default, let @ be typed first