diff --git a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx index 9f364ba0..8b198b1b 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/markdown/ApplyBlockHoverButtons.tsx @@ -322,12 +322,12 @@ export const ApplyButtonsHTML = ({ codeStr, applyBoxId, reapplyIcon, uri }: { co } diff --git a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx index 4892feff..c385de66 100644 --- a/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx +++ b/src/vs/workbench/contrib/void/browser/react/src/sidebar-tsx/SidebarChat.tsx @@ -20,14 +20,13 @@ import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js'; import { ChatMode, FeatureName, isFeatureNameDisabled } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js'; import { WarningBox } from '../void-settings-tsx/WarningBox.js'; import { getModelCapabilities, getIsReasoningEnabledState } from '../../../../common/modelCapabilities.js'; -import { AlertTriangle, Ban, Check, ChevronRight, Dot, FileIcon, Pencil, Undo, Undo2, X } from 'lucide-react'; +import { AlertTriangle, Ban, Check, ChevronRight, Dot, FileIcon, Pencil, Undo, Undo2, X, Flag } from 'lucide-react'; import { ChatMessage, CheckpointEntry, StagingSelectionItem, ToolMessage } from '../../../../common/chatThreadServiceTypes.js'; import { LintErrorItem, ToolCallParams, ToolNameWithApproval } from '../../../../common/toolsServiceTypes.js'; import { ApplyButtonsHTML, CopyButton, IconShell1, JumpToFileButton, JumpToTerminalButton, StatusIndicator, StatusIndicatorForApplyButton, useApplyButtonState } from '../markdown/ApplyBlockHoverButtons.js'; import { IsRunningType } from '../../../chatThreadService.js'; import { acceptAllBg, acceptBorder, buttonFontSize, buttonTextColor, rejectAllBg, rejectBg, rejectBorder } from '../../../../common/helpers/colors.js'; import { ToolName, toolNames } from '../../../../common/prompt/prompts.js'; -import { error } from 'console'; import { RawToolCallObj } from '../../../../common/sendLLMMessageTypes.js'; import { MAX_FILE_CHARS_PAGE } from '../../../toolsService.js'; @@ -1355,21 +1354,31 @@ const LintErrorChildren = ({ lintErrors }: { lintErrors: LintErrorItem[] }) => { } const EditToolLintErrors = ({ lintErrors }: { lintErrors: LintErrorItem[] }) => { - - if (lintErrors.length === 0) return null; - - const [isOpen, setIsOpen] = useState(false); - - return ( -
- { setIsOpen(o => !o) }} > - - - -
- ) - - + if (lintErrors.length === 0) return null; + const [isOpen, setIsOpen] = useState(false); + return ( +
+
setIsOpen(o => !o)} + style={{background: 'none'}} + > + + Lint errors +
+
+
+ {lintErrors.map((error, i) => ( +
Lines {error.startLineNumber}-{error.endLineNumber}: {error.message}
+ ))} +
+
+
+ ); } @@ -1445,7 +1454,7 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper, const { params, result } = toolMessage componentParams.onClick = () => { commandService.executeCommand('vscode.open', params.uri, { preview: true }) } if (result.hasNextPage && params.pageNumber === 1) // first page - componentParams.desc2 = `(first ${Math.round(MAX_FILE_CHARS_PAGE) / 1000}k)` + componentParams.desc2 = `(truncated after ${Math.round(MAX_FILE_CHARS_PAGE) / 1000}k)` else if (params.pageNumber > 1) // subsequent pages componentParams.desc2 = `(part ${params.pageNumber})` } @@ -1927,23 +1936,23 @@ const Checkpoint = ({ message, threadId, messageIdx, isCheckpointGhost, threadIs const chatThreadService = accessor.get('IChatThreadService') return
-
+
{ if (threadIsRunning) return chatThreadService.jumpToCheckpointBeforeMessageIdx({ threadId, messageIdx, jumpToUserModified: true }) }} - > - Checkpoint -
-
+ > + Checkpoint +
+ } @@ -2345,30 +2354,30 @@ const CommandBarInChat = () => { const EditToolSoFar = ({ toolCallSoFar, }: { toolCallSoFar: RawToolCallObj }) => { - const uri = URI.file(toolCallSoFar.rawParams.uri ?? 'unknown') + const uri = URI.file(toolCallSoFar.rawParams.uri ?? 'unknown') - const title = titleOfToolName['edit_file'].proposed + const title = titleOfToolName['edit_file'].proposed - const uriDone = toolCallSoFar.doneParams.includes('uri') - const desc1 = - {uriDone ? - getBasename(toolCallSoFar.rawParams['uri'] ?? 'unknown') - : `Generating`} - - + const uriDone = toolCallSoFar.doneParams.includes('uri') + const desc1 = + {uriDone ? + getBasename(toolCallSoFar.rawParams['uri'] ?? 'unknown') + : `Generating`} + + // If URI has not been specified return } + title={title} + desc1={desc1} + desc2={} > - + diff --git a/src/vs/workbench/contrib/void/browser/sidebarActions.ts b/src/vs/workbench/contrib/void/browser/sidebarActions.ts index e1476552..ba257dc4 100644 --- a/src/vs/workbench/contrib/void/browser/sidebarActions.ts +++ b/src/vs/workbench/contrib/void/browser/sidebarActions.ts @@ -25,6 +25,7 @@ import { Disposable } from '../../../../base/common/lifecycle.js'; import { localize2 } from '../../../../nls.js'; import { StagingSelectionItem } from '../common/chatThreadServiceTypes.js'; import { IChatThreadService } from './chatThreadService.js'; +import { getActiveWindow } from '../../../../base/browser/dom.js'; // ---------- Register commands and keybindings ---------- @@ -225,9 +226,13 @@ registerAction2(class extends Action2 { metricsService.capture('Chat Navigation', { type: 'New Chat' }) stateService.setState({ isHistoryOpen: false, currentTab: 'chat' }) - stateService.fireFocusChat() const chatThreadService = accessor.get(IChatThreadService) chatThreadService.openNewThread() + + // focus + stateService.fireFocusChat() + const window = getActiveWindow() + window.requestAnimationFrame(() => stateService.fireFocusChat()) } }) diff --git a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts index 687497d0..b3eec6ae 100644 --- a/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts +++ b/src/vs/workbench/contrib/void/electron-main/llmMessage/sendLLMMessage.impl.ts @@ -256,7 +256,12 @@ const _sendOpenAICompatibleChat = ({ messages, onText, onFinalMessage, onError, fullReasoningSoFar += newReasoning } - onText({ fullText: fullTextSoFar, fullReasoning: fullReasoningSoFar }) + onText({ + fullText: fullTextSoFar, + fullReasoning: fullReasoningSoFar, + toolCall: isAToolName(toolName) ? { name: toolName, rawParams: {}, isDone: false, doneParams: [], id: toolId } : undefined, + }) + } // on final if (!fullTextSoFar && !fullReasoningSoFar && !toolName) { @@ -402,6 +407,14 @@ const sendAnthropicChat = ({ messages, providerName, onText, onFinalMessage, onE let fullToolName = '' let fullToolParams = '' + + const runOnText = () => { + onText({ + fullText, + fullReasoning, + toolCall: isAToolName(fullToolName) ? { name: fullToolName, rawParams: {}, isDone: false, doneParams: [], id: 'dummy' } : undefined, + }) + } // there are no events for tool_use, it comes in at the end stream.on('streamEvent', e => { // start block @@ -409,22 +422,22 @@ const sendAnthropicChat = ({ messages, providerName, onText, onFinalMessage, onE if (e.content_block.type === 'text') { if (fullText) fullText += '\n\n' // starting a 2nd text block fullText += e.content_block.text - onText({ fullText, fullReasoning, }) + runOnText() } else if (e.content_block.type === 'thinking') { if (fullReasoning) fullReasoning += '\n\n' // starting a 2nd reasoning block fullReasoning += e.content_block.thinking - onText({ fullText, fullReasoning, }) + runOnText() } else if (e.content_block.type === 'redacted_thinking') { console.log('delta', e.content_block.type) if (fullReasoning) fullReasoning += '\n\n' // starting a 2nd reasoning block fullReasoning += '[redacted_thinking]' - onText({ fullText, fullReasoning, }) + runOnText() } else if (e.content_block.type === 'tool_use') { fullToolName += e.content_block.name ?? '' // anthropic gives us the tool name in the start block - onText({ fullText, fullReasoning, }) + runOnText() } } @@ -432,15 +445,15 @@ const sendAnthropicChat = ({ messages, providerName, onText, onFinalMessage, onE else if (e.type === 'content_block_delta') { if (e.delta.type === 'text_delta') { fullText += e.delta.text - onText({ fullText, fullReasoning, }) + runOnText() } else if (e.delta.type === 'thinking_delta') { fullReasoning += e.delta.thinking - onText({ fullText, fullReasoning, }) + runOnText() } else if (e.delta.type === 'input_json_delta') { // tool use fullToolParams += e.delta.partial_json ?? '' // anthropic gives us the partial delta (string) here - https://docs.anthropic.com/en/api/messages-streaming - onText({ fullText, fullReasoning, }) + runOnText() } } })