Simplify Roo Code's quick actions (#3024)

* Quick fix actions

* Remove unused keys

* Simplify more stuff

* Bring back "Explain Code"

* Bring "Improve Code" back

* Add back "Improve"

* This is too flakey for now
This commit is contained in:
Chris Estreich 2025-04-29 08:07:24 -07:00 committed by GitHub
parent 60270d1064
commit d07e60575b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 106 additions and 251 deletions

View file

@ -4,7 +4,7 @@ import type { ClineMessage } from "../../../src/exports/roo-code"
import { sleep, waitFor, waitUntilCompleted } from "./utils"
suite("Roo Code Subtasks", () => {
suite.skip("Roo Code Subtasks", () => {
test("Should handle subtask cancellation and resumption correctly", async () => {
const api = globalThis.api

View file

@ -160,16 +160,6 @@
"title": "%command.terminal.explainCommand.title%",
"category": "Terminal"
},
{
"command": "roo-cline.terminalFixCommandInCurrentTask",
"title": "%command.terminal.fixCommandInCurrentTask.title%",
"category": "Terminal"
},
{
"command": "roo-cline.terminalExplainCommandInCurrentTask",
"title": "%command.terminal.explainCommandInCurrentTask.title%",
"category": "Terminal"
},
{
"command": "roo-cline.setCustomStoragePath",
"title": "%command.setCustomStoragePath.title%",
@ -202,13 +192,9 @@
"command": "roo-cline.explainCode",
"group": "1_actions@2"
},
{
"command": "roo-cline.fixCode",
"group": "1_actions@3"
},
{
"command": "roo-cline.improveCode",
"group": "1_actions@4"
"group": "1_actions@3"
}
],
"terminal/context": [
@ -229,14 +215,6 @@
{
"command": "roo-cline.terminalExplainCommand",
"group": "1_actions@3"
},
{
"command": "roo-cline.terminalFixCommandInCurrentTask",
"group": "1_actions@5"
},
{
"command": "roo-cline.terminalExplainCommandInCurrentTask",
"group": "1_actions@6"
}
],
"view/title": [

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Afegir Contingut del Terminal al Context",
"command.terminal.fixCommand.title": "Corregir Aquesta Ordre",
"command.terminal.explainCommand.title": "Explicar Aquesta Ordre",
"command.terminal.fixCommandInCurrentTask.title": "Corregir Aquesta Ordre (Tasca Actual)",
"command.terminal.explainCommandInCurrentTask.title": "Explicar Aquesta Ordre (Tasca Actual)",
"command.acceptInput.title": "Acceptar Entrada/Suggeriment",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Terminal-Inhalt zum Kontext Hinzufügen",
"command.terminal.fixCommand.title": "Diesen Befehl Reparieren",
"command.terminal.explainCommand.title": "Diesen Befehl Erklären",
"command.terminal.fixCommandInCurrentTask.title": "Diesen Befehl Reparieren (Aktuelle Aufgabe)",
"command.terminal.explainCommandInCurrentTask.title": "Diesen Befehl Erklären (Aktuelle Aufgabe)",
"command.acceptInput.title": "Eingabe/Vorschlag Akzeptieren",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Añadir Contenido de Terminal al Contexto",
"command.terminal.fixCommand.title": "Corregir Este Comando",
"command.terminal.explainCommand.title": "Explicar Este Comando",
"command.terminal.fixCommandInCurrentTask.title": "Corregir Este Comando (Tarea Actual)",
"command.terminal.explainCommandInCurrentTask.title": "Explicar Este Comando (Tarea Actual)",
"command.acceptInput.title": "Aceptar Entrada/Sugerencia",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Ajouter le Contenu du Terminal au Contexte",
"command.terminal.fixCommand.title": "Corriger cette Commande",
"command.terminal.explainCommand.title": "Expliquer cette Commande",
"command.terminal.fixCommandInCurrentTask.title": "Corriger cette Commande (Tâche Actuelle)",
"command.terminal.explainCommandInCurrentTask.title": "Expliquer cette Commande (Tâche Actuelle)",
"command.acceptInput.title": "Accepter l'Entrée/Suggestion",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "टर्मिनल सामग्री को संदर्भ में जोड़ें",
"command.terminal.fixCommand.title": "यह कमांड ठीक करें",
"command.terminal.explainCommand.title": "यह कमांड समझाएं",
"command.terminal.fixCommandInCurrentTask.title": "यह कमांड ठीक करें (वर्तमान कार्य)",
"command.terminal.explainCommandInCurrentTask.title": "यह कमांड समझाएं (वर्तमान कार्य)",
"command.acceptInput.title": "इनपुट/सुझाव स्वीकारें",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Aggiungi Contenuto del Terminale al Contesto",
"command.terminal.fixCommand.title": "Correggi Questo Comando",
"command.terminal.explainCommand.title": "Spiega Questo Comando",
"command.terminal.fixCommandInCurrentTask.title": "Correggi Questo Comando (Task Corrente)",
"command.terminal.explainCommandInCurrentTask.title": "Spiega Questo Comando (Task Corrente)",
"command.acceptInput.title": "Accetta Input/Suggerimento",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -21,8 +21,6 @@
"command.terminal.addToContext.title": "ターミナルの内容をコンテキストに追加",
"command.terminal.fixCommand.title": "このコマンドを修正",
"command.terminal.explainCommand.title": "このコマンドを説明",
"command.terminal.fixCommandInCurrentTask.title": "このコマンドを修正(現在のタスク)",
"command.terminal.explainCommandInCurrentTask.title": "このコマンドを説明(現在のタスク)",
"command.acceptInput.title": "入力/提案を承認",
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "'常に実行操作を承認する'が有効な場合に自動実行できるコマンド",

View file

@ -21,8 +21,6 @@
"command.terminal.addToContext.title": "Add Terminal Content to Context",
"command.terminal.fixCommand.title": "Fix This Command",
"command.terminal.explainCommand.title": "Explain This Command",
"command.terminal.fixCommandInCurrentTask.title": "Fix This Command (Current Task)",
"command.terminal.explainCommandInCurrentTask.title": "Explain This Command (Current Task)",
"command.acceptInput.title": "Accept Input/Suggestion",
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Commands that can be auto-executed when 'Always approve execute operations' is enabled",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "터미널 내용을 컨텍스트에 추가",
"command.terminal.fixCommand.title": "이 명령어 수정",
"command.terminal.explainCommand.title": "이 명령어 설명",
"command.terminal.fixCommandInCurrentTask.title": "이 명령어 수정 (현재 작업)",
"command.terminal.explainCommandInCurrentTask.title": "이 명령어 설명 (현재 작업)",
"command.acceptInput.title": "입력/제안 수락",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Dodaj Zawartość Terminala do Kontekstu",
"command.terminal.fixCommand.title": "Napraw tę Komendę",
"command.terminal.explainCommand.title": "Wyjaśnij tę Komendę",
"command.terminal.fixCommandInCurrentTask.title": "Napraw tę Komendę (Bieżące Zadanie)",
"command.terminal.explainCommandInCurrentTask.title": "Wyjaśnij tę Komendę (Bieżące Zadanie)",
"command.acceptInput.title": "Akceptuj Wprowadzanie/Sugestię",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Adicionar Conteúdo do Terminal ao Contexto",
"command.terminal.fixCommand.title": "Corrigir Este Comando",
"command.terminal.explainCommand.title": "Explicar Este Comando",
"command.terminal.fixCommandInCurrentTask.title": "Corrigir Este Comando (Tarefa Atual)",
"command.terminal.explainCommandInCurrentTask.title": "Explicar Este Comando (Tarefa Atual)",
"command.acceptInput.title": "Aceitar Entrada/Sugestão",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -21,8 +21,6 @@
"command.terminal.addToContext.title": "Добавить содержимое терминала в контекст",
"command.terminal.fixCommand.title": "Исправить эту команду",
"command.terminal.explainCommand.title": "Объяснить эту команду",
"command.terminal.fixCommandInCurrentTask.title": "Исправить эту команду (текущая задача)",
"command.terminal.explainCommandInCurrentTask.title": "Объяснить эту команду (текущая задача)",
"command.acceptInput.title": "Принять ввод/предложение",
"configuration.title": "Roo Code",
"commands.allowedCommands.description": "Команды, которые могут быть автоматически выполнены, когда включена опция 'Всегда подтверждать операции выполнения'",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Terminal İçeriğini Bağlama Ekle",
"command.terminal.fixCommand.title": "Bu Komutu Düzelt",
"command.terminal.explainCommand.title": "Bu Komutu Açıkla",
"command.terminal.fixCommandInCurrentTask.title": "Bu Komutu Düzelt (Mevcut Görev)",
"command.terminal.explainCommandInCurrentTask.title": "Bu Komutu Açıkla (Mevcut Görev)",
"command.acceptInput.title": "Girişi/Öneriyi Kabul Et",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "Thêm Nội Dung Terminal vào Ngữ Cảnh",
"command.terminal.fixCommand.title": "Sửa Lệnh Này",
"command.terminal.explainCommand.title": "Giải Thích Lệnh Này",
"command.terminal.fixCommandInCurrentTask.title": "Sửa Lệnh Này (Tác Vụ Hiện Tại)",
"command.terminal.explainCommandInCurrentTask.title": "Giải Thích Lệnh Này (Tác Vụ Hiện Tại)",
"command.acceptInput.title": "Chấp Nhận Đầu Vào/Gợi Ý",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "将终端内容添加到上下文",
"command.terminal.fixCommand.title": "修复此命令",
"command.terminal.explainCommand.title": "解释此命令",
"command.terminal.fixCommandInCurrentTask.title": "修复此命令(当前任务)",
"command.terminal.explainCommandInCurrentTask.title": "解释此命令(当前任务)",
"command.acceptInput.title": "接受输入/建议",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -12,8 +12,6 @@
"command.terminal.addToContext.title": "將終端內容添加到上下文",
"command.terminal.fixCommand.title": "修復此命令",
"command.terminal.explainCommand.title": "解釋此命令",
"command.terminal.fixCommandInCurrentTask.title": "修復此命令(當前任務)",
"command.terminal.explainCommandInCurrentTask.title": "解釋此命令(當前任務)",
"command.acceptInput.title": "接受輸入/建議",
"views.activitybar.title": "Roo Code",
"views.contextMenu.label": "Roo Code",

View file

@ -1,22 +1,23 @@
import * as vscode from "vscode"
import { COMMAND_IDS } from "../core/CodeActionProvider"
import { ClineProvider } from "../core/webview/ClineProvider"
import { t } from "../i18n"
export const handleNewTask = async (params: { prompt?: string } | null | undefined) => {
let prompt = params?.prompt
if (!prompt) {
prompt = await vscode.window.showInputBox({
prompt: t("common:input.task_prompt"),
placeHolder: t("common:input.task_placeholder"),
})
}
if (!prompt) {
await vscode.commands.executeCommand("roo-cline.SidebarProvider.focus")
return
}
await ClineProvider.handleCodeAction(COMMAND_IDS.NEW_TASK, "NEW_TASK", {
userInput: prompt,
})
await ClineProvider.handleCodeAction(COMMAND_IDS.NEW_TASK, "NEW_TASK", { userInput: prompt })
}

View file

@ -1,55 +1,21 @@
import * as vscode from "vscode"
import { ACTION_NAMES, COMMAND_IDS } from "../core/CodeActionProvider"
import { type CodeActionName, type CodeActionId, COMMAND_IDS } from "../core/CodeActionProvider"
import { EditorUtils } from "../core/EditorUtils"
import { ClineProvider } from "../core/webview/ClineProvider"
export const registerCodeActions = (context: vscode.ExtensionContext) => {
registerCodeActionPair(
context,
COMMAND_IDS.EXPLAIN,
"EXPLAIN",
"What would you like Roo to explain?",
"E.g. How does the error handling work?",
)
registerCodeActionPair(
context,
COMMAND_IDS.FIX,
"FIX",
"What would you like Roo to fix?",
"E.g. Maintain backward compatibility",
)
registerCodeActionPair(
context,
COMMAND_IDS.IMPROVE,
"IMPROVE",
"What would you like Roo to improve?",
"E.g. Focus on performance optimization",
)
registerCodeAction(context, COMMAND_IDS.EXPLAIN, "EXPLAIN")
registerCodeAction(context, COMMAND_IDS.FIX, "FIX")
registerCodeAction(context, COMMAND_IDS.IMPROVE, "IMPROVE")
registerCodeAction(context, COMMAND_IDS.ADD_TO_CONTEXT, "ADD_TO_CONTEXT")
}
const registerCodeAction = (
context: vscode.ExtensionContext,
command: string,
promptType: keyof typeof ACTION_NAMES,
inputPrompt?: string,
inputPlaceholder?: string,
) => {
const registerCodeAction = (context: vscode.ExtensionContext, command: CodeActionId, promptType: CodeActionName) => {
let userInput: string | undefined
context.subscriptions.push(
vscode.commands.registerCommand(command, async (...args: any[]) => {
if (inputPrompt) {
userInput = await vscode.window.showInputBox({
prompt: inputPrompt,
placeHolder: inputPlaceholder,
})
}
// Handle both code action and direct command cases.
let filePath: string
let selectedText: string
@ -63,7 +29,11 @@ const registerCodeAction = (
} else {
// Called directly from command palette.
const context = EditorUtils.getEditorContext()
if (!context) return
if (!context) {
return
}
;({ filePath, selectedText, startLine, endLine, diagnostics } = context)
}
@ -79,17 +49,3 @@ const registerCodeAction = (
}),
)
}
const registerCodeActionPair = (
context: vscode.ExtensionContext,
baseCommand: string,
promptType: keyof typeof ACTION_NAMES,
inputPrompt?: string,
inputPlaceholder?: string,
) => {
// Register new task version.
registerCodeAction(context, baseCommand, promptType, inputPrompt, inputPlaceholder)
// Register current task version.
registerCodeAction(context, `${baseCommand}InCurrentTask`, promptType, inputPrompt, inputPlaceholder)
}

View file

@ -66,31 +66,51 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
"roo-cline.activationCompleted": () => {},
"roo-cline.plusButtonClicked": async () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) return
if (!visibleProvider) {
return
}
await visibleProvider.removeClineFromStack()
await visibleProvider.postStateToWebview()
await visibleProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
},
"roo-cline.mcpButtonClicked": () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) return
if (!visibleProvider) {
return
}
visibleProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })
},
"roo-cline.promptsButtonClicked": () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) return
if (!visibleProvider) {
return
}
visibleProvider.postMessageToWebview({ type: "action", action: "promptsButtonClicked" })
},
"roo-cline.popoutButtonClicked": () => openClineInNewTab({ context, outputChannel }),
"roo-cline.openInNewTab": () => openClineInNewTab({ context, outputChannel }),
"roo-cline.settingsButtonClicked": () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) return
if (!visibleProvider) {
return
}
visibleProvider.postMessageToWebview({ type: "action", action: "settingsButtonClicked" })
},
"roo-cline.historyButtonClicked": () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) return
if (!visibleProvider) {
return
}
visibleProvider.postMessageToWebview({ type: "action", action: "historyButtonClicked" })
},
"roo-cline.helpButtonClicked": () => {
@ -118,6 +138,7 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
"roo-cline.focusInput": async () => {
try {
const panel = getPanel()
if (!panel) {
await vscode.commands.executeCommand("workbench.view.extension.roo-cline-ActivityBar")
} else if (panel === tabPanel) {
@ -132,7 +153,11 @@ const getCommandsMap = ({ context, outputChannel, provider }: RegisterCommandOpt
},
"roo.acceptInput": () => {
const visibleProvider = getVisibleProviderOrLog(outputChannel)
if (!visibleProvider) return
if (!visibleProvider) {
return
}
visibleProvider.postMessageToWebview({ type: "acceptInput" })
},
}

View file

@ -6,33 +6,24 @@ import { t } from "../i18n"
const TERMINAL_COMMAND_IDS = {
ADD_TO_CONTEXT: "roo-cline.terminalAddToContext",
FIX: "roo-cline.terminalFixCommand",
FIX_IN_CURRENT_TASK: "roo-cline.terminalFixCommandInCurrentTask",
EXPLAIN: "roo-cline.terminalExplainCommand",
EXPLAIN_IN_CURRENT_TASK: "roo-cline.terminalExplainCommandInCurrentTask",
} as const
export const registerTerminalActions = (context: vscode.ExtensionContext) => {
registerTerminalAction(context, TERMINAL_COMMAND_IDS.ADD_TO_CONTEXT, "TERMINAL_ADD_TO_CONTEXT")
registerTerminalActionPair(context, TERMINAL_COMMAND_IDS.FIX, "TERMINAL_FIX", "What would you like Roo to fix?")
registerTerminalActionPair(
context,
TERMINAL_COMMAND_IDS.EXPLAIN,
"TERMINAL_EXPLAIN",
"What would you like Roo to explain?",
)
registerTerminalAction(context, TERMINAL_COMMAND_IDS.FIX, "TERMINAL_FIX")
registerTerminalAction(context, TERMINAL_COMMAND_IDS.EXPLAIN, "TERMINAL_EXPLAIN")
}
const registerTerminalAction = (
context: vscode.ExtensionContext,
command: string,
promptType: "TERMINAL_ADD_TO_CONTEXT" | "TERMINAL_FIX" | "TERMINAL_EXPLAIN",
inputPrompt?: string,
) => {
context.subscriptions.push(
vscode.commands.registerCommand(command, async (args: any) => {
let content = args.selection
if (!content || content === "") {
content = await Terminal.getTerminalContents(promptType === "TERMINAL_ADD_TO_CONTEXT" ? -1 : 1)
}
@ -42,30 +33,9 @@ const registerTerminalAction = (
return
}
const params: Record<string, any> = {
await ClineProvider.handleTerminalAction(command, promptType, {
terminalContent: content,
}
if (inputPrompt) {
params.userInput =
(await vscode.window.showInputBox({
prompt: inputPrompt,
})) ?? ""
}
await ClineProvider.handleTerminalAction(command, promptType, params)
})
}),
)
}
const registerTerminalActionPair = (
context: vscode.ExtensionContext,
baseCommand: string,
promptType: "TERMINAL_ADD_TO_CONTEXT" | "TERMINAL_FIX" | "TERMINAL_EXPLAIN",
inputPrompt?: string,
) => {
// Register new task version
registerTerminalAction(context, baseCommand, promptType, inputPrompt)
// Register current task version
registerTerminalAction(context, `${baseCommand}InCurrentTask`, promptType, inputPrompt)
}

View file

@ -1,16 +1,25 @@
import * as vscode from "vscode"
import { EditorUtils } from "./EditorUtils"
export const ACTION_NAMES = {
EXPLAIN: "Roo Code: Explain Code",
FIX: "Roo Code: Fix Code",
FIX_LOGIC: "Roo Code: Fix Logic",
IMPROVE: "Roo Code: Improve Code",
ADD_TO_CONTEXT: "Roo Code: Add to Context",
NEW_TASK: "Roo Code: New Task",
export type CodeActionName = "EXPLAIN" | "FIX" | "IMPROVE" | "ADD_TO_CONTEXT" | "NEW_TASK"
export type CodeActionId =
| "roo-cline.explainCode"
| "roo-cline.fixCode"
| "roo-cline.improveCode"
| "roo-cline.addToContext"
| "roo-cline.newTask"
export const ACTION_TITLES: Record<CodeActionName, string> = {
EXPLAIN: "Explain with Roo Code",
FIX: "Fix with Roo Code",
IMPROVE: "Improve with Roo Code",
ADD_TO_CONTEXT: "Add to Roo Code",
NEW_TASK: "New Roo Code Task",
} as const
export const COMMAND_IDS = {
export const COMMAND_IDS: Record<CodeActionName, CodeActionId> = {
EXPLAIN: "roo-cline.explainCode",
FIX: "roo-cline.fixCode",
IMPROVE: "roo-cline.improveCode",
@ -24,24 +33,17 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
vscode.CodeActionKind.RefactorRewrite,
]
private createAction(title: string, kind: vscode.CodeActionKind, command: string, args: any[]): vscode.CodeAction {
private createAction(
title: string,
kind: vscode.CodeActionKind,
command: CodeActionId,
args: any[],
): vscode.CodeAction {
const action = new vscode.CodeAction(title, kind)
action.command = { command, title, arguments: args }
return action
}
private createActionPair(
baseTitle: string,
kind: vscode.CodeActionKind,
baseCommand: string,
args: any[],
): vscode.CodeAction[] {
return [
this.createAction(`${baseTitle} in New Task`, kind, baseCommand, args),
this.createAction(`${baseTitle} in Current Task`, kind, `${baseCommand}InCurrentTask`, args),
]
}
public provideCodeActions(
document: vscode.TextDocument,
range: vscode.Range | vscode.Selection,
@ -49,6 +51,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
): vscode.ProviderResult<(vscode.CodeAction | vscode.Command)[]> {
try {
const effectiveRange = EditorUtils.getEffectiveRange(document, range)
if (!effectiveRange) {
return []
}
@ -58,7 +61,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
actions.push(
this.createAction(
ACTION_NAMES.ADD_TO_CONTEXT,
ACTION_TITLES.ADD_TO_CONTEXT,
vscode.CodeActionKind.QuickFix,
COMMAND_IDS.ADD_TO_CONTEXT,
[
@ -70,35 +73,34 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
),
)
actions.push(
...this.createActionPair(ACTION_NAMES.EXPLAIN, vscode.CodeActionKind.QuickFix, COMMAND_IDS.EXPLAIN, [
filePath,
effectiveRange.text,
effectiveRange.range.start.line + 1,
effectiveRange.range.end.line + 1,
]),
)
if (context.diagnostics.length > 0) {
const relevantDiagnostics = context.diagnostics.filter((d) =>
EditorUtils.hasIntersectingRange(effectiveRange.range, d.range),
)
if (relevantDiagnostics.length > 0) {
const diagnosticMessages = relevantDiagnostics.map(EditorUtils.createDiagnosticData)
actions.push(
...this.createActionPair(ACTION_NAMES.FIX, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
this.createAction(ACTION_TITLES.FIX, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
filePath,
effectiveRange.text,
effectiveRange.range.start.line + 1,
effectiveRange.range.end.line + 1,
diagnosticMessages,
relevantDiagnostics.map(EditorUtils.createDiagnosticData),
]),
)
}
} else {
actions.push(
...this.createActionPair(ACTION_NAMES.FIX_LOGIC, vscode.CodeActionKind.QuickFix, COMMAND_IDS.FIX, [
this.createAction(ACTION_TITLES.EXPLAIN, vscode.CodeActionKind.QuickFix, COMMAND_IDS.EXPLAIN, [
filePath,
effectiveRange.text,
effectiveRange.range.start.line + 1,
effectiveRange.range.end.line + 1,
]),
)
actions.push(
this.createAction(ACTION_TITLES.IMPROVE, vscode.CodeActionKind.QuickFix, COMMAND_IDS.IMPROVE, [
filePath,
effectiveRange.text,
effectiveRange.range.start.line + 1,
@ -107,20 +109,6 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
)
}
actions.push(
...this.createActionPair(
ACTION_NAMES.IMPROVE,
vscode.CodeActionKind.RefactorRewrite,
COMMAND_IDS.IMPROVE,
[
filePath,
effectiveRange.text,
effectiveRange.range.start.line + 1,
effectiveRange.range.end.line + 1,
],
),
)
return actions
} catch (error) {
console.error("Error providing code actions:", error)

View file

@ -2,9 +2,10 @@
import * as vscode from "vscode"
import { CodeActionProvider, ACTION_NAMES } from "../CodeActionProvider"
import { EditorUtils } from "../EditorUtils"
import { CodeActionProvider, ACTION_TITLES } from "../CodeActionProvider"
// Mock VSCode API
jest.mock("vscode", () => ({
CodeAction: jest.fn().mockImplementation((title, kind) => ({
@ -77,34 +78,22 @@ describe("CodeActionProvider", () => {
it("should provide explain, improve, fix logic, and add to context actions by default", () => {
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext)
expect(actions).toHaveLength(7) // 2 explain + 2 fix logic + 2 improve + 1 add to context
expect((actions as any)[0].title).toBe(ACTION_NAMES.ADD_TO_CONTEXT)
expect((actions as any)[1].title).toBe(`${ACTION_NAMES.EXPLAIN} in New Task`)
expect((actions as any)[2].title).toBe(`${ACTION_NAMES.EXPLAIN} in Current Task`)
expect((actions as any)[3].title).toBe(`${ACTION_NAMES.FIX_LOGIC} in New Task`)
expect((actions as any)[4].title).toBe(`${ACTION_NAMES.FIX_LOGIC} in Current Task`)
expect((actions as any)[5].title).toBe(`${ACTION_NAMES.IMPROVE} in New Task`)
expect((actions as any)[6].title).toBe(`${ACTION_NAMES.IMPROVE} in Current Task`)
expect(actions).toHaveLength(3)
expect((actions as any)[0].title).toBe(ACTION_TITLES.ADD_TO_CONTEXT)
expect((actions as any)[1].title).toBe(ACTION_TITLES.EXPLAIN)
expect((actions as any)[2].title).toBe(ACTION_TITLES.IMPROVE)
})
it("should provide fix action instead of fix logic when diagnostics exist", () => {
mockContext.diagnostics = [
{
message: "test error",
severity: vscode.DiagnosticSeverity.Error,
range: mockRange,
},
{ message: "test error", severity: vscode.DiagnosticSeverity.Error, range: mockRange },
]
const actions = provider.provideCodeActions(mockDocument, mockRange, mockContext)
expect(actions).toHaveLength(7) // 2 explain + 2 fix + 2 improve + 1 add to context
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX} in New Task`)).toBe(true)
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX} in Current Task`)).toBe(true)
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX_LOGIC} in New Task`)).toBe(false)
expect((actions as any).some((a: any) => a.title === `${ACTION_NAMES.FIX_LOGIC} in Current Task`)).toBe(
false,
)
expect(actions).toHaveLength(2)
expect((actions as any).some((a: any) => a.title === `${ACTION_TITLES.FIX}`)).toBe(true)
expect((actions as any).some((a: any) => a.title === `${ACTION_TITLES.ADD_TO_CONTEXT}`)).toBe(true)
})
it("should return empty array when no effective range", () => {

View file

@ -41,7 +41,7 @@ import { ContextProxy } from "../config/ContextProxy"
import { ProviderSettingsManager } from "../config/ProviderSettingsManager"
import { CustomModesManager } from "../config/CustomModesManager"
import { buildApiHandler } from "../../api"
import { ACTION_NAMES } from "../CodeActionProvider"
import { CodeActionName } from "../CodeActionProvider"
import { Cline, ClineOptions } from "../Cline"
import { getNonce } from "./getNonce"
import { getUri } from "./getUri"
@ -262,7 +262,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
public static async handleCodeAction(
command: string,
promptType: keyof typeof ACTION_NAMES,
promptType: CodeActionName,
params: Record<string, string | any[]>,
): Promise<void> {
// Capture telemetry for code action usage
@ -276,20 +276,11 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
const { customSupportPrompts } = await visibleProvider.getState()
// TODO: Improve type safety for promptType.
const prompt = supportPrompt.create(promptType, params, customSupportPrompts)
if (command.endsWith("addToContext")) {
await visibleProvider.postMessageToWebview({
type: "invoke",
invoke: "setChatBoxMessage",
text: prompt,
})
return
}
if (visibleProvider.getCurrentCline() && command.endsWith("InCurrentTask")) {
await visibleProvider.postMessageToWebview({ type: "invoke", invoke: "sendMessage", text: prompt })
await visibleProvider.postMessageToWebview({ type: "invoke", invoke: "setChatBoxMessage", text: prompt })
return
}
@ -304,6 +295,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
// Capture telemetry for terminal action usage
telemetryService.captureCodeActionUsed(promptType)
const visibleProvider = await ClineProvider.getInstance()
if (!visibleProvider) {
return
}
@ -313,20 +305,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
const prompt = supportPrompt.create(promptType, params, customSupportPrompts)
if (command.endsWith("AddToContext")) {
await visibleProvider.postMessageToWebview({
type: "invoke",
invoke: "setChatBoxMessage",
text: prompt,
})
return
}
if (visibleProvider.getCurrentCline() && command.endsWith("InCurrentTask")) {
await visibleProvider.postMessageToWebview({
type: "invoke",
invoke: "sendMessage",
text: prompt,
})
await visibleProvider.postMessageToWebview({ type: "invoke", invoke: "setChatBoxMessage", text: prompt })
return
}

View file

@ -401,6 +401,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
(text: string, images: string[]) => {
// Avoid nested template literals by breaking down the logic
let newValue = text
if (inputValue !== "") {
newValue = inputValue + " " + text
}