mirror of
https://github.com/andrepimenta/claude-code-chat.git
synced 2025-12-08 21:29:43 +00:00
Enable sidebar view
This commit is contained in:
@@ -130,6 +130,7 @@
|
|||||||
"claude-code-chat": [
|
"claude-code-chat": [
|
||||||
{
|
{
|
||||||
"id": "claude-code-chat.chat",
|
"id": "claude-code-chat.chat",
|
||||||
|
"type": "webview",
|
||||||
"name": "Claude Code Chat",
|
"name": "Claude Code Chat",
|
||||||
"when": "true",
|
"when": "true",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
|
|||||||
403
src/extension.ts
403
src/extension.ts
@@ -19,12 +19,9 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
provider.loadConversation(filename);
|
provider.loadConversation(filename);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register tree data provider for the activity bar view
|
// Register webview view provider for sidebar chat (using shared provider instance)
|
||||||
const treeProvider = new ClaudeChatViewProvider(context.extensionUri, context);
|
const webviewProvider = new ClaudeChatWebviewProvider(context.extensionUri, context, provider);
|
||||||
vscode.window.registerTreeDataProvider('claude-code-chat.chat', treeProvider);
|
vscode.window.registerWebviewViewProvider('claude-code-chat.chat', webviewProvider);
|
||||||
|
|
||||||
// Make tree provider accessible to chat provider for refreshing
|
|
||||||
provider.setTreeProvider(treeProvider);
|
|
||||||
|
|
||||||
// Listen for configuration changes
|
// Listen for configuration changes
|
||||||
const configChangeDisposable = vscode.workspace.onDidChangeConfiguration(event => {
|
const configChangeDisposable = vscode.workspace.onDidChangeConfiguration(event => {
|
||||||
@@ -47,70 +44,47 @@ export function activate(context: vscode.ExtensionContext) {
|
|||||||
|
|
||||||
export function deactivate() { }
|
export function deactivate() { }
|
||||||
|
|
||||||
class ClaudeChatViewProvider implements vscode.TreeDataProvider<vscode.TreeItem> {
|
class ClaudeChatWebviewProvider implements vscode.WebviewViewProvider {
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<vscode.TreeItem | undefined | null | void> = new vscode.EventEmitter<vscode.TreeItem | undefined | null | void>();
|
|
||||||
readonly onDidChangeTreeData: vscode.Event<vscode.TreeItem | undefined | null | void> = this._onDidChangeTreeData.event;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private extensionUri: vscode.Uri,
|
private readonly _extensionUri: vscode.Uri,
|
||||||
private context: vscode.ExtensionContext
|
private readonly _context: vscode.ExtensionContext,
|
||||||
) { }
|
private readonly _chatProvider: ClaudeChatProvider
|
||||||
|
) {}
|
||||||
|
|
||||||
refresh(): void {
|
public resolveWebviewView(
|
||||||
this._onDidChangeTreeData.fire();
|
webviewView: vscode.WebviewView,
|
||||||
}
|
_context: vscode.WebviewViewResolveContext,
|
||||||
|
_token: vscode.CancellationToken,
|
||||||
|
) {
|
||||||
|
|
||||||
getTreeItem(element: vscode.TreeItem): vscode.TreeItem {
|
webviewView.webview.options = {
|
||||||
return element;
|
enableScripts: true,
|
||||||
}
|
localResourceRoots: [this._extensionUri]
|
||||||
|
|
||||||
getChildren(): vscode.TreeItem[] {
|
|
||||||
const items: vscode.TreeItem[] = [];
|
|
||||||
|
|
||||||
// Add "Open Claude Code Chat" item
|
|
||||||
const openChatItem = new vscode.TreeItem('Open Claude Code Chat', vscode.TreeItemCollapsibleState.None);
|
|
||||||
openChatItem.command = {
|
|
||||||
command: 'claude-code-chat.openChat',
|
|
||||||
title: 'Open Claude Code Chat'
|
|
||||||
};
|
};
|
||||||
openChatItem.iconPath = vscode.Uri.joinPath(this.extensionUri, 'icon.png');
|
|
||||||
openChatItem.tooltip = 'Open Claude Code Chat (Ctrl+Shift+C)';
|
|
||||||
items.push(openChatItem);
|
|
||||||
|
|
||||||
// Add conversation history items
|
// Use the shared chat provider instance for the sidebar
|
||||||
const conversationIndex = this.context.workspaceState.get('claude.conversationIndex', []) as any[];
|
this._chatProvider.showInWebview(webviewView.webview, webviewView);
|
||||||
|
|
||||||
if (conversationIndex.length > 0) {
|
// Handle visibility changes to reinitialize when sidebar reopens
|
||||||
// Add separator
|
webviewView.onDidChangeVisibility(() => {
|
||||||
const separatorItem = new vscode.TreeItem('Recent Conversations', vscode.TreeItemCollapsibleState.None);
|
if (webviewView.visible) {
|
||||||
separatorItem.description = '';
|
// Close main panel when sidebar becomes visible
|
||||||
separatorItem.tooltip = 'Click on any conversation to load it';
|
if (this._chatProvider._panel) {
|
||||||
items.push(separatorItem);
|
console.log('Closing main panel because sidebar became visible');
|
||||||
|
this._chatProvider._panel.dispose();
|
||||||
// Add conversation items (show only last 5 for cleaner UI)
|
this._chatProvider._panel = undefined;
|
||||||
conversationIndex.slice(0, 20).forEach((conv, index) => {
|
}
|
||||||
const item = new vscode.TreeItem(
|
this._chatProvider.reinitializeWebview();
|
||||||
conv.firstUserMessage.substring(0, 50) + (conv.firstUserMessage.length > 50 ? '...' : ''),
|
}
|
||||||
vscode.TreeItemCollapsibleState.None
|
});
|
||||||
);
|
|
||||||
item.description = new Date(conv.startTime).toLocaleDateString();
|
|
||||||
item.tooltip = `First: ${conv.firstUserMessage}\nLast: ${conv.lastUserMessage}\nMessages: ${conv.messageCount}, Cost: $${conv.totalCost.toFixed(3)}`;
|
|
||||||
item.command = {
|
|
||||||
command: 'claude-code-chat.loadConversation',
|
|
||||||
title: 'Load Conversation',
|
|
||||||
arguments: [conv.filename]
|
|
||||||
};
|
|
||||||
item.iconPath = new vscode.ThemeIcon('comment-discussion');
|
|
||||||
items.push(item);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ClaudeChatProvider {
|
class ClaudeChatProvider {
|
||||||
private _panel: vscode.WebviewPanel | undefined;
|
public _panel: vscode.WebviewPanel | undefined;
|
||||||
|
private _webview: vscode.Webview | undefined;
|
||||||
|
private _webviewView: vscode.WebviewView | undefined;
|
||||||
private _disposables: vscode.Disposable[] = [];
|
private _disposables: vscode.Disposable[] = [];
|
||||||
private _totalCost: number = 0;
|
private _totalCost: number = 0;
|
||||||
private _totalTokensInput: number = 0;
|
private _totalTokensInput: number = 0;
|
||||||
@@ -132,7 +106,6 @@ class ClaudeChatProvider {
|
|||||||
firstUserMessage: string,
|
firstUserMessage: string,
|
||||||
lastUserMessage: string
|
lastUserMessage: string
|
||||||
}> = [];
|
}> = [];
|
||||||
private _treeProvider: ClaudeChatViewProvider | undefined;
|
|
||||||
private _currentClaudeProcess: cp.ChildProcess | undefined;
|
private _currentClaudeProcess: cp.ChildProcess | undefined;
|
||||||
private _selectedModel: string = 'default'; // Default model
|
private _selectedModel: string = 'default'; // Default model
|
||||||
|
|
||||||
@@ -159,6 +132,9 @@ class ClaudeChatProvider {
|
|||||||
public show() {
|
public show() {
|
||||||
const column = vscode.ViewColumn.Two;
|
const column = vscode.ViewColumn.Two;
|
||||||
|
|
||||||
|
// Close sidebar if it's open
|
||||||
|
this._closeSidebar();
|
||||||
|
|
||||||
if (this._panel) {
|
if (this._panel) {
|
||||||
this._panel.reveal(column);
|
this._panel.reveal(column);
|
||||||
return;
|
return;
|
||||||
@@ -183,65 +159,7 @@ class ClaudeChatProvider {
|
|||||||
|
|
||||||
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
|
this._panel.onDidDispose(() => this.dispose(), null, this._disposables);
|
||||||
|
|
||||||
this._panel.webview.onDidReceiveMessage(
|
this._setupWebviewMessageHandler(this._panel.webview);
|
||||||
message => {
|
|
||||||
switch (message.type) {
|
|
||||||
case 'sendMessage':
|
|
||||||
this._sendMessageToClaude(message.text, message.planMode, message.thinkingMode);
|
|
||||||
return;
|
|
||||||
case 'newSession':
|
|
||||||
this._newSession();
|
|
||||||
return;
|
|
||||||
case 'restoreCommit':
|
|
||||||
this._restoreToCommit(message.commitSha);
|
|
||||||
return;
|
|
||||||
case 'getConversationList':
|
|
||||||
this._sendConversationList();
|
|
||||||
return;
|
|
||||||
case 'getWorkspaceFiles':
|
|
||||||
this._sendWorkspaceFiles(message.searchTerm);
|
|
||||||
return;
|
|
||||||
case 'selectImageFile':
|
|
||||||
this._selectImageFile();
|
|
||||||
return;
|
|
||||||
case 'loadConversation':
|
|
||||||
this.loadConversation(message.filename);
|
|
||||||
return;
|
|
||||||
case 'stopRequest':
|
|
||||||
this._stopClaudeProcess();
|
|
||||||
return;
|
|
||||||
case 'getSettings':
|
|
||||||
this._sendCurrentSettings();
|
|
||||||
return;
|
|
||||||
case 'updateSettings':
|
|
||||||
this._updateSettings(message.settings);
|
|
||||||
return;
|
|
||||||
case 'getClipboardText':
|
|
||||||
this._getClipboardText();
|
|
||||||
return;
|
|
||||||
case 'selectModel':
|
|
||||||
this._setSelectedModel(message.model);
|
|
||||||
return;
|
|
||||||
case 'openModelTerminal':
|
|
||||||
this._openModelTerminal();
|
|
||||||
return;
|
|
||||||
case 'executeSlashCommand':
|
|
||||||
this._executeSlashCommand(message.command);
|
|
||||||
return;
|
|
||||||
case 'dismissWSLAlert':
|
|
||||||
this._dismissWSLAlert();
|
|
||||||
return;
|
|
||||||
case 'openFile':
|
|
||||||
this._openFileInEditor(message.filePath);
|
|
||||||
return;
|
|
||||||
case 'createImageFile':
|
|
||||||
this._createImageFile(message.imageData, message.imageType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
null,
|
|
||||||
this._disposables
|
|
||||||
);
|
|
||||||
|
|
||||||
// Resume session from latest conversation
|
// Resume session from latest conversation
|
||||||
const latestConversation = this._getLatestConversation();
|
const latestConversation = this._getLatestConversation();
|
||||||
@@ -254,33 +172,160 @@ class ClaudeChatProvider {
|
|||||||
|
|
||||||
// Send ready message immediately
|
// Send ready message immediately
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Send current session info if available
|
// If no conversation to load, send ready immediately
|
||||||
if (this._currentSessionId) {
|
if (!latestConversation) {
|
||||||
this._panel?.webview.postMessage({
|
this._sendReadyMessage();
|
||||||
type: 'sessionResumed',
|
|
||||||
data: {
|
|
||||||
sessionId: this._currentSessionId
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
|
||||||
type: 'ready',
|
|
||||||
data: 'Ready to chat with Claude Code! Type your message below.'
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send current model to webview
|
|
||||||
this._panel?.webview.postMessage({
|
|
||||||
type: 'modelSelected',
|
|
||||||
model: this._selectedModel
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// Send platform information to webview
|
|
||||||
this._sendPlatformInfo();
|
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _postMessage(message: any) {
|
||||||
|
if (this._panel && this._panel.webview) {
|
||||||
|
this._panel.webview.postMessage(message);
|
||||||
|
} else if (this._webview) {
|
||||||
|
this._webview.postMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _sendReadyMessage() {
|
||||||
|
// Send current session info if available
|
||||||
|
if (this._currentSessionId) {
|
||||||
|
this._postMessage({
|
||||||
|
type: 'sessionResumed',
|
||||||
|
data: {
|
||||||
|
sessionId: this._currentSessionId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this._postMessage({
|
||||||
|
type: 'ready',
|
||||||
|
data: 'Ready to chat with Claude Code! Type your message below.'
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send current model to webview
|
||||||
|
this._postMessage({
|
||||||
|
type: 'modelSelected',
|
||||||
|
model: this._selectedModel
|
||||||
|
});
|
||||||
|
|
||||||
|
// Send platform information to webview
|
||||||
|
this._sendPlatformInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _handleWebviewMessage(message: any) {
|
||||||
|
switch (message.type) {
|
||||||
|
case 'sendMessage':
|
||||||
|
this._sendMessageToClaude(message.text, message.planMode, message.thinkingMode);
|
||||||
|
return;
|
||||||
|
case 'newSession':
|
||||||
|
this._newSession();
|
||||||
|
return;
|
||||||
|
case 'restoreCommit':
|
||||||
|
this._restoreToCommit(message.commitSha);
|
||||||
|
return;
|
||||||
|
case 'getConversationList':
|
||||||
|
this._sendConversationList();
|
||||||
|
return;
|
||||||
|
case 'getWorkspaceFiles':
|
||||||
|
this._sendWorkspaceFiles(message.searchTerm);
|
||||||
|
return;
|
||||||
|
case 'selectImageFile':
|
||||||
|
this._selectImageFile();
|
||||||
|
return;
|
||||||
|
case 'loadConversation':
|
||||||
|
this.loadConversation(message.filename);
|
||||||
|
return;
|
||||||
|
case 'stopRequest':
|
||||||
|
this._stopClaudeProcess();
|
||||||
|
return;
|
||||||
|
case 'getSettings':
|
||||||
|
this._sendCurrentSettings();
|
||||||
|
return;
|
||||||
|
case 'updateSettings':
|
||||||
|
this._updateSettings(message.settings);
|
||||||
|
return;
|
||||||
|
case 'getClipboardText':
|
||||||
|
this._getClipboardText();
|
||||||
|
return;
|
||||||
|
case 'selectModel':
|
||||||
|
this._setSelectedModel(message.model);
|
||||||
|
return;
|
||||||
|
case 'openModelTerminal':
|
||||||
|
this._openModelTerminal();
|
||||||
|
return;
|
||||||
|
case 'executeSlashCommand':
|
||||||
|
this._executeSlashCommand(message.command);
|
||||||
|
return;
|
||||||
|
case 'dismissWSLAlert':
|
||||||
|
this._dismissWSLAlert();
|
||||||
|
return;
|
||||||
|
case 'openFile':
|
||||||
|
this._openFileInEditor(message.filePath);
|
||||||
|
return;
|
||||||
|
case 'createImageFile':
|
||||||
|
this._createImageFile(message.imageData, message.imageType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private _setupWebviewMessageHandler(webview: vscode.Webview) {
|
||||||
|
webview.onDidReceiveMessage(
|
||||||
|
message => this._handleWebviewMessage(message),
|
||||||
|
null,
|
||||||
|
this._disposables
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _closeSidebar() {
|
||||||
|
if (this._webviewView) {
|
||||||
|
// Switch VS Code to show Explorer view instead of chat sidebar
|
||||||
|
vscode.commands.executeCommand('workbench.view.explorer');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public showInWebview(webview: vscode.Webview, webviewView?: vscode.WebviewView) {
|
||||||
|
// Close main panel if it's open
|
||||||
|
if (this._panel) {
|
||||||
|
console.log('Closing main panel because sidebar is opening');
|
||||||
|
this._panel.dispose();
|
||||||
|
this._panel = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._webview = webview;
|
||||||
|
this._webviewView = webviewView;
|
||||||
|
this._webview.html = this._getHtmlForWebview();
|
||||||
|
|
||||||
|
this._setupWebviewMessageHandler(this._webview);
|
||||||
|
|
||||||
|
// Initialize the webview
|
||||||
|
this._initializeWebview();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _initializeWebview() {
|
||||||
|
// Resume session from latest conversation
|
||||||
|
const latestConversation = this._getLatestConversation();
|
||||||
|
this._currentSessionId = latestConversation?.sessionId;
|
||||||
|
|
||||||
|
// Load latest conversation history if available
|
||||||
|
if (latestConversation) {
|
||||||
|
this._loadConversationHistory(latestConversation.filename);
|
||||||
|
} else {
|
||||||
|
// If no conversation to load, send ready immediately
|
||||||
|
setTimeout(() => {
|
||||||
|
this._sendReadyMessage();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public reinitializeWebview() {
|
||||||
|
// Only reinitialize if we have a webview (sidebar)
|
||||||
|
if (this._webview) {
|
||||||
|
this._initializeWebview();
|
||||||
|
this._setupWebviewMessageHandler(this._webview);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async _sendMessageToClaude(message: string, planMode?: boolean, thinkingMode?: boolean) {
|
private async _sendMessageToClaude(message: string, planMode?: boolean, thinkingMode?: boolean) {
|
||||||
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
const workspaceFolder = vscode.workspace.workspaceFolders?.[0];
|
||||||
const cwd = workspaceFolder ? workspaceFolder.uri.fsPath : process.cwd();
|
const cwd = workspaceFolder ? workspaceFolder.uri.fsPath : process.cwd();
|
||||||
@@ -323,7 +368,7 @@ class ClaudeChatProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Set processing state
|
// Set processing state
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'setProcessing',
|
type: 'setProcessing',
|
||||||
data: true
|
data: true
|
||||||
});
|
});
|
||||||
@@ -337,7 +382,7 @@ class ClaudeChatProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'loading',
|
type: 'loading',
|
||||||
data: 'Claude is working...'
|
data: 'Claude is working...'
|
||||||
});
|
});
|
||||||
@@ -450,7 +495,7 @@ class ClaudeChatProvider {
|
|||||||
this._currentClaudeProcess = undefined;
|
this._currentClaudeProcess = undefined;
|
||||||
|
|
||||||
// Clear loading indicator
|
// Clear loading indicator
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'clearLoading'
|
type: 'clearLoading'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -469,7 +514,7 @@ class ClaudeChatProvider {
|
|||||||
// Clear process reference
|
// Clear process reference
|
||||||
this._currentClaudeProcess = undefined;
|
this._currentClaudeProcess = undefined;
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'clearLoading'
|
type: 'clearLoading'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -646,7 +691,7 @@ class ClaudeChatProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clear processing state
|
// Clear processing state
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'setProcessing',
|
type: 'setProcessing',
|
||||||
data: false
|
data: false
|
||||||
});
|
});
|
||||||
@@ -664,7 +709,7 @@ class ClaudeChatProvider {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Send updated totals to webview
|
// Send updated totals to webview
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'updateTotals',
|
type: 'updateTotals',
|
||||||
data: {
|
data: {
|
||||||
totalCost: this._totalCost,
|
totalCost: this._totalCost,
|
||||||
@@ -698,7 +743,7 @@ class ClaudeChatProvider {
|
|||||||
this._requestCount = 0;
|
this._requestCount = 0;
|
||||||
|
|
||||||
// Notify webview to clear all messages and reset session
|
// Notify webview to clear all messages and reset session
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'sessionCleared'
|
type: 'sessionCleared'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -722,13 +767,13 @@ class ClaudeChatProvider {
|
|||||||
|
|
||||||
private _handleLoginRequired() {
|
private _handleLoginRequired() {
|
||||||
// Clear processing state
|
// Clear processing state
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'setProcessing',
|
type: 'setProcessing',
|
||||||
data: false
|
data: false
|
||||||
});
|
});
|
||||||
|
|
||||||
// Show login required message
|
// Show login required message
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'loginRequired'
|
type: 'loginRequired'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -755,7 +800,7 @@ class ClaudeChatProvider {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Send message to UI about terminal
|
// Send message to UI about terminal
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'terminalOpened',
|
type: 'terminalOpened',
|
||||||
data: `Please login to Claude in the terminal, then come back to this chat to continue.`,
|
data: `Please login to Claude in the terminal, then come back to this chat to continue.`,
|
||||||
});
|
});
|
||||||
@@ -860,7 +905,7 @@ class ClaudeChatProvider {
|
|||||||
try {
|
try {
|
||||||
const commit = this._commits.find(c => c.sha === commitSha);
|
const commit = this._commits.find(c => c.sha === commitSha);
|
||||||
if (!commit) {
|
if (!commit) {
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'restoreError',
|
type: 'restoreError',
|
||||||
data: 'Commit not found'
|
data: 'Commit not found'
|
||||||
});
|
});
|
||||||
@@ -875,7 +920,7 @@ class ClaudeChatProvider {
|
|||||||
|
|
||||||
const workspacePath = workspaceFolder.uri.fsPath;
|
const workspacePath = workspaceFolder.uri.fsPath;
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'restoreProgress',
|
type: 'restoreProgress',
|
||||||
data: 'Restoring files from backup...'
|
data: 'Restoring files from backup...'
|
||||||
});
|
});
|
||||||
@@ -896,7 +941,7 @@ class ClaudeChatProvider {
|
|||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error('Failed to restore commit:', error.message);
|
console.error('Failed to restore commit:', error.message);
|
||||||
vscode.window.showErrorMessage(`Failed to restore commit: ${error.message}`);
|
vscode.window.showErrorMessage(`Failed to restore commit: ${error.message}`);
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'restoreError',
|
type: 'restoreError',
|
||||||
data: `Failed to restore: ${error.message}`
|
data: `Failed to restore: ${error.message}`
|
||||||
});
|
});
|
||||||
@@ -935,8 +980,8 @@ class ClaudeChatProvider {
|
|||||||
message.data.sessionId;
|
message.data.sessionId;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send to UI
|
// Send to UI using the helper method
|
||||||
this._panel?.webview.postMessage(message);
|
this._postMessage(message);
|
||||||
|
|
||||||
// Save to conversation
|
// Save to conversation
|
||||||
this._currentConversation.push({
|
this._currentConversation.push({
|
||||||
@@ -997,20 +1042,14 @@ class ClaudeChatProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public setTreeProvider(treeProvider: ClaudeChatViewProvider): void {
|
|
||||||
this._treeProvider = treeProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async loadConversation(filename: string): Promise<void> {
|
public async loadConversation(filename: string): Promise<void> {
|
||||||
// Show the webview first
|
|
||||||
this.show();
|
|
||||||
|
|
||||||
// Load the conversation history
|
// Load the conversation history
|
||||||
await this._loadConversationHistory(filename);
|
await this._loadConversationHistory(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _sendConversationList(): void {
|
private _sendConversationList(): void {
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'conversationList',
|
type: 'conversationList',
|
||||||
data: this._conversationIndex
|
data: this._conversationIndex
|
||||||
});
|
});
|
||||||
@@ -1053,13 +1092,13 @@ class ClaudeChatProvider {
|
|||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
.sort((a, b) => a.name.localeCompare(b.name))
|
||||||
.slice(0, 50);
|
.slice(0, 50);
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'workspaceFiles',
|
type: 'workspaceFiles',
|
||||||
data: fileList
|
data: fileList
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error getting workspace files:', error);
|
console.error('Error getting workspace files:', error);
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'workspaceFiles',
|
type: 'workspaceFiles',
|
||||||
data: []
|
data: []
|
||||||
});
|
});
|
||||||
@@ -1082,7 +1121,7 @@ class ClaudeChatProvider {
|
|||||||
if (result && result.length > 0) {
|
if (result && result.length > 0) {
|
||||||
// Send the selected file paths back to webview
|
// Send the selected file paths back to webview
|
||||||
result.forEach(uri => {
|
result.forEach(uri => {
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'imagePath',
|
type: 'imagePath',
|
||||||
path: uri.fsPath
|
path: uri.fsPath
|
||||||
});
|
});
|
||||||
@@ -1115,12 +1154,12 @@ class ClaudeChatProvider {
|
|||||||
this._currentClaudeProcess = undefined;
|
this._currentClaudeProcess = undefined;
|
||||||
|
|
||||||
// Update UI state
|
// Update UI state
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'setProcessing',
|
type: 'setProcessing',
|
||||||
data: false
|
data: false
|
||||||
});
|
});
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'clearLoading'
|
type: 'clearLoading'
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1167,9 +1206,6 @@ class ClaudeChatProvider {
|
|||||||
|
|
||||||
// Save to workspace state
|
// Save to workspace state
|
||||||
this._context.workspaceState.update('claude.conversationIndex', this._conversationIndex);
|
this._context.workspaceState.update('claude.conversationIndex', this._conversationIndex);
|
||||||
|
|
||||||
// Refresh tree view
|
|
||||||
this._treeProvider?.refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private _getLatestConversation(): any | undefined {
|
private _getLatestConversation(): any | undefined {
|
||||||
@@ -1204,21 +1240,21 @@ class ClaudeChatProvider {
|
|||||||
// Clear UI messages first, then send all messages to recreate the conversation
|
// Clear UI messages first, then send all messages to recreate the conversation
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Clear existing messages
|
// Clear existing messages
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'sessionCleared'
|
type: 'sessionCleared'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Small delay to ensure messages are cleared before loading new ones
|
// Small delay to ensure messages are cleared before loading new ones
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
for (const message of this._currentConversation) {
|
for (const message of this._currentConversation) {
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: message.messageType,
|
type: message.messageType,
|
||||||
data: message.data
|
data: message.data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send updated totals
|
// Send updated totals
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'updateTotals',
|
type: 'updateTotals',
|
||||||
data: {
|
data: {
|
||||||
totalCost: this._totalCost,
|
totalCost: this._totalCost,
|
||||||
@@ -1227,6 +1263,9 @@ class ClaudeChatProvider {
|
|||||||
requestCount: this._requestCount
|
requestCount: this._requestCount
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Send ready message after conversation is loaded
|
||||||
|
this._sendReadyMessage();
|
||||||
}, 50);
|
}, 50);
|
||||||
}, 100); // Small delay to ensure webview is ready
|
}, 100); // Small delay to ensure webview is ready
|
||||||
|
|
||||||
@@ -1250,7 +1289,7 @@ class ClaudeChatProvider {
|
|||||||
'wsl.claudePath': config.get<string>('wsl.claudePath', '/usr/local/bin/claude')
|
'wsl.claudePath': config.get<string>('wsl.claudePath', '/usr/local/bin/claude')
|
||||||
};
|
};
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'settingsData',
|
type: 'settingsData',
|
||||||
data: settings
|
data: settings
|
||||||
});
|
});
|
||||||
@@ -1274,7 +1313,7 @@ class ClaudeChatProvider {
|
|||||||
private async _getClipboardText(): Promise<void> {
|
private async _getClipboardText(): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const text = await vscode.env.clipboard.readText();
|
const text = await vscode.env.clipboard.readText();
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'clipboardText',
|
type: 'clipboardText',
|
||||||
data: text
|
data: text
|
||||||
});
|
});
|
||||||
@@ -1332,7 +1371,7 @@ class ClaudeChatProvider {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Send message to UI about terminal
|
// Send message to UI about terminal
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'terminalOpened',
|
type: 'terminalOpened',
|
||||||
data: 'Check the terminal to update your default model configuration. Come back to this chat here after making changes.'
|
data: 'Check the terminal to update your default model configuration. Come back to this chat here after making changes.'
|
||||||
});
|
});
|
||||||
@@ -1369,7 +1408,7 @@ class ClaudeChatProvider {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Send message to UI about terminal
|
// Send message to UI about terminal
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'terminalOpened',
|
type: 'terminalOpened',
|
||||||
data: `Executing /${command} command in terminal. Check the terminal output and return when ready.`,
|
data: `Executing /${command} command in terminal. Check the terminal output and return when ready.`,
|
||||||
});
|
});
|
||||||
@@ -1383,7 +1422,7 @@ class ClaudeChatProvider {
|
|||||||
const config = vscode.workspace.getConfiguration('claudeCodeChat');
|
const config = vscode.workspace.getConfiguration('claudeCodeChat');
|
||||||
const wslEnabled = config.get<boolean>('wsl.enabled', false);
|
const wslEnabled = config.get<boolean>('wsl.enabled', false);
|
||||||
|
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'platformInfo',
|
type: 'platformInfo',
|
||||||
data: {
|
data: {
|
||||||
platform: platform,
|
platform: platform,
|
||||||
@@ -1434,7 +1473,7 @@ class ClaudeChatProvider {
|
|||||||
await vscode.workspace.fs.writeFile(imagePath, buffer);
|
await vscode.workspace.fs.writeFile(imagePath, buffer);
|
||||||
|
|
||||||
// Send the file path back to webview
|
// Send the file path back to webview
|
||||||
this._panel?.webview.postMessage({
|
this._postMessage({
|
||||||
type: 'imagePath',
|
type: 'imagePath',
|
||||||
data: {
|
data: {
|
||||||
filePath: imagePath.fsPath
|
filePath: imagePath.fsPath
|
||||||
|
|||||||
Reference in New Issue
Block a user