mirror of
https://github.com/andrepimenta/claude-code-chat.git
synced 2025-12-12 13:19:47 +00:00
plan first and thinking mode initial implementation
This commit is contained in:
@@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
132
src/ui.ts
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user