mirror of
https://github.com/voideditor/void
synced 2026-05-24 01:48:25 +00:00
loading
This commit is contained in:
parent
6ce37f7627
commit
321876932a
4 changed files with 80 additions and 53 deletions
|
|
@ -322,12 +322,12 @@ export const ApplyButtonsHTML = ({ codeStr, applyBoxId, reapplyIcon, uri }: { co
|
|||
<IconShell1
|
||||
Icon={X}
|
||||
onClick={onReject}
|
||||
{...tooltipPropsForApplyBlock({ tooltipName: 'Reject file' })}
|
||||
{...tooltipPropsForApplyBlock({ tooltipName: 'Remove' })}
|
||||
/>
|
||||
<IconShell1
|
||||
Icon={Check}
|
||||
onClick={onAccept}
|
||||
{...tooltipPropsForApplyBlock({ tooltipName: 'Accept file' })}
|
||||
{...tooltipPropsForApplyBlock({ tooltipName: 'Keep' })}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<div className="w-full px-2">
|
||||
<ToolHeaderWrapper className='!border-t-0' title={'Lint errors'} desc1={''} isOpen={isOpen} onClick={() => { setIsOpen(o => !o) }} >
|
||||
<LintErrorChildren lintErrors={lintErrors} />
|
||||
</ToolHeaderWrapper>
|
||||
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
if (lintErrors.length === 0) return null;
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
return (
|
||||
<div className="w-full px-2 mt-0.5">
|
||||
<div
|
||||
className={`flex items-center cursor-pointer select-none transition-colors duration-150 pl-0 py-0.5 rounded group`}
|
||||
onClick={() => setIsOpen(o => !o)}
|
||||
style={{background: 'none'}}
|
||||
>
|
||||
<ChevronRight
|
||||
className={`mr-1 h-4 w-4 flex-shrink-0 transition-transform duration-100 text-void-fg-4 group-hover:text-void-fg-3 ${isOpen ? 'rotate-90' : ''}`}
|
||||
/>
|
||||
<span className="font-medium text-void-fg-4 group-hover:text-void-fg-3 text-xs">Lint errors</span>
|
||||
</div>
|
||||
<div
|
||||
className={`overflow-hidden transition-all duration-200 ease-in-out ${isOpen ? 'opacity-100 py-1' : 'max-h-0 opacity-0'} text-xs pl-5`}
|
||||
>
|
||||
<div className="flex flex-col gap-0.5 overflow-x-auto whitespace-nowrap text-void-fg-4 opacity-90 border-l-2 border-void-warning px-2 py-0.5">
|
||||
{lintErrors.map((error, i) => (
|
||||
<div key={i} className="">Lines {error.startLineNumber}-{error.endLineNumber}: {error.message}</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1445,7 +1454,7 @@ const toolNameToComponent: { [T in ToolName]: { resultWrapper: ResultWrapper<T>,
|
|||
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 <div
|
||||
className={`flex items-center justify-center px-2 `}
|
||||
>
|
||||
<div
|
||||
className={`flex items-center justify-center px-2 `}
|
||||
>
|
||||
<div
|
||||
className={`
|
||||
text-xs
|
||||
text-void-fg-3
|
||||
cursor-pointer select-none
|
||||
${isCheckpointGhost ? 'opacity-50' : 'opacity-100'}
|
||||
text-xs
|
||||
text-void-fg-3
|
||||
cursor-pointer select-none
|
||||
${isCheckpointGhost ? 'opacity-50' : 'opacity-100'}
|
||||
`}
|
||||
onClick={() => {
|
||||
if (threadIsRunning) return
|
||||
chatThreadService.jumpToCheckpointBeforeMessageIdx({ threadId, messageIdx, jumpToUserModified: true })
|
||||
}}
|
||||
>
|
||||
Checkpoint
|
||||
</div>
|
||||
</div>
|
||||
>
|
||||
Checkpoint
|
||||
</div>
|
||||
</div>
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -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 = <span className='flex items-center'>
|
||||
{uriDone ?
|
||||
getBasename(toolCallSoFar.rawParams['uri'] ?? 'unknown')
|
||||
: `Generating`}
|
||||
<IconLoading />
|
||||
</span>
|
||||
const uriDone = toolCallSoFar.doneParams.includes('uri')
|
||||
const desc1 = <span className='flex items-center'>
|
||||
{uriDone ?
|
||||
getBasename(toolCallSoFar.rawParams['uri'] ?? 'unknown')
|
||||
: `Generating`}
|
||||
<IconLoading />
|
||||
</span>
|
||||
|
||||
// If URI has not been specified
|
||||
return <ToolHeaderWrapper
|
||||
title={title}
|
||||
desc1={desc1}
|
||||
desc2={<JumpToFileButton uri={uri} />}
|
||||
title={title}
|
||||
desc1={desc1}
|
||||
desc2={<JumpToFileButton uri={uri} />}
|
||||
>
|
||||
<EditToolChildren
|
||||
uri={uri}
|
||||
changeDescription={toolCallSoFar.rawParams.change_description ?? ''}
|
||||
/>
|
||||
<IconLoading />
|
||||
</ToolHeaderWrapper>
|
||||
</ToolHeaderWrapper>
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue