diff --git a/core/config/migrateSharedConfig.ts b/core/config/migrateSharedConfig.ts
index e27a631dc6e..8b18b41428d 100644
--- a/core/config/migrateSharedConfig.ts
+++ b/core/config/migrateSharedConfig.ts
@@ -173,13 +173,6 @@ export function migrateJsonSharedConfig(filepath: string, ide: IDE): void {
effected = true;
}
- const { autoAcceptEditToolDiffs, ...withoutAutoApply } = migratedUI;
- if (autoAcceptEditToolDiffs !== undefined) {
- shareConfigUpdates.autoAcceptEditToolDiffs = autoAcceptEditToolDiffs;
- migratedUI = withoutAutoApply;
- effected = true;
- }
-
const { showChatScrollbar, ...withoutShowChatScrollbar } = migratedUI;
if (showChatScrollbar !== undefined) {
shareConfigUpdates.showChatScrollbar = showChatScrollbar;
diff --git a/core/config/sharedConfig.ts b/core/config/sharedConfig.ts
index 52b96061aa2..87306a2aed8 100644
--- a/core/config/sharedConfig.ts
+++ b/core/config/sharedConfig.ts
@@ -31,7 +31,6 @@ export const sharedConfigSchema = z
codeWrap: z.boolean(),
displayRawMarkdown: z.boolean(),
showChatScrollbar: z.boolean(),
- autoAcceptEditToolDiffs: z.boolean(),
continueAfterToolRejection: z.boolean(),
// `tabAutocompleteOptions` in `ContinueConfig`
@@ -140,10 +139,6 @@ export function modifyAnyConfigWithSharedConfig<
if (sharedConfig.showChatScrollbar !== undefined) {
configCopy.ui.showChatScrollbar = sharedConfig.showChatScrollbar;
}
- if (sharedConfig.autoAcceptEditToolDiffs !== undefined) {
- configCopy.ui.autoAcceptEditToolDiffs =
- sharedConfig.autoAcceptEditToolDiffs;
- }
if (sharedConfig.allowAnonymousTelemetry !== undefined) {
configCopy.allowAnonymousTelemetry = sharedConfig.allowAnonymousTelemetry;
diff --git a/core/index.d.ts b/core/index.d.ts
index 87bc1ba1395..83d896e34f9 100644
--- a/core/index.d.ts
+++ b/core/index.d.ts
@@ -1389,7 +1389,6 @@ export interface ContinueUIConfig {
showChatScrollbar?: boolean;
codeWrap?: boolean;
showSessionTabs?: boolean;
- autoAcceptEditToolDiffs?: boolean;
continueAfterToolRejection?: boolean;
}
diff --git a/gui/src/pages/config/components/ToolPoliciesGroup.tsx b/gui/src/pages/config/components/ToolPoliciesGroup.tsx
index 796b715f63b..3561f9e7316 100644
--- a/gui/src/pages/config/components/ToolPoliciesGroup.tsx
+++ b/gui/src/pages/config/components/ToolPoliciesGroup.tsx
@@ -2,6 +2,7 @@ import {
ChevronDownIcon,
WrenchScrewdriverIcon,
} from "@heroicons/react/24/outline";
+import { Tool } from "core";
import { useMemo, useState } from "react";
import ToggleSwitch from "../../../components/gui/Switch";
import { ToolTip } from "../../../components/gui/Tooltip";
@@ -28,7 +29,9 @@ export function ToolPoliciesGroup({
const dispatch = useAppDispatch();
const [isExpanded, setIsExpanded] = useState(false);
- const availableTools = useAppSelector((state) => state.config.config.tools);
+ const availableTools = useAppSelector(
+ (state) => state.config.config.tools as Tool[],
+ );
const tools = useMemo(() => {
return availableTools.filter((t) => t.group === groupName);
}, [availableTools, groupName]);
diff --git a/gui/src/pages/config/components/ToolPolicyItem.tsx b/gui/src/pages/config/components/ToolPolicyItem.tsx
index 2971e015d4f..5d81c5908f2 100644
--- a/gui/src/pages/config/components/ToolPolicyItem.tsx
+++ b/gui/src/pages/config/components/ToolPolicyItem.tsx
@@ -19,7 +19,6 @@ import {
import { useFontSize } from "../../../components/ui/font";
import { useAppSelector } from "../../../redux/hooks";
import { addTool, setToolPolicy } from "../../../redux/slices/uiSlice";
-import { isEditTool } from "../../../util/toolCallState";
interface ToolPolicyItemProps {
tool: Tool;
@@ -29,22 +28,12 @@ interface ToolPolicyItemProps {
export function ToolPolicyItem(props: ToolPolicyItemProps) {
const dispatch = useDispatch();
- const toolPolicy = useAppSelector(
+ const policy = useAppSelector(
(state) => state.ui.toolSettings[props.tool.function.name],
);
const [isExpanded, setIsExpanded] = useState(false);
const mode = useAppSelector((state) => state.session.mode);
- const autoAcceptEditToolDiffs = useAppSelector(
- (state) => state.config.config.ui?.autoAcceptEditToolDiffs,
- );
- const isAutoAcceptedToolCall =
- isEditTool(props.tool.function.name) && autoAcceptEditToolDiffs;
-
- const policy = isAutoAcceptedToolCall
- ? "allowedWithoutPermission"
- : toolPolicy;
-
useEffect(() => {
if (!policy) {
dispatch(addTool(props.tool));
@@ -64,7 +53,6 @@ export function ToolPolicyItem(props: ToolPolicyItemProps) {
const fontSize = useFontSize(-2);
const disabled =
- isAutoAcceptedToolCall ||
!props.isGroupEnabled ||
(mode === "plan" &&
props.tool.group === BUILT_IN_GROUP_NAME &&
@@ -112,19 +100,6 @@ export function ToolPolicyItem(props: ToolPolicyItemProps) {
) : null}
- {isAutoAcceptedToolCall ? (
-
- Auto-Accept Agent Edits setting is on
-
- }
- >
-
-
- ) : null}
{props.tool.faviconUrl && (
- {isAutoAcceptedToolCall
- ? "Automatic"
- : disabled || policy === "disabled"
- ? "Excluded"
- : policy === "allowedWithoutPermission"
- ? "Automatic"
- : "Ask First"}
+ {disabled || policy === "disabled"
+ ? "Excluded"
+ : policy === "allowedWithoutPermission"
+ ? "Automatic"
+ : "Ask First"}
diff --git a/gui/src/pages/config/sections/UserSettingsSection.tsx b/gui/src/pages/config/sections/UserSettingsSection.tsx
index afa56aca4ef..27b7f9bb183 100644
--- a/gui/src/pages/config/sections/UserSettingsSection.tsx
+++ b/gui/src/pages/config/sections/UserSettingsSection.tsx
@@ -64,7 +64,6 @@ export function UserSettingsSection() {
const codeWrap = config.ui?.codeWrap ?? false;
const showChatScrollbar = config.ui?.showChatScrollbar ?? false;
const readResponseTTS = config.experimental?.readResponseTTS ?? false;
- const autoAcceptEditToolDiffs = config.ui?.autoAcceptEditToolDiffs ?? false;
const displayRawMarkdown = config.ui?.displayRawMarkdown ?? false;
const disableSessionTitles = config.disableSessionTitles ?? false;
const useCurrentFileAsContext =
@@ -163,15 +162,6 @@ export function UserSettingsSection() {
handleUpdate({ displayRawMarkdown: !value })
}
/>
-
- handleUpdate({ autoAcceptEditToolDiffs: value })
- }
- />
diff --git a/gui/src/pages/gui/chat-tests/EditToolScenarios.test.tsx b/gui/src/pages/gui/chat-tests/EditToolScenarios.test.tsx
index dd95e09a979..b06264f8daa 100644
--- a/gui/src/pages/gui/chat-tests/EditToolScenarios.test.tsx
+++ b/gui/src/pages/gui/chat-tests/EditToolScenarios.test.tsx
@@ -1,9 +1,4 @@
import { BuiltInToolNames } from "core/tools/builtIn";
-import { generateToolCallButtonTestId } from "../../../components/mainInput/Lump/LumpToolbar/PendingToolCallToolbar";
-import {
- addAndSelectMockLlm,
- triggerConfigUpdate,
-} from "../../../util/test/config";
import { updateConfig } from "../../../redux/slices/configSlice";
import { renderWithProviders } from "../../../util/test/render";
import { Chat } from "../Chat";
@@ -11,7 +6,6 @@ import { Chat } from "../Chat";
import { waitFor } from "@testing-library/dom";
import { act } from "@testing-library/react";
import { ChatMessage } from "core";
-import { setToolPolicy } from "../../../redux/slices/uiSlice";
import { setInactive } from "../../../redux/slices/sessionSlice";
import {
getElementByTestId,
@@ -133,12 +127,6 @@ test(
await user.click(toggleCodeblockChevron);
await getElementByText(EDIT_CHANGES);
- // Pending tool call - find and click the accept button
- const acceptToolCallButton = await getElementByTestId(
- generateToolCallButtonTestId("accept", EDIT_TOOL_CALL_ID),
- );
- await user.click(acceptToolCallButton);
-
// Tool call, check that applyToFile was called for edit
await waitFor(() => {
expect(messengerRequestSpy).toHaveBeenCalledWith("applyToFile", {
diff --git a/gui/src/pages/gui/chat-tests/EditToolScenariosYolo.test.tsx b/gui/src/pages/gui/chat-tests/EditToolScenariosYolo.test.tsx
deleted file mode 100644
index c13d46773ee..00000000000
--- a/gui/src/pages/gui/chat-tests/EditToolScenariosYolo.test.tsx
+++ /dev/null
@@ -1,228 +0,0 @@
-import { BuiltInToolNames } from "core/tools/builtIn";
-import { generateToolCallButtonTestId } from "../../../components/mainInput/Lump/LumpToolbar/PendingToolCallToolbar";
-import { triggerConfigUpdate } from "../../../util/test/config";
-import { updateConfig } from "../../../redux/slices/configSlice";
-import { renderWithProviders } from "../../../util/test/render";
-import { Chat } from "../Chat";
-
-import { waitFor } from "@testing-library/dom";
-import { act } from "@testing-library/react";
-import { ChatMessage } from "core";
-import { setToolPolicy } from "../../../redux/slices/uiSlice";
-import { setInactive } from "../../../redux/slices/sessionSlice";
-import {
- getElementByTestId,
- getElementByText,
- sendInputWithMockedResponse,
- verifyNotPresentByTestId,
-} from "../../../util/test/utils";
-
-const EDIT_WORKSPACE_DIR = "file:///workspace";
-const EDIT_FILEPATH = "test.txt";
-const EDIT_FILE_URI = `${EDIT_WORKSPACE_DIR}/${EDIT_FILEPATH}`;
-const EDIT_CHANGES = "New content";
-const EDIT_TOOL_CALL_ID = "known-id";
-const EDIT_MESSAGES: ChatMessage[] = [
- {
- role: "assistant",
- content: "I'll edit the file for you.",
- },
- {
- role: "assistant",
- content: "",
- toolCalls: [
- {
- id: EDIT_TOOL_CALL_ID,
- function: {
- name: BuiltInToolNames.EditExistingFile,
- arguments: JSON.stringify({
- filepath: EDIT_FILEPATH,
- changes: EDIT_CHANGES,
- }),
- },
- },
- ],
- },
-];
-
-const POST_EDIT_RESPONSE = "Edit applied successfully";
-beforeEach(async () => {
- vi.clearAllMocks();
- // Clear any persisted state to ensure test isolation
- localStorage.clear();
- sessionStorage.clear();
-
- // Add a small delay to ensure cleanup is complete
- await new Promise((resolve) => setTimeout(resolve, 50));
-});
-
-test("Edit run with no policy and yolo mode", { timeout: 15000 }, async () => {
- // Additional cleanup before test starts
- localStorage.clear();
- sessionStorage.clear();
- await new Promise((resolve) => setTimeout(resolve, 100));
-
- // Setup
- const { ideMessenger, store, user } = await renderWithProviders();
-
- // Reset mocks to ensure clean state
- ideMessenger.resetMocks();
-
- // Reset streaming state to prevent test interference
- store.dispatch(setInactive());
-
- // Additional delay to ensure state is fully reset
- await new Promise((resolve) => setTimeout(resolve, 100));
-
- ideMessenger.responses["getWorkspaceDirs"] = [EDIT_WORKSPACE_DIR];
- ideMessenger.responses["tools/evaluatePolicy"] = {
- policy: "allowedWithoutPermission",
- };
-
- // Mock context/getSymbolsForFiles to prevent errors during streaming
- ideMessenger.responses["context/getSymbolsForFiles"] = {};
-
- const messengerPostSpy = vi.spyOn(ideMessenger, "post");
- const messengerRequestSpy = vi.spyOn(ideMessenger, "request");
-
- // Instead of using addAndSelectMockLlm (which relies on events that might be failing),
- // directly dispatch the config update to set the selected model
- const currentConfig = store.getState().config.config;
- store.dispatch(
- updateConfig({
- ...currentConfig,
- selectedModelByRole: {
- ...currentConfig.selectedModelByRole,
- chat: {
- model: "mock",
- provider: "mock",
- title: "Mock LLM",
- underlyingProviderName: "mock",
- },
- },
- modelsByRole: {
- ...currentConfig.modelsByRole,
- chat: [
- ...(currentConfig.modelsByRole.chat || []),
- {
- model: "mock",
- provider: "mock",
- title: "Mock LLM",
- underlyingProviderName: "mock",
- },
- ],
- },
- }),
- );
-
- // Enable automatic edit and yolo mode
- store.dispatch(
- setToolPolicy({
- toolName: BuiltInToolNames.EditExistingFile,
- policy: "allowedWithoutPermission",
- }),
- );
- triggerConfigUpdate({
- store,
- ideMessenger,
- editConfig: (current) => {
- current.ui = {
- ...current.ui,
- autoAcceptEditToolDiffs: true, // Enable auto-accept for edit tool diffs
- };
- return current;
- },
- });
- expect(store.getState().config.config.ui?.autoAcceptEditToolDiffs).toBe(true);
-
- // Send the input that will respond with an edit tool call
- await sendInputWithMockedResponse(
- ideMessenger,
- "Edit this file",
- EDIT_MESSAGES,
- );
-
- // Wait for streaming to complete and tool calls to be processed
- await act(async () => {
- await new Promise((resolve) => setTimeout(resolve, 1000));
- });
-
- // Toggle the codeblock and make sure the changes show
- const toggleCodeblockChevron = await getElementByTestId("toggle-codeblock");
-
- await user.click(toggleCodeblockChevron);
- await getElementByText(EDIT_CHANGES);
-
- // Make sure there's no pending tool call
- await verifyNotPresentByTestId(
- generateToolCallButtonTestId("accept", EDIT_TOOL_CALL_ID),
- );
- // Tool call, check that applyToFile was called for edit
- await waitFor(() => {
- expect(messengerRequestSpy).toHaveBeenCalledWith("applyToFile", {
- streamId: expect.any(String),
- filepath: EDIT_FILE_URI,
- text: EDIT_CHANGES,
- toolCallId: EDIT_TOOL_CALL_ID,
- });
- });
-
- // Extract stream ID and initiate mock streaming
- const streamId = messengerRequestSpy.mock.calls.find(
- (call) => call[0] === "applyToFile",
- )?.[1]?.streamId;
- expect(streamId).toBeDefined();
-
- ideMessenger.mockMessageToWebview("updateApplyState", {
- status: "streaming",
- streamId,
- toolCallId: EDIT_TOOL_CALL_ID,
- filepath: EDIT_FILE_URI,
- });
-
- // Mid stream, should show applying in notch
- await getElementByTestId("notch-applying-text");
- await getElementByTestId("notch-applying-cancel-button");
-
- // Close the stream
- ideMessenger.mockMessageToWebview("updateApplyState", {
- status: "done",
- streamId,
- toolCallId: EDIT_TOOL_CALL_ID,
- filepath: EDIT_FILE_URI,
- });
-
- // Set the chat response text before the auto-accept triggers
- ideMessenger.setChatResponseText(POST_EDIT_RESPONSE);
-
- await waitFor(() => {
- expect(messengerPostSpy).toHaveBeenCalledWith("acceptDiff", {
- streamId,
- filepath: EDIT_FILE_URI,
- });
- });
-
- // Close the stream, ensure response is shown and diff buttons are not present
- ideMessenger.mockMessageToWebview("updateApplyState", {
- status: "closed",
- streamId,
- toolCallId: EDIT_TOOL_CALL_ID,
- filepath: EDIT_FILE_URI,
- });
-
- // Allow time for the auto-streaming to complete
- await new Promise((resolve) => setTimeout(resolve, 1000));
-
- await verifyNotPresentByTestId("edit-accept-button");
- await verifyNotPresentByTestId("edit-reject-button");
-
- // Try to manually trigger the streaming by checking if the response is set
- await act(async () => {
- await new Promise((resolve) => setTimeout(resolve, 500));
- });
-
- // TODO: Fix this test - the POST_EDIT_RESPONSE is not being displayed
- // await waitFor(() => getElementByText(POST_EDIT_RESPONSE), {
- // timeout: 8000,
- // });
-});
diff --git a/gui/src/redux/thunks/evaluateToolPolicies.ts b/gui/src/redux/thunks/evaluateToolPolicies.ts
index 37c009210a2..d25cad6797e 100644
--- a/gui/src/redux/thunks/evaluateToolPolicies.ts
+++ b/gui/src/redux/thunks/evaluateToolPolicies.ts
@@ -21,13 +21,9 @@ async function evaluateToolPolicy(
activeTools: Tool[],
toolCallState: ToolCallState,
toolPolicies: ToolPolicies,
- autoAcceptEditToolDiffs: boolean | undefined,
): Promise {
- // allow edit tool calls without permission if auto-accept is enabled
- if (
- isEditTool(toolCallState.toolCall.function.name) &&
- autoAcceptEditToolDiffs
- ) {
+ // allow edit tool calls without permission
+ if (isEditTool(toolCallState.toolCall.function.name)) {
return { policy: "allowedWithoutPermission", toolCallState };
}
@@ -83,7 +79,6 @@ export async function evaluateToolPolicies(
activeTools: Tool[],
generatedToolCalls: ToolCallState[],
toolPolicies: ToolPolicies,
- autoAcceptEditToolDiffs: boolean | undefined,
): Promise {
// Check if ALL tool calls are auto-approved using dynamic evaluation
const policyResults = await Promise.all(
@@ -93,7 +88,6 @@ export async function evaluateToolPolicies(
activeTools,
toolCallState,
toolPolicies,
- autoAcceptEditToolDiffs,
),
),
);
diff --git a/gui/src/redux/thunks/handleApplyStateUpdate.test.ts b/gui/src/redux/thunks/handleApplyStateUpdate.test.ts
index 46ae54c35fc..2e426b7d7c1 100644
--- a/gui/src/redux/thunks/handleApplyStateUpdate.test.ts
+++ b/gui/src/redux/thunks/handleApplyStateUpdate.test.ts
@@ -161,61 +161,6 @@ describe("handleApplyStateUpdate", () => {
expect.objectContaining({ type: "session/updateApplyState" }),
);
});
-
- it("should auto-accept diffs when configured and status is done", async () => {
- mockGetState.mockReturnValue({
- config: {
- config: {
- ui: {
- autoAcceptEditToolDiffs: true,
- },
- },
- },
- session: { history: [] },
- });
-
- const applyState: ApplyState = {
- streamId: "chat-stream",
- toolCallId: "test-tool-call",
- status: "done",
- filepath: "test.txt",
- numDiffs: 1,
- };
-
- const thunk = handleApplyStateUpdate(applyState);
- await thunk(mockDispatch, mockGetState, mockExtra);
-
- expect(mockExtra.ideMessenger.post).toHaveBeenCalledWith("acceptDiff", {
- streamId: "chat-stream",
- filepath: "test.txt",
- });
- });
-
- it("should not auto-accept when config is disabled", async () => {
- mockGetState.mockReturnValue({
- config: {
- config: {
- ui: {
- autoAcceptEditToolDiffs: false,
- },
- },
- },
- session: { history: [] },
- });
-
- const applyState: ApplyState = {
- streamId: "chat-stream",
- toolCallId: "test-tool-call",
- status: "done",
- filepath: "test.txt",
- numDiffs: 1,
- };
-
- const thunk = handleApplyStateUpdate(applyState);
- await thunk(mockDispatch, mockGetState, mockExtra);
-
- expect(mockExtra.ideMessenger.post).not.toHaveBeenCalled();
- });
});
describe("closed status handling", () => {
diff --git a/gui/src/redux/thunks/handleApplyStateUpdate.ts b/gui/src/redux/thunks/handleApplyStateUpdate.ts
index 1cc2c35d07d..bbb0b520697 100644
--- a/gui/src/redux/thunks/handleApplyStateUpdate.ts
+++ b/gui/src/redux/thunks/handleApplyStateUpdate.ts
@@ -44,15 +44,6 @@ export const handleApplyStateUpdate = createAsyncThunk<
// Handle apply status updates - use toolCallId from event payload
if (applyState.toolCallId) {
- if (
- applyState.status === "done" &&
- getState().config.config?.ui?.autoAcceptEditToolDiffs
- ) {
- extra.ideMessenger.post("acceptDiff", {
- streamId: applyState.streamId,
- filepath: applyState.filepath,
- });
- }
if (applyState.status === "closed") {
// Find the tool call to check if it was canceled
const toolCallState = findToolCallById(
diff --git a/gui/src/redux/thunks/streamNormalInput.ts b/gui/src/redux/thunks/streamNormalInput.ts
index 226146e072a..96cd2bb16f3 100644
--- a/gui/src/redux/thunks/streamNormalInput.ts
+++ b/gui/src/redux/thunks/streamNormalInput.ts
@@ -317,7 +317,6 @@ export const streamNormalInput = createAsyncThunk<
activeTools,
generatedCalls3,
toolPolicies,
- state3.config.config.ui?.autoAcceptEditToolDiffs,
);
const anyRequireApproval = policies.find(
({ policy }) => policy === "allowedWithPermission",