plan first and thinking mode initial implementation

This commit is contained in:
andrepimenta
2025-06-20 15:52:38 +01:00
parent 49ea9cca66
commit a0286f017e
3 changed files with 156 additions and 54 deletions

View File

@@ -181,7 +181,7 @@ class ClaudeChatProvider {
message => { message => {
switch (message.type) { switch (message.type) {
case 'sendMessage': case 'sendMessage':
this._sendMessageToClaude(message.text); this._sendMessageToClaude(message.text, message.planMode, message.thinkingMode);
return; return;
case 'newSession': case 'newSession':
this._newSession(); this._newSession();
@@ -259,11 +259,20 @@ class ClaudeChatProvider {
}, 100); }, 100);
} }
private async _sendMessageToClaude(message: string) { 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();
// Show user input in chat and save to conversation // Prepend mode instructions if enabled
let actualMessage = message;
if (planMode && !message.toLowerCase().includes('plan first')) {
actualMessage = 'PLAN FIRST BEFORE MAKING ANY CHANGES, SHOW ME IN DETAIL WHAT YOU WILL CHANGE. DONT PROCEED BEFORE I ACCEPT IN A DIFFERENT MESSAGE: \n' + message;
}
if (thinkingMode && !actualMessage.toLowerCase().includes('think through')) {
actualMessage = 'THINK THROUGH THIS STEP BY STEP: \n' + actualMessage;
}
// 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
@@ -353,9 +362,9 @@ class ClaudeChatProvider {
// Store process reference for potential termination // Store process reference for potential termination
this._currentClaudeProcess = claudeProcess; this._currentClaudeProcess = claudeProcess;
// Send the message to Claude's stdin // Send the message to Claude's stdin (with mode prefixes if enabled)
if (claudeProcess.stdin) { if (claudeProcess.stdin) {
claudeProcess.stdin.write(message + '\n'); claudeProcess.stdin.write(actualMessage + '\n');
claudeProcess.stdin.end(); claudeProcess.stdin.end();
} }

View File

@@ -433,10 +433,67 @@ const styles = `
padding: 10px; padding: 10px;
border-top: 1px solid var(--vscode-panel-border); border-top: 1px solid var(--vscode-panel-border);
background-color: var(--vscode-panel-background); background-color: var(--vscode-panel-background);
display: flex;
flex-direction: column;
position: relative;
}
.input-modes {
display: flex;
gap: 16px;
align-items: center;
padding-bottom: 5px;
font-size: 9.5px;
}
.mode-toggle {
display: flex;
align-items: center;
gap: 6px;
color: var(--vscode-foreground);
opacity: 0.8;
transition: opacity 0.2s ease;
}
.mode-toggle:hover {
opacity: 1;
}
.mode-switch {
position: relative;
width: 28px;
height: 16px;
background-color: var(--vscode-panel-border);
border-radius: 8px;
cursor: pointer;
transition: background-color 0.2s ease;
}
.mode-switch.active {
background-color: var(--vscode-button-background);
}
.mode-switch::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 12px;
height: 12px;
background-color: var(--vscode-foreground);
border-radius: 50%;
transition: transform 0.2s ease;
}
.mode-switch.active::after {
transform: translateX(12px);
background-color: var(--vscode-button-foreground);
}
.textarea-container {
display: flex; display: flex;
gap: 10px; gap: 10px;
align-items: flex-end; align-items: flex-end;
position: relative;
} }
.textarea-wrapper { .textarea-wrapper {

132
src/ui.ts
View File

@@ -38,54 +38,66 @@ const html = `<!DOCTYPE html>
<div class="chat-container" id="chatContainer"> <div class="chat-container" id="chatContainer">
<div class="messages" id="messages"></div> <div class="messages" id="messages"></div>
<div class="input-container" id="inputContainer"> <div class="input-container" id="inputContainer">
<div class="textarea-wrapper"> <div class="input-modes">
<textarea class="input-field" id="messageInput" placeholder="Type your message to Claude Code..." rows="1"></textarea> <div class="mode-toggle">
<div class="input-controls"> <span>Plan First</span>
<div class="left-controls"> <div class="mode-switch" id="planModeSwitch" onclick="togglePlanMode()"></div>
<button class="model-selector" id="modelSelector" onclick="showModelSelector()" title="Select model"> </div>
<span id="selectedModel">Opus</span> <div class="mode-toggle">
<svg width="8" height="8" viewBox="0 0 8 8" fill="currentColor"> <span>Thinking Mode</span>
<path d="M1 2.5l3 3 3-3"></path> <div class="mode-switch" id="thinkingModeSwitch" onclick="toggleThinkingMode()"></div>
</div>
</div>
<div class="textarea-container">
<div class="textarea-wrapper">
<textarea class="input-field" id="messageInput" placeholder="Type your message to Claude Code..." rows="1"></textarea>
<div class="input-controls">
<div class="left-controls">
<button class="model-selector" id="modelSelector" onclick="showModelSelector()" title="Select model">
<span id="selectedModel">Opus</span>
<svg width="8" height="8" viewBox="0 0 8 8" fill="currentColor">
<path d="M1 2.5l3 3 3-3"></path>
</svg>
</button>
<button class="tools-btn" onclick="showToolsModal()" title="Configure tools">
Tools: All
<svg width="8" height="8" viewBox="0 0 8 8" fill="currentColor">
<path d="M1 2.5l3 3 3-3"></path>
</svg>
</button>
</div>
<div class="right-controls">
<button class="at-btn" onclick="showFilePicker()" title="Reference files">@</button>
<button class="image-btn" id="imageBtn" onclick="selectImage()" title="Attach images">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 16 16"
width="14"
height="16"
>
<g fill="currentColor">
<path d="M6.002 5.5a1.5 1.5 0 1 1-3 0a1.5 1.5 0 0 1 3 0"></path>
<path d="M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2zm13 1a.5.5 0 0 1 .5.5v6l-3.775-1.947a.5.5 0 0 0-.577.093l-3.71 3.71l-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12v.54L1 12.5v-9a.5.5 0 0 1 .5-.5z"></path>
</g>
</svg> </svg>
</button> </button>
<button class="tools-btn" onclick="showToolsModal()" title="Configure tools"> <button class="send-btn" id="sendBtn" onclick="sendMessage()">
Tools: All <div>
<svg width="8" height="8" viewBox="0 0 8 8" fill="currentColor"> <span>Send </span>
<path d="M1 2.5l3 3 3-3"></path> <svg
</svg> xmlns="http://www.w3.org/2000/svg"
</button> viewBox="0 0 24 24"
</div> width="11"
<div class="right-controls"> height="11"
<button class="at-btn" onclick="showFilePicker()" title="Reference files">@</button> >
<button class="image-btn" id="imageBtn" onclick="selectImage()" title="Attach images"> <path
<svg fill="currentColor"
xmlns="http://www.w3.org/2000/svg" d="M20 4v9a4 4 0 0 1-4 4H6.914l2.5 2.5L8 20.914L3.086 16L8 11.086L9.414 12.5l-2.5 2.5H16a2 2 0 0 0 2-2V4z"
viewBox="0 0 16 16" ></path>
width="14" </svg>
height="16" </div>
> </button>
<g fill="currentColor"> </div>
<path d="M6.002 5.5a1.5 1.5 0 1 1-3 0a1.5 1.5 0 0 1 3 0"></path>
<path d="M1.5 2A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2zm13 1a.5.5 0 0 1 .5.5v6l-3.775-1.947a.5.5 0 0 0-.577.093l-3.71 3.71l-2.66-1.772a.5.5 0 0 0-.63.062L1.002 12v.54L1 12.5v-9a.5.5 0 0 1 .5-.5z"></path>
</g>
</svg>
</button>
<button class="send-btn" id="sendBtn" onclick="sendMessage()">
<div>
<span>Send </span>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="11"
height="11"
>
<path
fill="currentColor"
d="M20 4v9a4 4 0 0 1-4 4H6.914l2.5 2.5L8 20.914L3.086 16L8 11.086L9.414 12.5l-2.5 2.5H16a2 2 0 0 0 2-2V4z"
></path>
</svg>
</div>
</button>
</div> </div>
</div> </div>
</div> </div>
@@ -299,6 +311,8 @@ const html = `<!DOCTYPE html>
let isProcessRunning = false; let isProcessRunning = false;
let filteredFiles = []; let filteredFiles = [];
let selectedFileIndex = -1; let selectedFileIndex = -1;
let planModeEnabled = false;
let thinkingModeEnabled = false;
function addMessage(content, type = 'claude') { function addMessage(content, type = 'claude') {
const messageDiv = document.createElement('div'); const messageDiv = document.createElement('div');
@@ -560,13 +574,35 @@ const html = `<!DOCTYPE html>
if (text) { if (text) {
vscode.postMessage({ vscode.postMessage({
type: 'sendMessage', type: 'sendMessage',
text: text text: text,
planMode: planModeEnabled,
thinkingMode: thinkingModeEnabled
}); });
messageInput.value = ''; messageInput.value = '';
} }
} }
function togglePlanMode() {
planModeEnabled = !planModeEnabled;
const switchElement = document.getElementById('planModeSwitch');
if (planModeEnabled) {
switchElement.classList.add('active');
} else {
switchElement.classList.remove('active');
}
}
function toggleThinkingMode() {
thinkingModeEnabled = !thinkingModeEnabled;
const switchElement = document.getElementById('thinkingModeSwitch');
if (thinkingModeEnabled) {
switchElement.classList.add('active');
} else {
switchElement.classList.remove('active');
}
}
let totalCost = 0; let totalCost = 0;
let totalTokensInput = 0; let totalTokensInput = 0;