add autoapply

This commit is contained in:
Andrew Pareles 2025-03-18 00:33:40 -07:00
parent 5b3471a7d7
commit 9ab3ec3c11
8 changed files with 64 additions and 14 deletions

View file

@ -712,7 +712,7 @@ class ChatThreadService extends Disposable implements IChatThreadService {
}
// 2. if tool requires approval, break from the loop, awaiting approval
const requiresApproval = true // TODO!!!
const requiresApproval = !this._settingsService.state.globalSettings.autoApprove
if (requiresApproval && toolNamesThatRequireApproval.has(toolName)) {
this._addMessageToThread(threadId, { role: 'tool_request', name: toolName, paramsStr: toolParamsStr, params: toolParams, id: toolId })
return true

View file

@ -28,7 +28,6 @@ import { IConsistentEditorItemService, IConsistentItemService } from './helperSe
import { voidPrefixAndSuffix, ctrlKStream_userMessage, ctrlKStream_systemMessage, defaultQuickEditFimTags, rewriteCode_systemMessage, rewriteCode_userMessage, searchReplace_systemMessage, searchReplace_userMessage, FINAL, ORIGINAL, DIVIDER, tripleTick, } from '../common/prompt/prompts.js';
import { mountCtrlK } from './react/out/quick-edit-tsx/index.js'
import { mountVoidCommandBar } from './react/out/void-command-bar-tsx/index.js'
import { QuickEditPropsType } from './quickEditActions.js';
import { IModelContentChangedEvent } from '../../../../editor/common/textModelEvents.js';
import { extractCodeFromFIM, extractCodeFromRegular, ExtractedSearchReplaceBlock, extractSearchReplaceBlocks } from '../common/helpers/extractCodeFromResult.js';
@ -1558,8 +1557,11 @@ class EditCodeService extends Disposable implements IEditCodeService {
const originalFileCode = model.getValue(EndOfLinePreference.LF)
const numLines = model.getLineCount()
// reject all diffZones on this URI, adding to history (there can't possibly be overlap after this)
this.removeDiffAreas({ uri, behavior: 'reject', removeCtrlKs: true })
// Only reject diffZones if we're not using keep-conflicts
if (opts.startBehavior !== 'keep-conflicts') {
// reject all diffZones on this URI, adding to history (there can't possibly be overlap after this)
this.removeDiffAreas({ uri, behavior: 'reject', removeCtrlKs: true })
}
const startLine = 1
const endLine = numLines
@ -1692,7 +1694,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
nMessagesSent += 1
if (nMessagesSent >= 5) {
this._notifyError({ message: 'Void Error: Tried to Fast Apply 5 times but failed. Please try again with a smarter model or disable Fast Apply.', fullError: null })
this._notifyError({ message: 'Tried to Fast Apply 5 times but failed. Please try again with a smarter model or disable Fast Apply.', fullError: null })
onDone()
this._undoHistory(uri)
break
@ -1732,7 +1734,11 @@ class EditCodeService extends Disposable implements IEditCodeService {
else {
// starting line is at least the number of lines in the generated code minus 1
const numLinesInOrig = numLinesOfStr(block.orig)
diffZone._streamState.line = Math.max(numLinesInOrig - 1, 1, diffZone._streamState.line ?? 1)
const newLine = Math.max(numLinesInOrig - 1, 1, diffZone._streamState.line ?? 1)
if (newLine !== diffZone._streamState.line) {
diffZone._streamState.line = newLine
this._refreshStylesAndDiffsInURI(uri)
}
}
// must be done writing original to move on to writing streamed content
continue
@ -1746,6 +1752,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
// if error
if (typeof originalBounds === 'string') {
console.log('Error finding text in code:')
console.log('originalFileCode', { originalFileCode })
console.log('fullText', { fullText })
console.log('error:', originalBounds)
console.log('block.orig:', block.orig)
@ -1759,6 +1766,7 @@ class EditCodeService extends Disposable implements IEditCodeService {
// TODO!!! test this
blocks.splice(blockNum, Infinity) // remove all blocks at and after this one
oldBlocks = deepClone(blocks)
addedTrackingZoneOfBlockNum.splice(blockNum, Infinity) // also remove corresponding tracking zones
// Reset streaming state but preserve line context
shouldUpdateOrigStreamStyle = true
@ -2412,7 +2420,11 @@ class AcceptAllRejectAllWidget extends Widget implements IOverlayWidget {
// Mount command bar using mountVoidCommandBar
this._instantiationService.invokeFunction(accessor => {
mountVoidCommandBar(voidCommandBar, accessor, {})
console.log(voidCommandBar)
if (voidCommandBar) { // remove this
Math.random()
}
// mountVoidCommandBar(voidCommandBar, accessor, {})
});
// Style accept button

View file

@ -19,7 +19,7 @@ export type StartApplyingOpts = ({
from: 'ClickApply';
applyStr: string;
uri: 'current' | URI;
startBehavior: 'accept-conflicts' | 'reject-conflicts';
startBehavior: 'accept-conflicts' | 'reject-conflicts' | 'keep-conflicts';
})

View file

@ -154,7 +154,7 @@ export const useApplyButtonHTML = ({ codeStr, applyBoxId, uri }: { codeStr: stri
from: 'ClickApply',
applyStr: codeStr,
uri: uri,
startBehavior: 'reject-conflicts',
startBehavior: 'keep-conflicts',
}) ?? []
if (!newApplyingUri) console.log('NOT new applying')

View file

@ -1147,6 +1147,8 @@ const ToolRequestAcceptRejectButtons = () => {
const accessor = useAccessor()
const chatThreadsService = accessor.get('IChatThreadService')
const metricsService = accessor.get('IMetricsService')
const voidSettingsService = accessor.get('IVoidSettingsService')
const voidSettingsState = useSettingsState()
const onAccept = useCallback(() => {
try { // this doesn't need to be wrapped in try/catch anymore
@ -1164,6 +1166,11 @@ const ToolRequestAcceptRejectButtons = () => {
metricsService.capture('Tool Request Rejected', {})
}, [chatThreadsService, metricsService])
const onToggleAutoApprove = useCallback((newValue: boolean) => {
voidSettingsService.setGlobalSetting('autoApprove', newValue)
metricsService.capture('Tool Auto-Accept Toggle', { enabled: newValue })
}, [voidSettingsService, metricsService])
const approveButton = (
<button
onClick={onAccept}
@ -1196,11 +1203,21 @@ const ToolRequestAcceptRejectButtons = () => {
</button>
)
// const isCancelled = state.cancelled || (!isLastMessage && state.awaiting)
const autoApproveToggle = (
<div className="flex items-center ml-2 gap-x-1" title="Auto-accept future tool calls">
<VoidSwitch
size="xs"
value={voidSettingsState.globalSettings.autoApprove}
onChange={onToggleAutoApprove}
/>
<span className="text-void-fg-3 text-xs">Auto</span>
</div>
)
return <div className="flex gap-2 my-1">
return <div className="flex gap-2 my-1 items-center">
{approveButton}
{cancelButton}
{autoApproveToggle}
</div>
}

View file

@ -524,12 +524,31 @@ export const FeaturesTab = () => {
</div>
</div>
</div>
</div>
{/* Tools Section */}
<h2 className={`text-3xl mb-2 mt-12`}>Agent Options</h2>
<div className='flex items-start mt-4 mb-8'>
<div className='w-full'>
<h4 className={`text-base`}>Tools</h4>
<div className='text-sm italic text-void-fg-3 mt-1 mb-4'>Settings that control Tool behavior.</div>
<div className='my-2'>
{/* Auto Accept Switch */}
<div className='flex items-center gap-x-2 my-2'>
<VoidSwitch
size='xs'
value={voidSettingsState.globalSettings.autoApprove}
onChange={(newVal) => voidSettingsService.setGlobalSetting('autoApprove', newVal)}
/>
<span className='text-void-fg-3 text-xs pointer-events-none'>{voidSettingsState.globalSettings.autoApprove ? 'Auto-approve' : 'Ask for approval'}</span>
</div>
</div>
</div>
</div>
</ErrorBoundary>

View file

@ -348,7 +348,7 @@ export class ToolsService implements IToolsService {
uri,
applyStr: changeDescription,
from: 'ClickApply',
startBehavior: 'accept-conflicts',
startBehavior: 'keep-conflicts',
})
if (!res) throw new Error(`The Apply model did not start running on ${basename(uri.fsPath)}. Please try again.`)
const [_, applyDonePromise] = res

View file

@ -388,6 +388,7 @@ export type GlobalSettings = {
syncApplyToChat: boolean;
enableFastApply: boolean;
chatMode: ChatMode;
autoApprove: boolean;
}
export const defaultGlobalSettings: GlobalSettings = {
@ -397,6 +398,7 @@ export const defaultGlobalSettings: GlobalSettings = {
syncApplyToChat: true,
enableFastApply: true,
chatMode: 'agent',
autoApprove: false,
}
export type GlobalSettingName = keyof GlobalSettings