chatMode and agent mode UI

This commit is contained in:
Andrew Pareles 2025-03-15 04:19:30 -07:00
parent c1e83e458b
commit a4d93ac95a
4 changed files with 69 additions and 17 deletions

View file

@ -540,11 +540,13 @@ class ChatThreadService extends Disposable implements IChatThreadService {
// CAN THROW ERRORS
approveTool(toolId: string) {
const chatMode = this._settingsService.state.globalSettings.chatMode
// if not streaming, approveToolAndStreamResponse
const threadId = this.getCurrentThread().id
const isStreaming = !!this.streamState[threadId]?.streamingToken
if (!isStreaming) {
this._approveToolAndStreamResponse_NotStreamingNow({ chatMode: 'agent' })
this._approveToolAndStreamResponse_NotStreamingNow({ chatMode })
}
else {
const resRej = this.resRejOfToolAwaitingApproval[toolId]

View file

@ -17,13 +17,13 @@ import { ChatMarkdownRender, ChatMessageLocation, getApplyBoxId } from '../markd
import { URI } from '../../../../../../../base/common/uri.js';
import { IDisposable } from '../../../../../../../base/common/lifecycle.js';
import { ErrorDisplay } from './ErrorDisplay.js';
import { TextAreaFns, VoidInputBox2, VoidSlider, VoidSwitch } from '../util/inputs.js';
import { TextAreaFns, VoidCustomDropdownBox, VoidInputBox2, VoidSlider, VoidSwitch } from '../util/inputs.js';
import { ModelDropdown, } from '../void-settings-tsx/ModelDropdown.js';
import { SidebarThreadSelector } from './SidebarThreadSelector.js';
import { useScrollbarStyles } from '../util/useScrollbarStyles.js';
import { VOID_CTRL_L_ACTION_ID } from '../../../actionIDs.js';
import { VOID_OPEN_SETTINGS_ACTION_ID } from '../../../voidSettingsPane.js';
import { FeatureName, isFeatureNameDisabled } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js';
import { ChatMode, FeatureName, isFeatureNameDisabled } from '../../../../../../../workbench/contrib/void/common/voidSettingsTypes.js';
import { WarningBox } from '../void-settings-tsx/WarningBox.js';
import { getModelSelectionState, getModelCapabilities } from '../../../../common/modelCapabilities.js';
import { AlertTriangle, ChevronRight, Dot, Pencil, X } from 'lucide-react';
@ -206,7 +206,7 @@ const getChatBubbleId = (threadId: string, messageIdx: number) => `${threadId}-$
// SLIDER ONLY:
const ReasoningOptionDropdown = ({ featureName }: { featureName: FeatureName }) => {
const ReasoningOptionSlider = ({ featureName }: { featureName: FeatureName }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
@ -264,6 +264,46 @@ const ReasoningOptionDropdown = ({ featureName }: { featureName: FeatureName })
const nameOfChatMode = {
'chat': 'Chat',
'gather': 'Gather',
'agent': 'Agent',
}
const detailOfChatMode = {
'chat': 'Chat only',
'gather': 'Read files',
'agent': 'Read and edit files',
}
const ChatModeDropdown = ({ className }: { className: string }) => {
const accessor = useAccessor()
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const options: ChatMode[] = useMemo(() => ['chat', 'gather', 'agent'], [])
const onChangeOption = useCallback((newVal: ChatMode) => {
voidSettingsService.setGlobalSetting('chatMode', newVal)
}, [voidSettingsService])
return <VoidCustomDropdownBox
className={className}
options={options}
selectedOption={voidSettingsService.state.globalSettings.chatMode}
onChangeOption={onChangeOption}
getOptionDisplayName={(val) => nameOfChatMode[val]}
getOptionDropdownName={(val) => nameOfChatMode[val]}
getOptionDropdownDetail={(val) => detailOfChatMode[val]}
getOptionsEqual={(a, b) => a === b}
/>
}
interface VoidChatAreaProps {
@ -363,9 +403,13 @@ export const VoidChatArea: React.FC<VoidChatAreaProps> = ({
{/* Bottom row */}
<div className='flex flex-row justify-between items-end gap-1'>
{showModelDropdown && (
<div className='max-w-[200px] flex-grow'>
<ReasoningOptionDropdown featureName={featureName} />
<ModelDropdown featureName={featureName} className='text-xs text-void-fg-3' />
<div className='flex flex-col gap-1'>
<ReasoningOptionSlider featureName={featureName} />
<div className='flex items-center flex-wrap gap-x-1 gap-y-1'>
<ModelDropdown featureName={featureName} className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
<ChatModeDropdown className='text-xs text-void-fg-3 bg-void-bg-1 border border-void-border-1 rounded p-0.5 px-1' />
</div>
</div>
)}
@ -1675,8 +1719,10 @@ export const SidebarChat = () => {
// getModelCapabilities() // TODO!!! check if can go into agent mode
const chatMode = settingsState.globalSettings.chatMode
try {
await chatThreadsService.addUserMessageAndStreamResponse({ userMessage, chatMode: 'agent' })
await chatThreadsService.addUserMessageAndStreamResponse({ userMessage, chatMode })
} catch (e) {
console.error('Error while sending message in chat:', e)
}

View file

@ -316,18 +316,18 @@ export const VoidSlider = ({
{/* Track */}
<div
className={`relative ${size === 'xxs' ? 'h-0.5' :
size === 'xs' ? 'h-1' :
size === 'sm' ? 'h-1.5' :
size === 'sm+' ? 'h-2' : 'h-2.5'
size === 'xs' ? 'h-1' :
size === 'sm' ? 'h-1.5' :
size === 'sm+' ? 'h-2' : 'h-2.5'
} bg-gray-200 dark:bg-gray-700 rounded-full cursor-pointer`}
onClick={handleTrackClick}
>
{/* Filled part of track */}
<div
className={`absolute left-0 ${size === 'xxs' ? 'h-0.5' :
size === 'xs' ? 'h-1' :
size === 'sm' ? 'h-1.5' :
size === 'sm+' ? 'h-2' : 'h-2.5'
size === 'xs' ? 'h-1' :
size === 'sm' ? 'h-1.5' :
size === 'sm+' ? 'h-2' : 'h-2.5'
} bg-gray-900 dark:bg-white rounded-full`}
style={{ width: `${percentage}%` }}
/>
@ -471,7 +471,8 @@ export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
className,
arrowTouchesText = true,
matchInputWidth = false,
gap = 0,
gapPx = 0,
offsetPx = -6,
}: {
options: T[];
selectedOption: T | undefined;
@ -483,7 +484,8 @@ export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
className?: string;
arrowTouchesText?: boolean;
matchInputWidth?: boolean;
gap?: number;
gapPx?: number;
offsetPx?:number;
}) => {
const [isOpen, setIsOpen] = useState(false);
const measureRef = useRef<HTMLDivElement>(null);
@ -502,7 +504,7 @@ export const VoidCustomDropdownBox = <T extends NonNullable<any>>({
placement: 'bottom-start',
middleware: [
offset(gap),
offset({ mainAxis: gapPx, crossAxis: offsetPx }),
flip({
boundary: document.body,
padding: 8

View file

@ -387,6 +387,7 @@ export type GlobalSettings = {
enableAutocomplete: boolean;
syncApplyToChat: boolean;
enableFastApply: boolean;
chatMode: ChatMode;
}
export const defaultGlobalSettings: GlobalSettings = {
@ -395,6 +396,7 @@ export const defaultGlobalSettings: GlobalSettings = {
enableAutocomplete: false,
syncApplyToChat: true,
enableFastApply: true,
chatMode: 'agent',
}
export type GlobalSettingName = keyof GlobalSettings