mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-05 08:10:14 +00:00
feat: add re-read after edit experiment
Implements issue #8927 - Add option to suggest reviewing changes after file edits. - Added RE_READ_AFTER_EDIT experiment configuration - Updated all file editing tools to suggest review when experiment is enabled - Added UI setting with English translation - Added tests for the new experiment When enabled, the AI will suggest using the read_file tool to review changes after editing files, helping catch errors that might be introduced during editing.
This commit is contained in:
parent
59ab1f3f3c
commit
77b0278be3
9 changed files with 92 additions and 6 deletions
|
|
@ -12,6 +12,7 @@ export const experimentIds = [
|
|||
"preventFocusDisruption",
|
||||
"imageGeneration",
|
||||
"runSlashCommand",
|
||||
"reReadAfterEdit",
|
||||
] as const
|
||||
|
||||
export const experimentIdsSchema = z.enum(experimentIds)
|
||||
|
|
@ -28,6 +29,7 @@ export const experimentsSchema = z.object({
|
|||
preventFocusDisruption: z.boolean().optional(),
|
||||
imageGeneration: z.boolean().optional(),
|
||||
runSlashCommand: z.boolean().optional(),
|
||||
reReadAfterEdit: z.boolean().optional(),
|
||||
})
|
||||
|
||||
export type Experiments = z.infer<typeof experimentsSchema>
|
||||
|
|
|
|||
|
|
@ -238,10 +238,20 @@ export async function applyDiffToolLegacy(
|
|||
? "\n<notice>Making multiple related changes in a single apply_diff is more efficient. If other changes are needed in this file, please include them as additional SEARCH/REPLACE blocks.</notice>"
|
||||
: ""
|
||||
|
||||
// Check if RE_READ_AFTER_EDIT experiment is enabled
|
||||
const isReReadAfterEditEnabled = experiments.isEnabled(
|
||||
state?.experiments ?? {},
|
||||
EXPERIMENT_IDS.RE_READ_AFTER_EDIT,
|
||||
)
|
||||
|
||||
const reReadSuggestion = isReReadAfterEditEnabled
|
||||
? `\n\n<review_suggestion>The file has been edited. Consider using the read_file tool to review the changes and ensure they are correct and complete.</review_suggestion>`
|
||||
: ""
|
||||
|
||||
if (partFailHint) {
|
||||
pushToolResult(partFailHint + message + singleBlockNotice)
|
||||
pushToolResult(partFailHint + message + singleBlockNotice + reReadSuggestion)
|
||||
} else {
|
||||
pushToolResult(message + singleBlockNotice)
|
||||
pushToolResult(message + singleBlockNotice + reReadSuggestion)
|
||||
}
|
||||
|
||||
await cline.diffViewProvider.reset()
|
||||
|
|
|
|||
|
|
@ -184,7 +184,17 @@ export async function insertContentTool(
|
|||
// Get the formatted response message
|
||||
const message = await cline.diffViewProvider.pushToolWriteResult(cline, cline.cwd, !fileExists)
|
||||
|
||||
pushToolResult(message)
|
||||
// Check if RE_READ_AFTER_EDIT experiment is enabled
|
||||
const isReReadAfterEditEnabled = experiments.isEnabled(
|
||||
state?.experiments ?? {},
|
||||
EXPERIMENT_IDS.RE_READ_AFTER_EDIT,
|
||||
)
|
||||
|
||||
const reReadSuggestion = isReReadAfterEditEnabled
|
||||
? `\n\n<review_suggestion>Content has been inserted into the file. Consider using the read_file tool to review the changes and ensure they are correct and complete.</review_suggestion>`
|
||||
: ""
|
||||
|
||||
pushToolResult(message + reReadSuggestion)
|
||||
|
||||
await cline.diffViewProvider.reset()
|
||||
|
||||
|
|
|
|||
|
|
@ -676,8 +676,23 @@ ${errorDetails ? `\nTechnical details:\n${errorDetails}\n` : ""}
|
|||
? "\n<notice>Making multiple related changes in a single apply_diff is more efficient. If other changes are needed in this file, please include them as additional SEARCH/REPLACE blocks.</notice>"
|
||||
: ""
|
||||
|
||||
// Check if RE_READ_AFTER_EDIT experiment is enabled
|
||||
const provider = cline.providerRef.deref()
|
||||
const state = await provider?.getState()
|
||||
const isReReadAfterEditEnabled = experiments.isEnabled(
|
||||
state?.experiments ?? {},
|
||||
EXPERIMENT_IDS.RE_READ_AFTER_EDIT,
|
||||
)
|
||||
|
||||
// Count how many files were successfully edited
|
||||
const editedFiles = operationResults.filter((op) => op.status === "approved").length
|
||||
const reReadSuggestion =
|
||||
isReReadAfterEditEnabled && editedFiles > 0
|
||||
? `\n\n<review_suggestion>${editedFiles === 1 ? "The file has" : `${editedFiles} files have`} been edited. Consider using the read_file tool to review the changes and ensure they are correct and complete.</review_suggestion>`
|
||||
: ""
|
||||
|
||||
// Push the final result combining all operation results
|
||||
pushToolResult(results.join("\n\n") + singleBlockNotice)
|
||||
pushToolResult(results.join("\n\n") + singleBlockNotice + reReadSuggestion)
|
||||
cline.processQueuedMessages()
|
||||
return
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -258,7 +258,17 @@ export async function searchAndReplaceTool(
|
|||
false, // Always false for search_and_replace
|
||||
)
|
||||
|
||||
pushToolResult(message)
|
||||
// Check if RE_READ_AFTER_EDIT experiment is enabled
|
||||
const isReReadAfterEditEnabled = experiments.isEnabled(
|
||||
state?.experiments ?? {},
|
||||
EXPERIMENT_IDS.RE_READ_AFTER_EDIT,
|
||||
)
|
||||
|
||||
const reReadSuggestion = isReReadAfterEditEnabled
|
||||
? `\n\n<review_suggestion>The file has been modified via search and replace. Consider using the read_file tool to review the changes and ensure they are correct and complete.</review_suggestion>`
|
||||
: ""
|
||||
|
||||
pushToolResult(message + reReadSuggestion)
|
||||
|
||||
// Record successful tool usage and cleanup
|
||||
cline.recordToolUsage("search_and_replace")
|
||||
|
|
|
|||
|
|
@ -304,7 +304,17 @@ export async function writeToFileTool(
|
|||
// Get the formatted response message
|
||||
const message = await cline.diffViewProvider.pushToolWriteResult(cline, cline.cwd, !fileExists)
|
||||
|
||||
pushToolResult(message)
|
||||
// Check if RE_READ_AFTER_EDIT experiment is enabled
|
||||
const isReReadAfterEditEnabled = experiments.isEnabled(
|
||||
state?.experiments ?? {},
|
||||
EXPERIMENT_IDS.RE_READ_AFTER_EDIT,
|
||||
)
|
||||
|
||||
const reReadSuggestion = isReReadAfterEditEnabled
|
||||
? `\n\n<review_suggestion>The file has been ${fileExists ? "edited" : "created"}. Consider using the read_file tool to review the ${fileExists ? "changes" : "content"} and ensure ${fileExists ? "they are" : "it is"} correct and complete.</review_suggestion>`
|
||||
: ""
|
||||
|
||||
pushToolResult(message + reReadSuggestion)
|
||||
|
||||
await cline.diffViewProvider.reset()
|
||||
|
||||
|
|
|
|||
23
src/shared/__tests__/experiments-reReadAfterEdit.spec.ts
Normal file
23
src/shared/__tests__/experiments-reReadAfterEdit.spec.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { describe, it, expect } from "vitest"
|
||||
import { EXPERIMENT_IDS, experiments, experimentDefault } from "../experiments"
|
||||
|
||||
describe("RE_READ_AFTER_EDIT experiment", () => {
|
||||
it("should include RE_READ_AFTER_EDIT in EXPERIMENT_IDS", () => {
|
||||
expect(EXPERIMENT_IDS.RE_READ_AFTER_EDIT).toBe("reReadAfterEdit")
|
||||
})
|
||||
|
||||
it("should have RE_READ_AFTER_EDIT in default configuration", () => {
|
||||
expect(experimentDefault.reReadAfterEdit).toBe(false)
|
||||
})
|
||||
|
||||
it("should correctly check if RE_READ_AFTER_EDIT is enabled", () => {
|
||||
const disabledConfig = { reReadAfterEdit: false }
|
||||
expect(experiments.isEnabled(disabledConfig, EXPERIMENT_IDS.RE_READ_AFTER_EDIT)).toBe(false)
|
||||
|
||||
const enabledConfig = { reReadAfterEdit: true }
|
||||
expect(experiments.isEnabled(enabledConfig, EXPERIMENT_IDS.RE_READ_AFTER_EDIT)).toBe(true)
|
||||
|
||||
const emptyConfig = {}
|
||||
expect(experiments.isEnabled(emptyConfig, EXPERIMENT_IDS.RE_READ_AFTER_EDIT)).toBe(false)
|
||||
})
|
||||
})
|
||||
|
|
@ -6,6 +6,7 @@ export const EXPERIMENT_IDS = {
|
|||
PREVENT_FOCUS_DISRUPTION: "preventFocusDisruption",
|
||||
IMAGE_GENERATION: "imageGeneration",
|
||||
RUN_SLASH_COMMAND: "runSlashCommand",
|
||||
RE_READ_AFTER_EDIT: "reReadAfterEdit",
|
||||
} as const satisfies Record<string, ExperimentId>
|
||||
|
||||
type _AssertExperimentIds = AssertEqual<Equals<ExperimentId, Values<typeof EXPERIMENT_IDS>>>
|
||||
|
|
@ -22,6 +23,7 @@ export const experimentConfigsMap: Record<ExperimentKey, ExperimentConfig> = {
|
|||
PREVENT_FOCUS_DISRUPTION: { enabled: false },
|
||||
IMAGE_GENERATION: { enabled: false },
|
||||
RUN_SLASH_COMMAND: { enabled: false },
|
||||
RE_READ_AFTER_EDIT: { enabled: false },
|
||||
}
|
||||
|
||||
export const experimentDefault = Object.fromEntries(
|
||||
|
|
|
|||
|
|
@ -775,6 +775,10 @@
|
|||
"RUN_SLASH_COMMAND": {
|
||||
"name": "Enable model-initiated slash commands",
|
||||
"description": "When enabled, Roo can run your slash commands to execute workflows."
|
||||
},
|
||||
"RE_READ_AFTER_EDIT": {
|
||||
"name": "Suggest review after file edits",
|
||||
"description": "When enabled, Roo will suggest reviewing changes after editing files. This helps catch errors that might be introduced during editing by prompting to review the changes."
|
||||
}
|
||||
},
|
||||
"promptCaching": {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue