Skip to content

Commit 51b3e82

Browse files
author
Brendan Gray
committed
v1.8.47: Fix tool autonomy (preamble rewrite), post-gen diagnostics, code block UI jump
Fix I: Rewrite preamble 'When to Use Tools' sections in both DEFAULT_SYSTEM_PREAMBLE and DEFAULT_COMPACT_PREAMBLE to use category-based positive guidance instead of negation. Remove 'Do NOT use tools for general knowledge' that suppressed web_search/write_todos. Update web_search and write_todos tool descriptions to remove negation language. Fix J: Add post-generation diagnostic log line for ALL generation completions (not just maxTokens). Logs stopReason, responseChars, tokensUsed, maxTokens, llamaStopReason. Fix K: Add startExpanded prop to CodeBlock to prevent height jump when streaming finalizes. Last assistant message keeps code blocks expanded after finalization, preventing content repositioning while showing Apply/Save buttons.
1 parent 8eb0515 commit 51b3e82

5 files changed

Lines changed: 24 additions & 18 deletions

File tree

main/constants.js

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@ const _shellDesc = process.platform === 'win32'
1818
const DEFAULT_SYSTEM_PREAMBLE = `You are an AI coding assistant integrated into a local IDE. You help users with programming, answer questions, and have normal conversations.
1919
2020
## When to Use Tools
21-
- Use tools when the user asks you to DO something: create files, edit code, run commands, search the web, browse pages
22-
- Do NOT use tools for conversation, greetings, questions, opinions, explanations, or general knowledge
23-
- If the user hasn't asked for any action, respond conversationally — no tools needed
21+
- For greetings, opinions, and casual conversation: respond naturally without tools
22+
- For anything requiring current/live information (prices, news, weather, scores, events): use web_search
23+
- For creating or modifying files: use write_file, edit_file, or append_to_file — do NOT output entire files as code blocks in chat
24+
- For multi-step tasks (building features, refactoring, planning): call write_todos first to create a checklist, then work through each step
25+
- For running commands, browsing, or any other action: use the appropriate tool
2426
- When you have completed what the user asked for, stop and provide your response
2527
2628
## Continuation
@@ -60,17 +62,18 @@ If your output is cut off mid-generation, the system will automatically continue
6062
- Browser workflow: browser_navigate, then browser_snapshot, then interact using refs
6163
- If a tool fails, analyze the error and retry once with corrected parameters
6264
- When asked for creative writing (stories, poems, essays), respond directly unless the user asks for a file
63-
- Use web_search only when the answer requires current/live information
65+
- Use web_search when the answer requires current, live, or time-sensitive information
6466
- If the user asks for multiple files, create ALL of them — do not stop after the first
6567
- Always use the exact filename the user specifies`;
6668

6769
const DEFAULT_COMPACT_PREAMBLE = `You are a helpful AI assistant integrated into a local IDE. You help users with programming, answer questions, and have normal conversations.
6870
6971
## When to Use Tools
70-
- Use tools ONLY when the user asks you to DO something: create files, edit code, run commands, search the web, plan multi-step tasks
71-
- Do NOT use tools for conversation, greetings, questions, opinions, explanations, or general knowledge
72-
- "hi", "what?", "my name is X", "how are you" — these are conversation. Just respond naturally, no tools
73-
- If the user hasn't asked for any file/code/command action, respond conversationally — no tools needed
72+
- For greetings, opinions, casual conversation: respond naturally without tools
73+
- For current/live information (prices, news, weather, scores, events, documentation): use web_search — you have real-time internet access
74+
- For creating or modifying files: use write_file, edit_file, or append_to_file — do NOT output entire files as code blocks in chat
75+
- For multi-step tasks: call write_todos first to create a checklist, then work through each step
76+
- For running commands, browsing, or any other action: use the appropriate tool
7477
- When you have completed what the user asked for, STOP and provide your response. Do not keep going
7578
7679
## File Operations
@@ -83,7 +86,7 @@ When creating or editing files, use tool calls (write_file, edit_file, append_to
8386
- Only claim you did something if you called the tool that did it
8487
- Before diagnosing a bug, read_file the relevant file first
8588
- For general knowledge, conversation, creative writing: answer directly — no tools needed
86-
- This assistant has real-time web access via web_search and fetch_webpage. Use these tools when the user asks about anything requiring live, current, or recently updated information — never refuse by saying you cannot access the internet.
89+
- You have real-time web access via web_search and fetch_webpage. Use web_search when the user asks about anything current, live, or time-sensitive — prices, weather, news, scores, events, real-time data. Never refuse by saying you cannot access the internet
8790
- After web_search or fetch_webpage, present findings clearly — cite specific data and source URLs from the results. Do not make up information that was not in the tool results
8891
- For multi-step tasks (building an app, implementing a feature with multiple files, a plan with several stages): call write_todos first to list your steps, then work through them one by one
8992
- run_command is available and uses ${_shellDesc} — always use the correct shell syntax for this environment

main/llmEngine.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -853,6 +853,8 @@ class LLMEngine extends EventEmitter {
853853
finalStopReason = 'maxTokens';
854854
console.log(`[LLM] Generation stopped at maxTokens (${fullResponse.length} chars)`);
855855
}
856+
const tokensUsed = this.sequence?.nextTokenIndex || 0;
857+
console.log(`[LLM] Post-gen: stopReason=${finalStopReason}, responseChars=${fullResponse.length}, tokensUsed=${tokensUsed}, maxTokens=${merged.maxTokens}, llamaStopReason=${result?.metadata?.stopReason || 'unknown'}`);
856858
return {
857859
text: sanitized,
858860
rawText: fullResponse,

main/mcpToolServer.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ class MCPToolServer {
269269
this._toolDefsCache = [
270270
{
271271
name: 'web_search',
272-
description: 'Search the web for information using DuckDuckGo. Use when the answer may have changed since your training — anything that varies over time. Also use for documentation and error solutions when the current version matters.',
272+
description: 'Search the web for current information using DuckDuckGo. Use for anything current, live, or time-sensitive: prices, weather, news, headlines, scores, events, stock data, documentation lookups.',
273273
parameters: {
274274
query: { type: 'string', description: 'Search query', required: true },
275275
maxResults: { type: 'number', description: 'Max results (default 5)', required: false },
@@ -759,7 +759,7 @@ class MCPToolServer {
759759
// ── Planning / TODO Tools ──
760760
{
761761
name: 'write_todos',
762-
description: 'Create a checklist for complex multi-step tasks (e.g. building an app, refactoring code, planning a project). Do NOT use for simple questions, greetings, or conversation.',
762+
description: 'Create a checklist to plan and track multi-step tasks. Use when a task involves multiple steps — building an app, refactoring code, implementing a feature, planning a project.',
763763
parameters: {
764764
items: { type: 'array', description: 'Array of todo strings or {text,status} objects', required: true },
765765
},

src/components/Chat/ChatPanel.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,7 +1618,7 @@ ${e.message}`,
16181618

16191619
// Render content with tool terminal and code block detection
16201620
// Merges tool calls with their results into single collapsible blocks
1621-
const renderContentParts = (content: string, suppressTools = false) => {
1621+
const renderContentParts = (content: string, suppressTools = false, expandBlocks = false) => {
16221622
// Pre-extract tool results for merging
16231623
const toolResultMap = extractToolResults(content);
16241624

@@ -1733,7 +1733,7 @@ ${e.message}`,
17331733
);
17341734
} else {
17351735
pendingWriteFP = null;
1736-
elements.push(<CodeBlock key={i} code={code} language={lang} onApply={() => onApplyCode(currentFile, code)} onSaveAsFile={handleSaveAsFile} />);
1736+
elements.push(<CodeBlock key={i} code={code} language={lang} onApply={() => onApplyCode(currentFile, code)} onSaveAsFile={handleSaveAsFile} startExpanded={expandBlocks} />);
17371737
}
17381738
continue;
17391739
}
@@ -1858,11 +1858,11 @@ ${e.message}`,
18581858
return elements;
18591859
};
18601860

1861-
const renderMessage = (msg: ChatMessage): React.ReactNode[] => {
1861+
const renderMessage = (msg: ChatMessage, expandBlocks = false): React.ReactNode[] => {
18621862
const hasMsgTools = !!(msg.toolsUsed && msg.toolsUsed.length > 0);
18631863
// suppressTools=true: content rendering skips all tool blocks to prevent duplicate write_file
18641864
// bubbles and wrong failure counts. msg.toolsUsed is the authoritative source for tool UI.
1865-
const parts = renderContentParts(msg.content, hasMsgTools);
1865+
const parts = renderContentParts(msg.content, hasMsgTools, expandBlocks);
18661866
if (hasMsgTools) {
18671867
const WRITE_TOOLS_MSG = ['write_file', 'create_file', 'edit_file', 'append_to_file'];
18681868
const MSG_LANG_MAP: Record<string, string> = { ts: 'typescript', tsx: 'tsx', js: 'javascript', jsx: 'jsx', py: 'python', rs: 'rust', go: 'go', java: 'java', cs: 'csharp', cpp: 'cpp', c: 'c', html: 'html', css: 'css', json: 'json', yaml: 'yaml', yml: 'yaml', md: 'markdown', sh: 'bash', bat: 'batch', txt: 'text', xml: 'xml', sql: 'sql' };
@@ -3193,7 +3193,7 @@ ${e.message}`,
31933193
</div>
31943194
</div>
31953195
) : (
3196-
<div className="space-y-1">{renderMessage(msg)}</div>
3196+
<div className="space-y-1">{renderMessage(msg, index === messages.length - 1)}</div>
31973197
)
31983198
) : (
31993199
<>

src/components/Chat/ChatWidgets.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -457,13 +457,14 @@ export const ToolCallGroup: React.FC<{ children: React.ReactNode; count: number
457457
// ── Code Block with Copy/Apply ──
458458
const COLLAPSE_LINE_THRESHOLD = 6; // Collapse code blocks taller than this many lines
459459

460-
export const CodeBlock: React.FC<{ code: string; language: string; onApply: () => void; isToolCall?: boolean; isStreaming?: boolean; isAlreadyWritten?: boolean; onSaveAsFile?: (code: string, language: string) => void; defaultCollapsed?: boolean }> = ({ code, language, onApply, isToolCall, isStreaming, isAlreadyWritten, onSaveAsFile, defaultCollapsed }) => {
460+
export const CodeBlock: React.FC<{ code: string; language: string; onApply: () => void; isToolCall?: boolean; isStreaming?: boolean; isAlreadyWritten?: boolean; onSaveAsFile?: (code: string, language: string) => void; defaultCollapsed?: boolean; startExpanded?: boolean }> = ({ code, language, onApply, isToolCall, isStreaming, isAlreadyWritten, onSaveAsFile, defaultCollapsed, startExpanded }) => {
461461
const [copied, setCopied] = useState(false);
462462
const lineCount = code.split('\n').length;
463463
const isLong = lineCount > COLLAPSE_LINE_THRESHOLD;
464464
// Default to collapsed for long blocks; keep streaming blocks expanded so users can watch generation
465465
// defaultCollapsed forces collapsed on first render (used for live tool call generation bubbles)
466-
const [expanded, setExpanded] = useState(defaultCollapsed ? false : !!isStreaming || !isLong);
466+
// startExpanded overrides collapse for just-finalized messages to prevent height jump on finalization
467+
const [expanded, setExpanded] = useState(defaultCollapsed ? false : !!isStreaming || !!startExpanded || !isLong);
467468

468469
const handleCopy = () => {
469470
navigator.clipboard.writeText(code);

0 commit comments

Comments
 (0)