mirror of
https://github.com/voideditor/void
synced 2026-05-24 09:58:23 +00:00
chatMode and agent mode UI
This commit is contained in:
parent
c1e83e458b
commit
a4d93ac95a
4 changed files with 69 additions and 17 deletions
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue