From 1456db95028f90b75bb521ad036a6fcc9d7bdd45 Mon Sep 17 00:00:00 2001
From: ShayBC
Date: Sat, 8 Mar 2025 06:01:49 +0200
Subject: [PATCH 01/29] added approve finish task button and auto approve
button for subtasks
---
src/core/Cline.ts | 26 +++++++++++++++++--
src/shared/ExtensionMessage.ts | 3 +++
src/shared/WebviewMessage.ts | 1 +
.../src/components/chat/AutoApproveMenu.tsx | 16 ++++++++++++
webview-ui/src/components/chat/ChatRow.tsx | 12 +++++++++
webview-ui/src/components/chat/ChatView.tsx | 5 +++-
.../src/context/ExtensionStateContext.tsx | 2 ++
7 files changed, 62 insertions(+), 3 deletions(-)
diff --git a/src/core/Cline.ts b/src/core/Cline.ts
index 51fb5265d4..c3e90d4300 100644
--- a/src/core/Cline.ts
+++ b/src/core/Cline.ts
@@ -1414,6 +1414,18 @@ export class Cline {
return true
}
+ const askFinishSubTaskApproval = async () => {
+ // ask the user to approve this task has completed, and he has reviewd it, and we can declare task is finished
+ // and return control to the parent task to continue running the rest of the sub-tasks
+ const toolMessage = JSON.stringify({
+ tool: "finishTask",
+ content:
+ "Task completed! You can review the results and suggest any corrections or next steps. If everything looks good, confirm to continue with the next task.",
+ })
+
+ return await askApproval("tool", toolMessage)
+ }
+
const handleError = async (action: string, error: Error) => {
const errorString = `Error ${action}: ${JSON.stringify(serializeError(error))}`
await this.say(
@@ -2941,8 +2953,13 @@ export class Cline {
if (lastMessage && lastMessage.ask !== "command") {
// havent sent a command message yet so first send completion_result then command
await this.say("completion_result", result, undefined, false)
- telemetryService.captureTaskCompleted(this.taskId)
+ // telemetryService.captureTaskCompleted(this.taskId)
if (this.isSubTask) {
+ const didApprove = await askFinishSubTaskApproval()
+ if (!didApprove) {
+ break
+ }
+
// tell the provider to remove the current subtask and resume the previous task in the stack
await this.providerRef
.deref()
@@ -2966,8 +2983,13 @@ export class Cline {
commandResult = execCommandResult
} else {
await this.say("completion_result", result, undefined, false)
- telemetryService.captureTaskCompleted(this.taskId)
+ // telemetryService.captureTaskCompleted(this.taskId)
if (this.isSubTask) {
+ const didApprove = await askFinishSubTaskApproval()
+ if (!didApprove) {
+ break
+ }
+
// tell the provider to remove the current subtask and resume the previous task in the stack
await this.providerRef
.deref()
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index 98ff9b36e1..dcdaf017f3 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -109,6 +109,7 @@ export interface ExtensionState {
alwaysAllowMcp?: boolean
alwaysApproveResubmit?: boolean
alwaysAllowModeSwitch?: boolean
+ alwaysAllowFinishTask?: boolean
browserToolEnabled?: boolean
requestDelaySeconds: number
rateLimitSeconds: number // Minimum time between successive requests (0 = disabled)
@@ -168,6 +169,7 @@ export type ClineAsk =
| "mistake_limit_reached"
| "browser_action_launch"
| "use_mcp_server"
+ | "finishTask"
export type ClineSay =
| "task"
@@ -207,6 +209,7 @@ export interface ClineSayTool {
| "searchFiles"
| "switchMode"
| "newTask"
+ | "finishTask"
path?: string
diff?: string
content?: string
diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts
index 10af6f7a94..086701a43f 100644
--- a/src/shared/WebviewMessage.ts
+++ b/src/shared/WebviewMessage.ts
@@ -48,6 +48,7 @@ export interface WebviewMessage {
| "alwaysAllowBrowser"
| "alwaysAllowMcp"
| "alwaysAllowModeSwitch"
+ | "alwaysAllowFinishTask"
| "playSound"
| "soundEnabled"
| "soundVolume"
diff --git a/webview-ui/src/components/chat/AutoApproveMenu.tsx b/webview-ui/src/components/chat/AutoApproveMenu.tsx
index 161f3032b0..02f75cd28a 100644
--- a/webview-ui/src/components/chat/AutoApproveMenu.tsx
+++ b/webview-ui/src/components/chat/AutoApproveMenu.tsx
@@ -30,6 +30,8 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
setAlwaysAllowMcp,
alwaysAllowModeSwitch,
setAlwaysAllowModeSwitch,
+ alwaysAllowFinishTask,
+ setAlwaysAllowFinishTask,
alwaysApproveResubmit,
setAlwaysApproveResubmit,
autoApprovalEnabled,
@@ -81,6 +83,13 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
description:
"Allows automatic switching between different AI modes and creating new tasks without requiring approval.",
},
+ {
+ id: "finishTask",
+ label: "Finish subtasks tasks",
+ shortName: "Finish",
+ enabled: alwaysAllowFinishTask ?? false,
+ description: "Allows automatic completeing a sub-task without requiring user review or approval.",
+ },
{
id: "retryRequests",
label: "Retry failed requests",
@@ -136,6 +145,12 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: newValue })
}, [alwaysAllowModeSwitch, setAlwaysAllowModeSwitch])
+ const handleFinishTaskChange = useCallback(() => {
+ const newValue = !(alwaysAllowFinishTask ?? false)
+ setAlwaysAllowFinishTask(newValue)
+ vscode.postMessage({ type: "alwaysAllowFinishTask", bool: newValue })
+ }, [alwaysAllowFinishTask, setAlwaysAllowFinishTask])
+
const handleRetryChange = useCallback(() => {
const newValue = !(alwaysApproveResubmit ?? false)
setAlwaysApproveResubmit(newValue)
@@ -150,6 +165,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
useBrowser: handleBrowserChange,
useMcp: handleMcpChange,
switchModes: handleModeSwitchChange,
+ finishTask: handleFinishTaskChange,
retryRequests: handleRetryChange,
}
diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx
index 1533bba3a8..6f19df665e 100644
--- a/webview-ui/src/components/chat/ChatRow.tsx
+++ b/webview-ui/src/components/chat/ChatRow.tsx
@@ -459,6 +459,18 @@ export const ChatRowContent = ({
>
)
+ case "finishTask":
+ return (
+ <>
+
+ {toolIcon("new-file")}
+ Roo wants to finish this task
+
+
+ {tool.content}
+
+ >
+ )
default:
return null
}
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx
index 35e63dd332..0f352819ef 100644
--- a/webview-ui/src/components/chat/ChatView.tsx
+++ b/webview-ui/src/components/chat/ChatView.tsx
@@ -61,6 +61,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
setMode,
autoApprovalEnabled,
alwaysAllowModeSwitch,
+ alwaysAllowFinishTask,
customModes,
telemetrySetting,
} = useExtensionState()
@@ -642,7 +643,8 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
(alwaysAllowModeSwitch &&
message.ask === "tool" &&
(JSON.parse(message.text || "{}")?.tool === "switchMode" ||
- JSON.parse(message.text || "{}")?.tool === "newTask"))
+ JSON.parse(message.text || "{}")?.tool === "newTask")) ||
+ (alwaysAllowFinishTask && message.ask === "finishTask")
)
},
[
@@ -657,6 +659,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
alwaysAllowMcp,
isMcpToolAlwaysAllowed,
alwaysAllowModeSwitch,
+ alwaysAllowFinishTask,
],
)
diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx
index c4daf426ca..aa132919c0 100644
--- a/webview-ui/src/context/ExtensionStateContext.tsx
+++ b/webview-ui/src/context/ExtensionStateContext.tsx
@@ -31,6 +31,7 @@ export interface ExtensionStateContextType extends ExtensionState {
setAlwaysAllowBrowser: (value: boolean) => void
setAlwaysAllowMcp: (value: boolean) => void
setAlwaysAllowModeSwitch: (value: boolean) => void
+ setAlwaysAllowFinishTask: (value: boolean) => void
setBrowserToolEnabled: (value: boolean) => void
setShowRooIgnoredFiles: (value: boolean) => void
setShowAnnouncement: (value: boolean) => void
@@ -247,6 +248,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setAlwaysAllowBrowser: (value) => setState((prevState) => ({ ...prevState, alwaysAllowBrowser: value })),
setAlwaysAllowMcp: (value) => setState((prevState) => ({ ...prevState, alwaysAllowMcp: value })),
setAlwaysAllowModeSwitch: (value) => setState((prevState) => ({ ...prevState, alwaysAllowModeSwitch: value })),
+ setAlwaysAllowFinishTask: (value) => setState((prevState) => ({ ...prevState, alwaysAllowFinishTask: value })),
setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })),
setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })),
setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })),
From 9246cf8f6dbe0f2a429872ea16f4ab2666e13d88 Mon Sep 17 00:00:00 2001
From: yt3trees
Date: Sat, 8 Mar 2025 20:23:53 +0900
Subject: [PATCH 02/29] Add o3-mini support to openai compatible
---
src/api/providers/openai.ts | 68 +++++++++++++++++++++++++++++++++++++
1 file changed, 68 insertions(+)
diff --git a/src/api/providers/openai.ts b/src/api/providers/openai.ts
index 9262f3b75a..caa99def09 100644
--- a/src/api/providers/openai.ts
+++ b/src/api/providers/openai.ts
@@ -66,6 +66,11 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
const deepseekReasoner = modelId.includes("deepseek-reasoner")
const ark = modelUrl.includes(".volces.com")
+ if (modelId.startsWith("o3-mini")) {
+ yield* this.handleO3FamilyMessage(modelId, systemPrompt, messages)
+ return
+ }
+
if (this.options.openAiStreamingEnabled ?? true) {
const systemMessage: OpenAI.Chat.ChatCompletionSystemMessageParam = {
role: "system",
@@ -169,6 +174,69 @@ export class OpenAiHandler extends BaseProvider implements SingleCompletionHandl
throw error
}
}
+
+ private async *handleO3FamilyMessage(
+ modelId: string,
+ systemPrompt: string,
+ messages: Anthropic.Messages.MessageParam[],
+ ): ApiStream {
+ if (this.options.openAiStreamingEnabled ?? true) {
+ const stream = await this.client.chat.completions.create({
+ model: "o3-mini",
+ messages: [
+ {
+ role: "developer",
+ content: `Formatting re-enabled\n${systemPrompt}`,
+ },
+ ...convertToOpenAiMessages(messages),
+ ],
+ stream: true,
+ stream_options: { include_usage: true },
+ reasoning_effort: this.getModel().info.reasoningEffort,
+ })
+
+ yield* this.handleStreamResponse(stream)
+ } else {
+ const requestOptions: OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming = {
+ model: modelId,
+ messages: [
+ {
+ role: "developer",
+ content: `Formatting re-enabled\n${systemPrompt}`,
+ },
+ ...convertToOpenAiMessages(messages),
+ ],
+ }
+
+ const response = await this.client.chat.completions.create(requestOptions)
+
+ yield {
+ type: "text",
+ text: response.choices[0]?.message.content || "",
+ }
+ yield this.processUsageMetrics(response.usage)
+ }
+ }
+
+ private async *handleStreamResponse(stream: AsyncIterable): ApiStream {
+ for await (const chunk of stream) {
+ const delta = chunk.choices[0]?.delta
+ if (delta?.content) {
+ yield {
+ type: "text",
+ text: delta.content,
+ }
+ }
+
+ if (chunk.usage) {
+ yield {
+ type: "usage",
+ inputTokens: chunk.usage.prompt_tokens || 0,
+ outputTokens: chunk.usage.completion_tokens || 0,
+ }
+ }
+ }
+ }
}
export async function getOpenAiModels(baseUrl?: string, apiKey?: string) {
From a186537a7f633d73526457d5ab18683c69bb1cb5 Mon Sep 17 00:00:00 2001
From: Yuto <57471763+yt3trees@users.noreply.github.com>
Date: Sat, 8 Mar 2025 20:38:27 +0900
Subject: [PATCH 03/29] Create wild-dragons-leave.md
---
.changeset/wild-dragons-leave.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/wild-dragons-leave.md
diff --git a/.changeset/wild-dragons-leave.md b/.changeset/wild-dragons-leave.md
new file mode 100644
index 0000000000..05320a4aa2
--- /dev/null
+++ b/.changeset/wild-dragons-leave.md
@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Add o3-mini support to openai compatible
From 27624a25a54be1f124ab5f7e765e7cb0b62c97a0 Mon Sep 17 00:00:00 2001
From: ShayBC
Date: Sat, 8 Mar 2025 16:25:45 +0200
Subject: [PATCH 04/29] fixed the missing case of cmd execution at the end of a
subyask and added auto aprove option for finish task (and continue to the
next task)
---
src/core/Cline.ts | 33 ++++++-------------
src/core/webview/ClineProvider.ts | 7 ++++
src/shared/globalState.ts | 1 +
.../src/components/chat/AutoApproveMenu.tsx | 6 ++--
webview-ui/src/components/chat/ChatView.tsx | 8 ++++-
.../settings/AutoApproveSettings.tsx | 14 ++++++++
.../src/components/settings/SettingsView.tsx | 3 ++
7 files changed, 45 insertions(+), 27 deletions(-)
diff --git a/src/core/Cline.ts b/src/core/Cline.ts
index c3e90d4300..cd1ce7031d 100644
--- a/src/core/Cline.ts
+++ b/src/core/Cline.ts
@@ -2953,19 +2953,7 @@ export class Cline {
if (lastMessage && lastMessage.ask !== "command") {
// havent sent a command message yet so first send completion_result then command
await this.say("completion_result", result, undefined, false)
- // telemetryService.captureTaskCompleted(this.taskId)
- if (this.isSubTask) {
- const didApprove = await askFinishSubTaskApproval()
- if (!didApprove) {
- break
- }
-
- // tell the provider to remove the current subtask and resume the previous task in the stack
- await this.providerRef
- .deref()
- ?.finishSubTask(`Task complete: ${lastMessage?.text}`)
- break
- }
+ telemetryService.captureTaskCompleted(this.taskId)
}
// complete command message
@@ -2983,19 +2971,18 @@ export class Cline {
commandResult = execCommandResult
} else {
await this.say("completion_result", result, undefined, false)
- // telemetryService.captureTaskCompleted(this.taskId)
- if (this.isSubTask) {
- const didApprove = await askFinishSubTaskApproval()
- if (!didApprove) {
- break
- }
+ telemetryService.captureTaskCompleted(this.taskId)
+ }
- // tell the provider to remove the current subtask and resume the previous task in the stack
- await this.providerRef
- .deref()
- ?.finishSubTask(`Task complete: ${lastMessage?.text}`)
+ if (this.isSubTask) {
+ const didApprove = await askFinishSubTaskApproval()
+ if (!didApprove) {
break
}
+
+ // tell the provider to remove the current subtask and resume the previous task in the stack
+ await this.providerRef.deref()?.finishSubTask(`Task complete: ${lastMessage?.text}`)
+ break
}
// we already sent completion_result says, an empty string asks relinquishes control over button and field
diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts
index 70feb45c2f..cc0b6f4f04 100644
--- a/src/core/webview/ClineProvider.ts
+++ b/src/core/webview/ClineProvider.ts
@@ -984,6 +984,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
await this.updateGlobalState("alwaysAllowModeSwitch", message.bool)
await this.postStateToWebview()
break
+ case "alwaysAllowFinishTask":
+ await this.updateGlobalState("alwaysAllowFinishTask", message.bool)
+ await this.postStateToWebview()
+ break
case "askResponse":
this.getCurrentCline()?.handleWebviewAskResponse(
message.askResponse!,
@@ -2177,6 +2181,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
alwaysAllowBrowser,
alwaysAllowMcp,
alwaysAllowModeSwitch,
+ alwaysAllowFinishTask,
soundEnabled,
diffEnabled,
enableCheckpoints,
@@ -2224,6 +2229,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
alwaysAllowBrowser: alwaysAllowBrowser ?? false,
alwaysAllowMcp: alwaysAllowMcp ?? false,
alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false,
+ alwaysAllowFinishTask: alwaysAllowFinishTask ?? false,
uriScheme: vscode.env.uriScheme,
currentTaskItem: this.getCurrentCline()?.taskId
? (taskHistory || []).find((item: HistoryItem) => item.id === this.getCurrentCline()?.taskId)
@@ -2385,6 +2391,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
alwaysAllowBrowser: stateValues.alwaysAllowBrowser ?? false,
alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false,
alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
+ alwaysAllowFinishTask: stateValues.alwaysAllowFinishTask ?? false,
taskHistory: stateValues.taskHistory,
allowedCommands: stateValues.allowedCommands,
soundEnabled: stateValues.soundEnabled ?? false,
diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts
index bfd24f4298..739fa11dad 100644
--- a/src/shared/globalState.ts
+++ b/src/shared/globalState.ts
@@ -40,6 +40,7 @@ export const GLOBAL_STATE_KEYS = [
"alwaysAllowBrowser",
"alwaysAllowMcp",
"alwaysAllowModeSwitch",
+ "alwaysAllowFinishTask",
"taskHistory",
"openAiBaseUrl",
"openAiModelId",
diff --git a/webview-ui/src/components/chat/AutoApproveMenu.tsx b/webview-ui/src/components/chat/AutoApproveMenu.tsx
index 02f75cd28a..fba97f6c7d 100644
--- a/webview-ui/src/components/chat/AutoApproveMenu.tsx
+++ b/webview-ui/src/components/chat/AutoApproveMenu.tsx
@@ -85,10 +85,10 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
},
{
id: "finishTask",
- label: "Finish subtasks tasks",
- shortName: "Finish",
+ label: "Continue to next task",
+ shortName: "Continue",
enabled: alwaysAllowFinishTask ?? false,
- description: "Allows automatic completeing a sub-task without requiring user review or approval.",
+ description: "Allow tasks to end execution and continue to the next task, without user review or approval.",
},
{
id: "retryRequests",
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx
index 0f352819ef..b92604e157 100644
--- a/webview-ui/src/components/chat/ChatView.tsx
+++ b/webview-ui/src/components/chat/ChatView.tsx
@@ -149,6 +149,10 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
setPrimaryButtonText("Save")
setSecondaryButtonText("Reject")
break
+ case "finishTask":
+ setPrimaryButtonText("Approve & Continue to the next Task")
+ setSecondaryButtonText(undefined)
+ break
default:
setPrimaryButtonText("Approve")
setSecondaryButtonText("Reject")
@@ -644,7 +648,9 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
message.ask === "tool" &&
(JSON.parse(message.text || "{}")?.tool === "switchMode" ||
JSON.parse(message.text || "{}")?.tool === "newTask")) ||
- (alwaysAllowFinishTask && message.ask === "finishTask")
+ (alwaysAllowFinishTask &&
+ message.ask === "tool" &&
+ JSON.parse(message.text || "{}")?.tool === "finishTask")
)
},
[
diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx
index b2da2cab75..1c8e6c9ea9 100644
--- a/webview-ui/src/components/settings/AutoApproveSettings.tsx
+++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx
@@ -18,6 +18,7 @@ type AutoApproveSettingsProps = HTMLAttributes & {
requestDelaySeconds: number
alwaysAllowMcp?: boolean
alwaysAllowModeSwitch?: boolean
+ alwaysAllowFinishTask?: boolean
alwaysAllowExecute?: boolean
allowedCommands?: string[]
setCachedStateField: SetCachedStateField
@@ -32,6 +33,7 @@ export const AutoApproveSettings = ({
requestDelaySeconds,
alwaysAllowMcp,
alwaysAllowModeSwitch,
+ alwaysAllowFinishTask,
alwaysAllowExecute,
allowedCommands,
setCachedStateField,
@@ -180,6 +182,18 @@ export const AutoApproveSettings = ({
+
+
setCachedStateField("alwaysAllowFinishTask", e.target.checked)}>
+ Always approve finish & continue to next task
+
+
+ Automatically approve tasks to finish execution and continue to the next task, without user
+ review or approval
+
+
+
(({ onDone },
alwaysAllowExecute,
alwaysAllowMcp,
alwaysAllowModeSwitch,
+ alwaysAllowFinishTask,
alwaysAllowWrite,
alwaysApproveResubmit,
browserToolEnabled,
@@ -184,6 +185,7 @@ const SettingsView = forwardRef(({ onDone },
vscode.postMessage({ type: "currentApiConfigName", text: currentApiConfigName })
vscode.postMessage({ type: "updateExperimental", values: experiments })
vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: alwaysAllowModeSwitch })
+ vscode.postMessage({ type: "alwaysAllowFinishTask", bool: alwaysAllowFinishTask })
vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration })
vscode.postMessage({ type: "telemetrySetting", text: telemetrySetting })
setChangeDetected(false)
@@ -364,6 +366,7 @@ const SettingsView = forwardRef(({ onDone },
requestDelaySeconds={requestDelaySeconds}
alwaysAllowMcp={alwaysAllowMcp}
alwaysAllowModeSwitch={alwaysAllowModeSwitch}
+ alwaysAllowFinishTask={alwaysAllowFinishTask}
alwaysAllowExecute={alwaysAllowExecute}
allowedCommands={allowedCommands}
setCachedStateField={setCachedStateField}
From 80139d88d7d7ab3baee492955a7380ade17550cc Mon Sep 17 00:00:00 2001
From: axb
Date: Sun, 9 Mar 2025 00:02:40 +0800
Subject: [PATCH 05/29] support tool progress status
---
src/core/Cline.ts | 26 ++++++++++++++++++-
.../diff/strategies/multi-search-replace.ts | 23 ++++++++++++++++
src/core/diff/types.ts | 5 ++++
src/shared/ExtensionMessage.ts | 5 ++++
webview-ui/src/components/chat/ChatRow.tsx | 1 +
.../src/components/common/CodeAccordian.tsx | 13 ++++++++++
6 files changed, 72 insertions(+), 1 deletion(-)
diff --git a/src/core/Cline.ts b/src/core/Cline.ts
index fd8ce3e9a2..232a8f4de7 100644
--- a/src/core/Cline.ts
+++ b/src/core/Cline.ts
@@ -48,6 +48,7 @@ import {
ClineSay,
ClineSayBrowserAction,
ClineSayTool,
+ ToolProgressStatus,
} from "../shared/ExtensionMessage"
import { getApiMetrics } from "../shared/getApiMetrics"
import { HistoryItem } from "../shared/HistoryItem"
@@ -408,6 +409,7 @@ export class Cline {
type: ClineAsk,
text?: string,
partial?: boolean,
+ progressStatus?: ToolProgressStatus,
): Promise<{ response: ClineAskResponse; text?: string; images?: string[] }> {
// If this Cline instance was aborted by the provider, then the only thing keeping us alive is a promise still running in the background, in which case we don't want to send its result to the webview as it is attached to a new instance of Cline now. So we can safely ignore the result of any active promises, and this class will be deallocated. (Although we set Cline = undefined in provider, that simply removes the reference to this instance, but the instance is still alive until this promise resolves or rejects.)
if (this.abort) {
@@ -423,6 +425,7 @@ export class Cline {
// existing partial message, so update it
lastMessage.text = text
lastMessage.partial = partial
+ lastMessage.progressStatus = progressStatus
// todo be more efficient about saving and posting only new data or one whole message at a time so ignore partial for saves, and only post parts of partial message instead of whole array in new listener
// await this.saveClineMessages()
// await this.providerRef.deref()?.postStateToWebview()
@@ -460,6 +463,8 @@ export class Cline {
// lastMessage.ts = askTs
lastMessage.text = text
lastMessage.partial = false
+ lastMessage.progressStatus = progressStatus
+
await this.saveClineMessages()
// await this.providerRef.deref()?.postStateToWebview()
await this.providerRef
@@ -511,6 +516,7 @@ export class Cline {
images?: string[],
partial?: boolean,
checkpoint?: Record,
+ progressStatus?: ToolProgressStatus,
): Promise {
if (this.abort) {
throw new Error(`Task: ${this.taskNumber} Roo Code instance aborted (#2)`)
@@ -526,6 +532,7 @@ export class Cline {
lastMessage.text = text
lastMessage.images = images
lastMessage.partial = partial
+ lastMessage.progressStatus = progressStatus
await this.providerRef
.deref()
?.postMessageToWebview({ type: "partialMessage", partialMessage: lastMessage })
@@ -545,6 +552,7 @@ export class Cline {
lastMessage.text = text
lastMessage.images = images
lastMessage.partial = false
+ lastMessage.progressStatus = progressStatus
// instead of streaming partialMessage events, we do a save and post like normal to persist to disk
await this.saveClineMessages()
@@ -1691,8 +1699,16 @@ export class Cline {
try {
if (block.partial) {
// update gui message
+ let toolProgressStatus
+ if (this.diffStrategy && this.diffStrategy.getProgressStatus) {
+ toolProgressStatus = this.diffStrategy.getProgressStatus(block)
+ }
+
const partialMessage = JSON.stringify(sharedMessageProps)
- await this.ask("tool", partialMessage, block.partial).catch(() => {})
+
+ await this.ask("tool", partialMessage, block.partial, toolProgressStatus).catch(
+ () => {},
+ )
break
} else {
if (!relPath) {
@@ -1787,6 +1803,14 @@ export class Cline {
diff: diffContent,
} satisfies ClineSayTool)
+ let toolProgressStatus
+ if (this.diffStrategy && this.diffStrategy.getProgressStatus) {
+ toolProgressStatus = this.diffStrategy.getProgressStatus(block, diffResult)
+ }
+ await this.ask("tool", completeMessage, block.partial, toolProgressStatus).catch(
+ () => {},
+ )
+
const didApprove = await askApproval("tool", completeMessage)
if (!didApprove) {
await this.diffViewProvider.revertChanges() // This likely handles closing the diff view
diff --git a/src/core/diff/strategies/multi-search-replace.ts b/src/core/diff/strategies/multi-search-replace.ts
index 99c22a31df..0462629b9b 100644
--- a/src/core/diff/strategies/multi-search-replace.ts
+++ b/src/core/diff/strategies/multi-search-replace.ts
@@ -1,6 +1,8 @@
import { DiffStrategy, DiffResult } from "../types"
import { addLineNumbers, everyLineHasLineNumbers, stripLineNumbers } from "../../../integrations/misc/extract-text"
import { distance } from "fastest-levenshtein"
+import { ToolProgressStatus } from "../../../shared/ExtensionMessage"
+import { ToolUse } from "../../assistant-message"
const BUFFER_LINES = 40 // Number of extra context lines to show before and after matches
@@ -362,4 +364,25 @@ Only use a single line of '=======' between search and replacement content, beca
failParts: diffResults,
}
}
+
+ getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
+ const diffContent = toolUse.params.diff
+ if (diffContent) {
+ if (toolUse.partial) {
+ if (diffContent.length < 1000 || (diffContent.length / 50) % 10 === 0) {
+ return { text: `progressing ${(diffContent.match(/SEARCH/g) || []).length} blocks...` }
+ }
+ } else if (result) {
+ const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
+ if (result.failParts) {
+ return {
+ text: `progressed ${searchBlockCount - result.failParts.length}/${searchBlockCount} blocks.`,
+ }
+ } else {
+ return { text: `progressed ${searchBlockCount} blocks.` }
+ }
+ }
+ }
+ return {}
+ }
}
diff --git a/src/core/diff/types.ts b/src/core/diff/types.ts
index be6d8cd311..e12a47762d 100644
--- a/src/core/diff/types.ts
+++ b/src/core/diff/types.ts
@@ -2,6 +2,9 @@
* Interface for implementing different diff strategies
*/
+import { ToolProgressStatus } from "../../shared/ExtensionMessage"
+import { ToolUse } from "../assistant-message"
+
export type DiffResult =
| { success: true; content: string; failParts?: DiffResult[] }
| ({
@@ -34,4 +37,6 @@ export interface DiffStrategy {
* @returns A DiffResult object containing either the successful result or error details
*/
applyDiff(originalContent: string, diffContent: string, startLine?: number, endLine?: number): Promise
+
+ getProgressStatus?(toolUse: ToolUse, result?: any): ToolProgressStatus
}
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index 98ff9b36e1..0f65d17199 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -154,6 +154,7 @@ export interface ClineMessage {
reasoning?: string
conversationHistoryIndex?: number
checkpoint?: Record
+ progressStatus?: ToolProgressStatus
}
export type ClineAsk =
@@ -271,3 +272,7 @@ export interface HumanRelayCancelMessage {
}
export type ClineApiReqCancelReason = "streaming_failed" | "user_cancelled"
+
+export type ToolProgressStatus = {
+ text?: string
+}
diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx
index 1533bba3a8..41c5863c96 100644
--- a/webview-ui/src/components/chat/ChatRow.tsx
+++ b/webview-ui/src/components/chat/ChatRow.tsx
@@ -258,6 +258,7 @@ export const ChatRowContent = ({
Roo wants to edit this file:
void
isLoading?: boolean
+ progressStatus?: ToolProgressStatus
}
/*
@@ -32,6 +34,7 @@ const CodeAccordian = ({
isExpanded,
onToggleExpand,
isLoading,
+ progressStatus,
}: CodeAccordianProps) => {
const inferredLanguage = useMemo(
() => code && (language ?? (path ? getLanguageFromPath(path) : undefined)),
@@ -95,6 +98,16 @@ const CodeAccordian = ({
>
)}
+ {progressStatus && progressStatus.text && (
+
+ {progressStatus.text}
+
+ )}
)}
From 4cf7754e655b069b05e30ee7255456b0babf3a65 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sat, 8 Mar 2025 17:24:34 -0500
Subject: [PATCH 06/29] Strip BOM when applying diffs
---
jest.config.js | 3 ++-
package-lock.json | 22 ++++++++++++++++-----
package.json | 3 ++-
src/__mocks__/strip-bom.js | 13 ++++++++++++
src/integrations/editor/DiffViewProvider.ts | 9 +++++++--
5 files changed, 41 insertions(+), 9 deletions(-)
create mode 100644 src/__mocks__/strip-bom.js
diff --git a/jest.config.js b/jest.config.js
index dbe5ee54eb..c18b6e9eff 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -30,9 +30,10 @@ module.exports = {
"^strip-ansi$": "/src/__mocks__/strip-ansi.js",
"^default-shell$": "/src/__mocks__/default-shell.js",
"^os-name$": "/src/__mocks__/os-name.js",
+ "^strip-bom$": "/src/__mocks__/strip-bom.js",
},
transformIgnorePatterns: [
- "node_modules/(?!(@modelcontextprotocol|delay|p-wait-for|globby|serialize-error|strip-ansi|default-shell|os-name)/)",
+ "node_modules/(?!(@modelcontextprotocol|delay|p-wait-for|globby|serialize-error|strip-ansi|default-shell|os-name|strip-bom)/)",
],
roots: ["/src", "/webview-ui/src"],
modulePathIgnorePatterns: [".vscode-test"],
diff --git a/package-lock.json b/package-lock.json
index 3b8f47c2e2..7c8935b791 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -51,6 +51,7 @@
"sound-play": "^1.1.0",
"string-similarity": "^4.0.4",
"strip-ansi": "^7.1.0",
+ "strip-bom": "^5.0.0",
"tmp": "^0.2.3",
"tree-sitter-wasms": "^0.1.11",
"turndown": "^7.2.0",
@@ -10782,6 +10783,15 @@
"node": ">=8"
}
},
+ "node_modules/jest-runtime/node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/jest-simple-dot-reporter": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/jest-simple-dot-reporter/-/jest-simple-dot-reporter-1.0.5.tgz",
@@ -14170,12 +14180,14 @@
}
},
"node_modules/strip-bom": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
- "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
- "dev": true,
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-5.0.0.tgz",
+ "integrity": "sha512-p+byADHF7SzEcVnLvc/r3uognM1hUhObuHXxJcgLCfD194XAkaLbjq3Wzb0N5G2tgIjH0dgT708Z51QxMeu60A==",
"engines": {
- "node": ">=8"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-final-newline": {
diff --git a/package.json b/package.json
index 5ddd9320f1..926218b21c 100644
--- a/package.json
+++ b/package.json
@@ -265,8 +265,8 @@
"@anthropic-ai/sdk": "^0.37.0",
"@anthropic-ai/vertex-sdk": "^0.7.0",
"@aws-sdk/client-bedrock-runtime": "^3.706.0",
- "@google/generative-ai": "^0.18.0",
"@google-cloud/vertexai": "^1.9.3",
+ "@google/generative-ai": "^0.18.0",
"@mistralai/mistralai": "^1.3.6",
"@modelcontextprotocol/sdk": "^1.0.1",
"@types/clone-deep": "^4.0.4",
@@ -304,6 +304,7 @@
"sound-play": "^1.1.0",
"string-similarity": "^4.0.4",
"strip-ansi": "^7.1.0",
+ "strip-bom": "^5.0.0",
"tmp": "^0.2.3",
"tree-sitter-wasms": "^0.1.11",
"turndown": "^7.2.0",
diff --git a/src/__mocks__/strip-bom.js b/src/__mocks__/strip-bom.js
new file mode 100644
index 0000000000..64bb0dac4f
--- /dev/null
+++ b/src/__mocks__/strip-bom.js
@@ -0,0 +1,13 @@
+// Mock implementation of strip-bom
+module.exports = function stripBom(string) {
+ if (typeof string !== "string") {
+ throw new TypeError("Expected a string")
+ }
+
+ // Removes UTF-8 BOM
+ if (string.charCodeAt(0) === 0xfeff) {
+ return string.slice(1)
+ }
+
+ return string
+}
diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts
index ee24d7db4e..5058ca0252 100644
--- a/src/integrations/editor/DiffViewProvider.ts
+++ b/src/integrations/editor/DiffViewProvider.ts
@@ -7,6 +7,7 @@ import { formatResponse } from "../../core/prompts/responses"
import { DecorationController } from "./DecorationController"
import * as diff from "diff"
import { diagnosticsToProblemsString, getNewDiagnostics } from "../diagnostics"
+import stripBom from "strip-bom"
export const DIFF_VIEW_URI_SCHEME = "cline-diff"
@@ -104,7 +105,7 @@ export class DiffViewProvider {
const edit = new vscode.WorkspaceEdit()
const rangeToReplace = new vscode.Range(0, 0, endLine + 1, 0)
const contentToReplace = accumulatedLines.slice(0, endLine + 1).join("\n") + "\n"
- edit.replace(document.uri, rangeToReplace, contentToReplace)
+ edit.replace(document.uri, rangeToReplace, stripBom(stripBom(contentToReplace)))
await vscode.workspace.applyEdit(edit)
// Update decorations
this.activeLineController.setActiveLine(endLine)
@@ -128,7 +129,11 @@ export class DiffViewProvider {
}
// Apply the final content
const finalEdit = new vscode.WorkspaceEdit()
- finalEdit.replace(document.uri, new vscode.Range(0, 0, document.lineCount, 0), accumulatedContent)
+ finalEdit.replace(
+ document.uri,
+ new vscode.Range(0, 0, document.lineCount, 0),
+ stripBom(stripBom(accumulatedContent)),
+ )
await vscode.workspace.applyEdit(finalEdit)
// Clear all decorations at the end (after applying final edit)
this.fadedOverlayController.clear()
From 585d5aba5ac0f3188cdb7b8e78f22ab8d088efd7 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sat, 8 Mar 2025 18:44:03 -0500
Subject: [PATCH 07/29] Strip all BOMs
---
src/integrations/editor/DiffViewProvider.ts | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/integrations/editor/DiffViewProvider.ts b/src/integrations/editor/DiffViewProvider.ts
index 5058ca0252..2aab8f9115 100644
--- a/src/integrations/editor/DiffViewProvider.ts
+++ b/src/integrations/editor/DiffViewProvider.ts
@@ -105,7 +105,7 @@ export class DiffViewProvider {
const edit = new vscode.WorkspaceEdit()
const rangeToReplace = new vscode.Range(0, 0, endLine + 1, 0)
const contentToReplace = accumulatedLines.slice(0, endLine + 1).join("\n") + "\n"
- edit.replace(document.uri, rangeToReplace, stripBom(stripBom(contentToReplace)))
+ edit.replace(document.uri, rangeToReplace, this.stripAllBOMs(contentToReplace))
await vscode.workspace.applyEdit(edit)
// Update decorations
this.activeLineController.setActiveLine(endLine)
@@ -132,7 +132,7 @@ export class DiffViewProvider {
finalEdit.replace(
document.uri,
new vscode.Range(0, 0, document.lineCount, 0),
- stripBom(stripBom(accumulatedContent)),
+ this.stripAllBOMs(accumulatedContent),
)
await vscode.workspace.applyEdit(finalEdit)
// Clear all decorations at the end (after applying final edit)
@@ -341,6 +341,16 @@ export class DiffViewProvider {
}
}
+ private stripAllBOMs(input: string): string {
+ let result = input
+ let previous
+ do {
+ previous = result
+ result = stripBom(result)
+ } while (result !== previous)
+ return result
+ }
+
// close editor if open?
async reset() {
this.editType = undefined
From 1c8071bbb371f019994c0bf7849ba37df2ef67e7 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sat, 8 Mar 2025 22:55:04 -0500
Subject: [PATCH 08/29] Clean up the tool progress UX
---
src/core/diff/strategies/multi-search-replace.ts | 12 +++++++-----
src/shared/ExtensionMessage.ts | 1 +
webview-ui/src/components/common/CodeAccordian.tsx | 14 ++++++--------
3 files changed, 14 insertions(+), 13 deletions(-)
diff --git a/src/core/diff/strategies/multi-search-replace.ts b/src/core/diff/strategies/multi-search-replace.ts
index 0462629b9b..bcf2f65430 100644
--- a/src/core/diff/strategies/multi-search-replace.ts
+++ b/src/core/diff/strategies/multi-search-replace.ts
@@ -368,18 +368,20 @@ Only use a single line of '=======' between search and replacement content, beca
getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
const diffContent = toolUse.params.diff
if (diffContent) {
+ const icon = "diff-multiple"
+ const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
if (toolUse.partial) {
if (diffContent.length < 1000 || (diffContent.length / 50) % 10 === 0) {
- return { text: `progressing ${(diffContent.match(/SEARCH/g) || []).length} blocks...` }
+ return { icon, text: `${searchBlockCount}` }
}
} else if (result) {
- const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
- if (result.failParts) {
+ if (result.failParts?.length) {
return {
- text: `progressed ${searchBlockCount - result.failParts.length}/${searchBlockCount} blocks.`,
+ icon,
+ text: `${searchBlockCount - result.failParts.length}/${searchBlockCount}`,
}
} else {
- return { text: `progressed ${searchBlockCount} blocks.` }
+ return { icon, text: `${searchBlockCount}` }
}
}
}
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index c051aab5a6..4e76b0abbc 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -277,5 +277,6 @@ export interface HumanRelayCancelMessage {
export type ClineApiReqCancelReason = "streaming_failed" | "user_cancelled"
export type ToolProgressStatus = {
+ icon?: string
text?: string
}
diff --git a/webview-ui/src/components/common/CodeAccordian.tsx b/webview-ui/src/components/common/CodeAccordian.tsx
index defafdc869..9d2f224ffb 100644
--- a/webview-ui/src/components/common/CodeAccordian.tsx
+++ b/webview-ui/src/components/common/CodeAccordian.tsx
@@ -99,14 +99,12 @@ const CodeAccordian = ({
)}
{progressStatus && progressStatus.text && (
-
- {progressStatus.text}
-
+ <>
+ {progressStatus.icon && }
+
+ {progressStatus.text}
+
+ >
)}
From e10757d6fadabeaae58441ebbadfa3e7ec5e3e2b Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sat, 8 Mar 2025 23:46:28 -0500
Subject: [PATCH 09/29] Iterate on subtasks UX
---
src/core/Cline.ts | 2 +-
src/core/webview/ClineProvider.ts | 14 ++++-----
src/shared/ExtensionMessage.ts | 2 +-
src/shared/WebviewMessage.ts | 2 +-
src/shared/globalState.ts | 2 +-
.../src/components/chat/AutoApproveMenu.tsx | 31 +++++++++----------
webview-ui/src/components/chat/ChatRow.tsx | 6 ++--
webview-ui/src/components/chat/ChatView.tsx | 13 ++++----
.../settings/AutoApproveSettings.tsx | 17 +++++-----
.../src/components/settings/SettingsView.tsx | 6 ++--
.../src/context/ExtensionStateContext.tsx | 4 +--
11 files changed, 47 insertions(+), 52 deletions(-)
diff --git a/src/core/Cline.ts b/src/core/Cline.ts
index be5306dd28..3d27a50255 100644
--- a/src/core/Cline.ts
+++ b/src/core/Cline.ts
@@ -1431,7 +1431,7 @@ export class Cline {
const toolMessage = JSON.stringify({
tool: "finishTask",
content:
- "Task completed! You can review the results and suggest any corrections or next steps. If everything looks good, confirm to continue with the next task.",
+ "Subtask completed! You can review the results and suggest any corrections or next steps. If everything looks good, confirm to return the result to the parent task.",
})
return await askApproval("tool", toolMessage)
diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts
index 90885cec43..657e4a9ab6 100644
--- a/src/core/webview/ClineProvider.ts
+++ b/src/core/webview/ClineProvider.ts
@@ -984,8 +984,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
await this.updateGlobalState("alwaysAllowModeSwitch", message.bool)
await this.postStateToWebview()
break
- case "alwaysAllowFinishTask":
- await this.updateGlobalState("alwaysAllowFinishTask", message.bool)
+ case "alwaysAllowSubtasks":
+ await this.updateGlobalState("alwaysAllowSubtasks", message.bool)
await this.postStateToWebview()
break
case "askResponse":
@@ -997,9 +997,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
break
case "clearTask":
// clear task resets the current session and allows for a new task to be started, if this session is a subtask - it allows the parent task to be resumed
- await this.finishSubTask(
- `new_task finished with an error!, it was stopped and canceled by the user.`,
- )
+ await this.finishSubTask(`Task error: It was stopped and canceled by the user.`)
await this.postStateToWebview()
break
case "didShowAnnouncement":
@@ -2181,7 +2179,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
alwaysAllowBrowser,
alwaysAllowMcp,
alwaysAllowModeSwitch,
- alwaysAllowFinishTask,
+ alwaysAllowSubtasks,
soundEnabled,
diffEnabled,
enableCheckpoints,
@@ -2229,7 +2227,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
alwaysAllowBrowser: alwaysAllowBrowser ?? false,
alwaysAllowMcp: alwaysAllowMcp ?? false,
alwaysAllowModeSwitch: alwaysAllowModeSwitch ?? false,
- alwaysAllowFinishTask: alwaysAllowFinishTask ?? false,
+ alwaysAllowSubtasks: alwaysAllowSubtasks ?? false,
uriScheme: vscode.env.uriScheme,
currentTaskItem: this.getCurrentCline()?.taskId
? (taskHistory || []).find((item: HistoryItem) => item.id === this.getCurrentCline()?.taskId)
@@ -2391,7 +2389,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
alwaysAllowBrowser: stateValues.alwaysAllowBrowser ?? false,
alwaysAllowMcp: stateValues.alwaysAllowMcp ?? false,
alwaysAllowModeSwitch: stateValues.alwaysAllowModeSwitch ?? false,
- alwaysAllowFinishTask: stateValues.alwaysAllowFinishTask ?? false,
+ alwaysAllowSubtasks: stateValues.alwaysAllowSubtasks ?? false,
taskHistory: stateValues.taskHistory,
allowedCommands: stateValues.allowedCommands,
soundEnabled: stateValues.soundEnabled ?? false,
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index 4e76b0abbc..b7e3d850cf 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -109,7 +109,7 @@ export interface ExtensionState {
alwaysAllowMcp?: boolean
alwaysApproveResubmit?: boolean
alwaysAllowModeSwitch?: boolean
- alwaysAllowFinishTask?: boolean
+ alwaysAllowSubtasks?: boolean
browserToolEnabled?: boolean
requestDelaySeconds: number
rateLimitSeconds: number // Minimum time between successive requests (0 = disabled)
diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts
index 086701a43f..216c7588d7 100644
--- a/src/shared/WebviewMessage.ts
+++ b/src/shared/WebviewMessage.ts
@@ -48,7 +48,7 @@ export interface WebviewMessage {
| "alwaysAllowBrowser"
| "alwaysAllowMcp"
| "alwaysAllowModeSwitch"
- | "alwaysAllowFinishTask"
+ | "alwaysAllowSubtasks"
| "playSound"
| "soundEnabled"
| "soundVolume"
diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts
index 739fa11dad..35e53bbe9c 100644
--- a/src/shared/globalState.ts
+++ b/src/shared/globalState.ts
@@ -40,7 +40,7 @@ export const GLOBAL_STATE_KEYS = [
"alwaysAllowBrowser",
"alwaysAllowMcp",
"alwaysAllowModeSwitch",
- "alwaysAllowFinishTask",
+ "alwaysAllowSubtasks",
"taskHistory",
"openAiBaseUrl",
"openAiModelId",
diff --git a/webview-ui/src/components/chat/AutoApproveMenu.tsx b/webview-ui/src/components/chat/AutoApproveMenu.tsx
index fba97f6c7d..692cf1d44c 100644
--- a/webview-ui/src/components/chat/AutoApproveMenu.tsx
+++ b/webview-ui/src/components/chat/AutoApproveMenu.tsx
@@ -30,8 +30,8 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
setAlwaysAllowMcp,
alwaysAllowModeSwitch,
setAlwaysAllowModeSwitch,
- alwaysAllowFinishTask,
- setAlwaysAllowFinishTask,
+ alwaysAllowSubtasks,
+ setAlwaysAllowSubtasks,
alwaysApproveResubmit,
setAlwaysApproveResubmit,
autoApprovalEnabled,
@@ -77,18 +77,17 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
},
{
id: "switchModes",
- label: "Switch modes & create tasks",
+ label: "Switch modes",
shortName: "Modes",
enabled: alwaysAllowModeSwitch ?? false,
- description:
- "Allows automatic switching between different AI modes and creating new tasks without requiring approval.",
+ description: "Allows automatic switching between different modes without requiring approval.",
},
{
- id: "finishTask",
- label: "Continue to next task",
- shortName: "Continue",
- enabled: alwaysAllowFinishTask ?? false,
- description: "Allow tasks to end execution and continue to the next task, without user review or approval.",
+ id: "subtasks",
+ label: "Create & complete subtasks",
+ shortName: "Subtasks",
+ enabled: alwaysAllowSubtasks ?? false,
+ description: "Allow creation and completion of subtasks without requiring approval.",
},
{
id: "retryRequests",
@@ -145,11 +144,11 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: newValue })
}, [alwaysAllowModeSwitch, setAlwaysAllowModeSwitch])
- const handleFinishTaskChange = useCallback(() => {
- const newValue = !(alwaysAllowFinishTask ?? false)
- setAlwaysAllowFinishTask(newValue)
- vscode.postMessage({ type: "alwaysAllowFinishTask", bool: newValue })
- }, [alwaysAllowFinishTask, setAlwaysAllowFinishTask])
+ const handleSubtasksChange = useCallback(() => {
+ const newValue = !(alwaysAllowSubtasks ?? false)
+ setAlwaysAllowSubtasks(newValue)
+ vscode.postMessage({ type: "alwaysAllowSubtasks", bool: newValue })
+ }, [alwaysAllowSubtasks, setAlwaysAllowSubtasks])
const handleRetryChange = useCallback(() => {
const newValue = !(alwaysApproveResubmit ?? false)
@@ -165,7 +164,7 @@ const AutoApproveMenu = ({ style }: AutoApproveMenuProps) => {
useBrowser: handleBrowserChange,
useMcp: handleMcpChange,
switchModes: handleModeSwitchChange,
- finishTask: handleFinishTaskChange,
+ subtasks: handleSubtasksChange,
retryRequests: handleRetryChange,
}
diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx
index bb5237dd23..b19d67dc05 100644
--- a/webview-ui/src/components/chat/ChatRow.tsx
+++ b/webview-ui/src/components/chat/ChatRow.tsx
@@ -452,7 +452,7 @@ export const ChatRowContent = ({
{toolIcon("new-file")}
- Roo wants to create a new task in {tool.mode} mode:
+ Roo wants to create a new subtask in {tool.mode} mode:
@@ -464,8 +464,8 @@ export const ChatRowContent = ({
return (
<>
- {toolIcon("new-file")}
- Roo wants to finish this task
+ {toolIcon("checklist")}
+ Roo wants to finish this subtask
{tool.content}
diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx
index b92604e157..5ac7f50559 100644
--- a/webview-ui/src/components/chat/ChatView.tsx
+++ b/webview-ui/src/components/chat/ChatView.tsx
@@ -61,7 +61,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
setMode,
autoApprovalEnabled,
alwaysAllowModeSwitch,
- alwaysAllowFinishTask,
+ alwaysAllowSubtasks,
customModes,
telemetrySetting,
} = useExtensionState()
@@ -150,7 +150,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
setSecondaryButtonText("Reject")
break
case "finishTask":
- setPrimaryButtonText("Approve & Continue to the next Task")
+ setPrimaryButtonText("Complete Subtask and Return")
setSecondaryButtonText(undefined)
break
default:
@@ -646,11 +646,10 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
(alwaysAllowMcp && message.ask === "use_mcp_server" && isMcpToolAlwaysAllowed(message)) ||
(alwaysAllowModeSwitch &&
message.ask === "tool" &&
- (JSON.parse(message.text || "{}")?.tool === "switchMode" ||
- JSON.parse(message.text || "{}")?.tool === "newTask")) ||
- (alwaysAllowFinishTask &&
+ JSON.parse(message.text || "{}")?.tool === "switchMode") ||
+ (alwaysAllowSubtasks &&
message.ask === "tool" &&
- JSON.parse(message.text || "{}")?.tool === "finishTask")
+ ["newTask", "finishTask"].includes(JSON.parse(message.text || "{}")?.tool))
)
},
[
@@ -665,7 +664,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
alwaysAllowMcp,
isMcpToolAlwaysAllowed,
alwaysAllowModeSwitch,
- alwaysAllowFinishTask,
+ alwaysAllowSubtasks,
],
)
diff --git a/webview-ui/src/components/settings/AutoApproveSettings.tsx b/webview-ui/src/components/settings/AutoApproveSettings.tsx
index 1c8e6c9ea9..d26fc33a7c 100644
--- a/webview-ui/src/components/settings/AutoApproveSettings.tsx
+++ b/webview-ui/src/components/settings/AutoApproveSettings.tsx
@@ -18,7 +18,7 @@ type AutoApproveSettingsProps = HTMLAttributes
& {
requestDelaySeconds: number
alwaysAllowMcp?: boolean
alwaysAllowModeSwitch?: boolean
- alwaysAllowFinishTask?: boolean
+ alwaysAllowSubtasks?: boolean
alwaysAllowExecute?: boolean
allowedCommands?: string[]
setCachedStateField: SetCachedStateField
@@ -33,7 +33,7 @@ export const AutoApproveSettings = ({
requestDelaySeconds,
alwaysAllowMcp,
alwaysAllowModeSwitch,
- alwaysAllowFinishTask,
+ alwaysAllowSubtasks,
alwaysAllowExecute,
allowedCommands,
setCachedStateField,
@@ -175,22 +175,21 @@ export const AutoApproveSettings = ({
setCachedStateField("alwaysAllowModeSwitch", e.target.checked)}>
- Always approve mode switching & task creation
+ Always approve mode switching
- Automatically switch between different AI modes and create new tasks without requiring approval
+ Automatically switch between different modes without requiring approval
setCachedStateField("alwaysAllowFinishTask", e.target.checked)}>
- Always approve finish & continue to next task
+ checked={alwaysAllowSubtasks}
+ onChange={(e: any) => setCachedStateField("alwaysAllowSubtasks", e.target.checked)}>
+ Always approve creation & completion of subtasks
- Automatically approve tasks to finish execution and continue to the next task, without user
- review or approval
+ Allow creation and completion of subtasks without requiring approval
diff --git a/webview-ui/src/components/settings/SettingsView.tsx b/webview-ui/src/components/settings/SettingsView.tsx
index 550fa73ca8..7cafbd6663 100644
--- a/webview-ui/src/components/settings/SettingsView.tsx
+++ b/webview-ui/src/components/settings/SettingsView.tsx
@@ -63,7 +63,7 @@ const SettingsView = forwardRef
(({ onDone },
alwaysAllowExecute,
alwaysAllowMcp,
alwaysAllowModeSwitch,
- alwaysAllowFinishTask,
+ alwaysAllowSubtasks,
alwaysAllowWrite,
alwaysApproveResubmit,
browserToolEnabled,
@@ -185,7 +185,7 @@ const SettingsView = forwardRef(({ onDone },
vscode.postMessage({ type: "currentApiConfigName", text: currentApiConfigName })
vscode.postMessage({ type: "updateExperimental", values: experiments })
vscode.postMessage({ type: "alwaysAllowModeSwitch", bool: alwaysAllowModeSwitch })
- vscode.postMessage({ type: "alwaysAllowFinishTask", bool: alwaysAllowFinishTask })
+ vscode.postMessage({ type: "alwaysAllowSubtasks", bool: alwaysAllowSubtasks })
vscode.postMessage({ type: "upsertApiConfiguration", text: currentApiConfigName, apiConfiguration })
vscode.postMessage({ type: "telemetrySetting", text: telemetrySetting })
setChangeDetected(false)
@@ -366,7 +366,7 @@ const SettingsView = forwardRef(({ onDone },
requestDelaySeconds={requestDelaySeconds}
alwaysAllowMcp={alwaysAllowMcp}
alwaysAllowModeSwitch={alwaysAllowModeSwitch}
- alwaysAllowFinishTask={alwaysAllowFinishTask}
+ alwaysAllowSubtasks={alwaysAllowSubtasks}
alwaysAllowExecute={alwaysAllowExecute}
allowedCommands={allowedCommands}
setCachedStateField={setCachedStateField}
diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx
index aa132919c0..8d16f2e0f0 100644
--- a/webview-ui/src/context/ExtensionStateContext.tsx
+++ b/webview-ui/src/context/ExtensionStateContext.tsx
@@ -31,7 +31,7 @@ export interface ExtensionStateContextType extends ExtensionState {
setAlwaysAllowBrowser: (value: boolean) => void
setAlwaysAllowMcp: (value: boolean) => void
setAlwaysAllowModeSwitch: (value: boolean) => void
- setAlwaysAllowFinishTask: (value: boolean) => void
+ setAlwaysAllowSubtasks: (value: boolean) => void
setBrowserToolEnabled: (value: boolean) => void
setShowRooIgnoredFiles: (value: boolean) => void
setShowAnnouncement: (value: boolean) => void
@@ -248,7 +248,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setAlwaysAllowBrowser: (value) => setState((prevState) => ({ ...prevState, alwaysAllowBrowser: value })),
setAlwaysAllowMcp: (value) => setState((prevState) => ({ ...prevState, alwaysAllowMcp: value })),
setAlwaysAllowModeSwitch: (value) => setState((prevState) => ({ ...prevState, alwaysAllowModeSwitch: value })),
- setAlwaysAllowFinishTask: (value) => setState((prevState) => ({ ...prevState, alwaysAllowFinishTask: value })),
+ setAlwaysAllowSubtasks: (value) => setState((prevState) => ({ ...prevState, alwaysAllowSubtasks: value })),
setShowAnnouncement: (value) => setState((prevState) => ({ ...prevState, shouldShowAnnouncement: value })),
setAllowedCommands: (value) => setState((prevState) => ({ ...prevState, allowedCommands: value })),
setSoundEnabled: (value) => setState((prevState) => ({ ...prevState, soundEnabled: value })),
From 91d16896b1457122fdfd3dc7e4045ecb1764e27c Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sat, 8 Mar 2025 23:46:49 -0500
Subject: [PATCH 10/29] Changeset
---
.changeset/modern-pillows-visit.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/modern-pillows-visit.md
diff --git a/.changeset/modern-pillows-visit.md b/.changeset/modern-pillows-visit.md
new file mode 100644
index 0000000000..4e5188175d
--- /dev/null
+++ b/.changeset/modern-pillows-visit.md
@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+v3.8.2
From 148e0560a1e0c6c70283d2c2c767b7fb6e125ba3 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Sun, 9 Mar 2025 05:02:18 +0000
Subject: [PATCH 11/29] changeset version bump
---
.changeset/modern-pillows-visit.md | 5 -----
.changeset/wild-dragons-leave.md | 5 -----
CHANGELOG.md | 7 +++++++
package-lock.json | 4 ++--
package.json | 2 +-
5 files changed, 10 insertions(+), 13 deletions(-)
delete mode 100644 .changeset/modern-pillows-visit.md
delete mode 100644 .changeset/wild-dragons-leave.md
diff --git a/.changeset/modern-pillows-visit.md b/.changeset/modern-pillows-visit.md
deleted file mode 100644
index 4e5188175d..0000000000
--- a/.changeset/modern-pillows-visit.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"roo-cline": patch
----
-
-v3.8.2
diff --git a/.changeset/wild-dragons-leave.md b/.changeset/wild-dragons-leave.md
deleted file mode 100644
index 05320a4aa2..0000000000
--- a/.changeset/wild-dragons-leave.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"roo-cline": patch
----
-
-Add o3-mini support to openai compatible
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ff2aa8de27..ba5d4ca8a7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
# Roo Code Changelog
+## 3.8.2
+
+### Patch Changes
+
+- v3.8.2
+- Add o3-mini support to openai compatible
+
## [3.8.1] - 2025-03-07
- Show the reserved output tokens in the context window visualization
diff --git a/package-lock.json b/package-lock.json
index 7c8935b791..61b8eea298 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "roo-cline",
- "version": "3.8.1",
+ "version": "3.8.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "roo-cline",
- "version": "3.8.1",
+ "version": "3.8.2",
"dependencies": {
"@anthropic-ai/bedrock-sdk": "^0.10.2",
"@anthropic-ai/sdk": "^0.37.0",
diff --git a/package.json b/package.json
index 926218b21c..c3adb234b3 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"displayName": "Roo Code (prev. Roo Cline)",
"description": "A whole dev team of AI agents in your editor.",
"publisher": "RooVeterinaryInc",
- "version": "3.8.1",
+ "version": "3.8.2",
"icon": "assets/icons/rocket.png",
"galleryBanner": {
"color": "#617A91",
From f4df55f020b310ec002e361cfb996c20ee7c40bf Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sun, 9 Mar 2025 00:04:30 -0500
Subject: [PATCH 12/29] Update CHANGELOG.md
---
CHANGELOG.md | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ba5d4ca8a7..ac03780cc8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,12 @@
# Roo Code Changelog
-## 3.8.2
+## [3.8.2] - 2025-03-08
-### Patch Changes
-
-- v3.8.2
-- Add o3-mini support to openai compatible
+- Create an auto-approval toggle for subtask creation and completion (thanks @shaybc!)
+- Show a progress indicator when using the multi-diff editing strategy (thanks @qdaxb!)
+- Add o3-mini support to the OpenAI-compatible provider (thanks @yt3trees!)
+- Fix encoding issue where unreadable characters were sometimes getting added to the beginning of files
+- Fix issue where settings dropdowns were getting truncated in some cases
## [3.8.1] - 2025-03-07
From 2a08c7c3dbbcaac5fc8b005109a0929a1ed8e9ef Mon Sep 17 00:00:00 2001
From: Roo Code
Date: Sat, 8 Mar 2025 22:05:27 -0700
Subject: [PATCH 13/29] feat: Add toggle for custom mode creation
This commit adds a new setting to allow users to disable custom mode creation,
which can help reduce token usage in Roo's prompts.
Key changes:
Add enableCustomModeCreation setting to global state
Conditionally include custom modes documentation in prompt only when enabled
Add UI toggle in PromptsView with explanatory text
Default the setting to enabled (true) for backward compatibility
Update necessary interfaces and message handlers for the new setting
The setting is placed in PromptsView rather than SettingsView since it directly
relates to the modes functionality managed in that component.
---
src/core/prompts/sections/modes.ts | 16 +++++++-
src/core/webview/ClineProvider.ts | 4 ++
src/shared/ExtensionMessage.ts | 1 +
src/shared/WebviewMessage.ts | 1 +
src/shared/globalState.ts | 1 +
.../src/components/prompts/PromptsView.tsx | 40 ++++++++++++++++++-
.../src/context/ExtensionStateContext.tsx | 5 +++
7 files changed, 65 insertions(+), 3 deletions(-)
diff --git a/src/core/prompts/sections/modes.ts b/src/core/prompts/sections/modes.ts
index f3863870db..d561e47a84 100644
--- a/src/core/prompts/sections/modes.ts
+++ b/src/core/prompts/sections/modes.ts
@@ -11,12 +11,21 @@ export async function getModesSection(context: vscode.ExtensionContext): Promise
// Get all modes with their overrides from extension state
const allModes = await getAllModesWithPrompts(context)
- return `====
+ // Get enableCustomModeCreation setting from extension state
+ const enableCustomModeCreation = await context.globalState.get("enableCustomModeCreation")
+ // Default to true if undefined
+ const shouldEnableCustomModeCreation = enableCustomModeCreation !== undefined ? enableCustomModeCreation : true
+
+ let modesContent = `====
MODES
- These are the currently available modes:
-${allModes.map((mode: ModeConfig) => ` * "${mode.name}" mode (${mode.slug}) - ${mode.roleDefinition.split(".")[0]}`).join("\n")}
+${allModes.map((mode: ModeConfig) => ` * "${mode.name}" mode (${mode.slug}) - ${mode.roleDefinition.split(".")[0]}`).join("\n")}`
+
+ // Only include custom modes documentation if the feature is enabled
+ if (shouldEnableCustomModeCreation) {
+ modesContent += `
- Custom modes can be configured in two ways:
1. Globally via '${customModesPath}' (created automatically on startup)
@@ -56,4 +65,7 @@ Both files should follow this structure:
}
]
}`
+ }
+
+ return modesContent
}
diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts
index e1d67b5a28..75689e2450 100644
--- a/src/core/webview/ClineProvider.ts
+++ b/src/core/webview/ClineProvider.ts
@@ -1476,6 +1476,10 @@ export class ClineProvider implements vscode.WebviewViewProvider {
await this.updateGlobalState("enhancementApiConfigId", message.text)
await this.postStateToWebview()
break
+ case "enableCustomModeCreation":
+ await this.updateGlobalState("enableCustomModeCreation", message.bool ?? true)
+ await this.postStateToWebview()
+ break
case "autoApprovalEnabled":
await this.updateGlobalState("autoApprovalEnabled", message.bool ?? false)
await this.postStateToWebview()
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index 98ff9b36e1..78c60acc97 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -128,6 +128,7 @@ export interface ExtensionState {
terminalOutputLimit?: number
mcpEnabled: boolean
enableMcpServerCreation: boolean
+ enableCustomModeCreation?: boolean
mode: Mode
modeApiConfigs?: Record
enhancementApiConfigId?: string
diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts
index 10af6f7a94..37328cd95a 100644
--- a/src/shared/WebviewMessage.ts
+++ b/src/shared/WebviewMessage.ts
@@ -71,6 +71,7 @@ export interface WebviewMessage {
| "terminalOutputLimit"
| "mcpEnabled"
| "enableMcpServerCreation"
+ | "enableCustomModeCreation"
| "searchCommits"
| "alwaysApproveResubmit"
| "requestDelaySeconds"
diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts
index bfd24f4298..579bf1df86 100644
--- a/src/shared/globalState.ts
+++ b/src/shared/globalState.ts
@@ -84,6 +84,7 @@ export const GLOBAL_STATE_KEYS = [
"enhancementApiConfigId",
"experiments", // Map of experiment IDs to their enabled state
"autoApprovalEnabled",
+ "enableCustomModeCreation", // Enable the ability to create custom modes
"customModes", // Array of custom modes
"unboundModelId",
"requestyModelId",
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index ccf1e6d700..e14ce8f939 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -71,6 +71,8 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
preferredLanguage,
setPreferredLanguage,
customModes,
+ enableCustomModeCreation,
+ setEnableCustomModeCreation,
} = useExtensionState()
// Memoize modes to preserve array order
@@ -341,6 +343,17 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
return () => document.removeEventListener("click", handleClickOutside)
}, [showConfigMenu])
+ // Add effect to sync enableCustomModeCreation with backend
+ useEffect(() => {
+ if (enableCustomModeCreation !== undefined) {
+ // Send the value to the extension's global state
+ vscode.postMessage({
+ type: "enableCustomModeCreation", // Using dedicated message type
+ bool: enableCustomModeCreation,
+ })
+ }
+ }, [enableCustomModeCreation])
+
useEffect(() => {
const handler = (event: MessageEvent) => {
const message = event.data
@@ -541,8 +554,33 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
in your workspace.
-
+ {/*
+ NOTE: This setting is placed in PromptsView rather than SettingsView since it
+ directly affects the functionality related to modes and custom mode creation,
+ which are managed in this component. This is an intentional deviation from
+ the standard pattern described in cline_docs/settings.md.
+ */}
+
+
{
+ // Just update the local state through React context
+ // The React context will update the global state
+ setEnableCustomModeCreation(e.target.checked)
+ }}>
+ Enable Custom Mode Creation
+
+
+ When enabled, Roo can help you create project-level custom modes. You can disable this to
+ reduce Roo's token usage.
+
+
e.stopPropagation()} className="flex justify-between items-center mb-3">
Modes
diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx
index c4daf426ca..3ed42b8586 100644
--- a/webview-ui/src/context/ExtensionStateContext.tsx
+++ b/webview-ui/src/context/ExtensionStateContext.tsx
@@ -52,6 +52,8 @@ export interface ExtensionStateContextType extends ExtensionState {
setMcpEnabled: (value: boolean) => void
enableMcpServerCreation: boolean
setEnableMcpServerCreation: (value: boolean) => void
+ enableCustomModeCreation?: boolean
+ setEnableCustomModeCreation: (value: boolean) => void
alwaysApproveResubmit?: boolean
setAlwaysApproveResubmit: (value: boolean) => void
requestDelaySeconds: number
@@ -117,6 +119,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
checkpointStorage: "task",
fuzzyMatchThreshold: 1.0,
preferredLanguage: "English",
+ enableCustomModeCreation: true,
writeDelayMs: 1000,
browserViewportSize: "900x600",
screenshotQuality: 75,
@@ -273,6 +276,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
setCustomSupportPrompts: (value) => setState((prevState) => ({ ...prevState, customSupportPrompts: value })),
setEnhancementApiConfigId: (value) =>
setState((prevState) => ({ ...prevState, enhancementApiConfigId: value })),
+ setEnableCustomModeCreation: (value) =>
+ setState((prevState) => ({ ...prevState, enableCustomModeCreation: value })),
setAutoApprovalEnabled: (value) => setState((prevState) => ({ ...prevState, autoApprovalEnabled: value })),
setCustomModes: (value) => setState((prevState) => ({ ...prevState, customModes: value })),
setMaxOpenTabsContext: (value) => setState((prevState) => ({ ...prevState, maxOpenTabsContext: value })),
From f6efa2b589b5ebda5204c64cbca9eba346483c25 Mon Sep 17 00:00:00 2001
From: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>
Date: Sat, 8 Mar 2025 22:31:10 -0700
Subject: [PATCH 14/29] Update src/core/prompts/sections/modes.ts
Co-authored-by: Matt Rubens
---
src/core/prompts/sections/modes.ts | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/core/prompts/sections/modes.ts b/src/core/prompts/sections/modes.ts
index d561e47a84..788c7d7ebe 100644
--- a/src/core/prompts/sections/modes.ts
+++ b/src/core/prompts/sections/modes.ts
@@ -12,9 +12,7 @@ export async function getModesSection(context: vscode.ExtensionContext): Promise
const allModes = await getAllModesWithPrompts(context)
// Get enableCustomModeCreation setting from extension state
- const enableCustomModeCreation = await context.globalState.get("enableCustomModeCreation")
- // Default to true if undefined
- const shouldEnableCustomModeCreation = enableCustomModeCreation !== undefined ? enableCustomModeCreation : true
+ const shouldEnableCustomModeCreation = await context.globalState.get("enableCustomModeCreation") ?? true
let modesContent = `====
From bb87b7896b595093da4d1731112fe00662a16575 Mon Sep 17 00:00:00 2001
From: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>
Date: Sat, 8 Mar 2025 22:31:20 -0700
Subject: [PATCH 15/29] Update src/shared/globalState.ts
Co-authored-by: Matt Rubens
---
src/shared/globalState.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/shared/globalState.ts b/src/shared/globalState.ts
index 579bf1df86..fd21d1c669 100644
--- a/src/shared/globalState.ts
+++ b/src/shared/globalState.ts
@@ -84,7 +84,7 @@ export const GLOBAL_STATE_KEYS = [
"enhancementApiConfigId",
"experiments", // Map of experiment IDs to their enabled state
"autoApprovalEnabled",
- "enableCustomModeCreation", // Enable the ability to create custom modes
+ "enableCustomModeCreation", // Enable the ability for Roo to create custom modes
"customModes", // Array of custom modes
"unboundModelId",
"requestyModelId",
From 74a0dcebf6b61ecb97fb512ae6a55360c5b0c92e Mon Sep 17 00:00:00 2001
From: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>
Date: Sat, 8 Mar 2025 22:32:14 -0700
Subject: [PATCH 16/29] Update
webview-ui/src/components/prompts/PromptsView.tsx
Co-authored-by: Matt Rubens
---
webview-ui/src/components/prompts/PromptsView.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index e14ce8f939..11e64003d1 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -577,7 +577,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
- When enabled, Roo can help you create project-level custom modes. You can disable this to
+ When enabled, Roo can help you create custom modes. You can disable this to
reduce Roo's token usage.
From 47294dec564fd2a698b150dc3f6d3bd3e1fc4d0a Mon Sep 17 00:00:00 2001
From: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>
Date: Sat, 8 Mar 2025 22:32:40 -0700
Subject: [PATCH 17/29] Update
webview-ui/src/components/prompts/PromptsView.tsx
Co-authored-by: Matt Rubens
---
webview-ui/src/components/prompts/PromptsView.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index 11e64003d1..7ea8bfba62 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -563,7 +563,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
*/}
{
// Just update the local state through React context
// The React context will update the global state
From cc4f6dd6757d4b7daef0ddd3ea0ba5804a7e1547 Mon Sep 17 00:00:00 2001
From: hannesrudolph
Date: Sat, 8 Mar 2025 22:40:43 -0700
Subject: [PATCH 18/29] style: Update margin styling for checkbox in
PromptsView component
---
webview-ui/src/components/prompts/PromptsView.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index 7ea8bfba62..3561a80d10 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -561,7 +561,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
which are managed in this component. This is an intentional deviation from
the standard pattern described in cline_docs/settings.md.
*/}
-
+
{
@@ -577,8 +577,8 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
marginTop: "5px",
color: "var(--vscode-descriptionForeground)",
}}>
- When enabled, Roo can help you create custom modes. You can disable this to
- reduce Roo's token usage.
+ When enabled, Roo can help you create custom modes. You can disable this to reduce Roo's
+ token usage.
e.stopPropagation()} className="flex justify-between items-center mb-3">
From 68cfdc985e87bf55d1f3f04aee39469108fb76f1 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sun, 9 Mar 2025 09:11:55 -0400
Subject: [PATCH 19/29] Fix the VSCode LM model picker
---
.changeset/eleven-birds-doubt.md | 5 +++
.../src/components/settings/ApiOptions.tsx | 32 +++++++++++--------
2 files changed, 23 insertions(+), 14 deletions(-)
create mode 100644 .changeset/eleven-birds-doubt.md
diff --git a/.changeset/eleven-birds-doubt.md b/.changeset/eleven-birds-doubt.md
new file mode 100644
index 0000000000..977228c808
--- /dev/null
+++ b/.changeset/eleven-birds-doubt.md
@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Fix VS Code LM API model picker
diff --git a/webview-ui/src/components/settings/ApiOptions.tsx b/webview-ui/src/components/settings/ApiOptions.tsx
index c5a02dc117..f7982080c8 100644
--- a/webview-ui/src/components/settings/ApiOptions.tsx
+++ b/webview-ui/src/components/settings/ApiOptions.tsx
@@ -1076,27 +1076,31 @@ const ApiOptions = ({
Language Model
{vsCodeLmModels.length > 0 ? (
- {
- const valueStr = (e as DropdownOption)?.value
+ onValueChange={handleInputChange("vsCodeLmModelSelector", (valueStr) => {
const [vendor, family] = valueStr.split("/")
return { vendor, family }
- })}
- options={[
- { value: "", label: "Select a model..." },
- ...vsCodeLmModels.map((model) => ({
- value: `${model.vendor}/${model.family}`,
- label: `${model.vendor} - ${model.family}`,
- })),
- ]}
- className="w-full"
- />
+ })}>
+
+
+
+
+
+ {vsCodeLmModels.map((model) => (
+
+ {`${model.vendor} - ${model.family}`}
+
+ ))}
+
+
+
) : (
The VS Code Language Model API allows you to run models provided by other VS Code
From b57fcf2094c8a96a327caa271086f02259d36da3 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
Date: Sun, 9 Mar 2025 13:46:40 +0000
Subject: [PATCH 20/29] changeset version bump
---
.changeset/eleven-birds-doubt.md | 5 -----
CHANGELOG.md | 6 ++++++
package-lock.json | 4 ++--
package.json | 2 +-
4 files changed, 9 insertions(+), 8 deletions(-)
delete mode 100644 .changeset/eleven-birds-doubt.md
diff --git a/.changeset/eleven-birds-doubt.md b/.changeset/eleven-birds-doubt.md
deleted file mode 100644
index 977228c808..0000000000
--- a/.changeset/eleven-birds-doubt.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"roo-cline": patch
----
-
-Fix VS Code LM API model picker
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ac03780cc8..248bdec9d3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
# Roo Code Changelog
+## 3.8.3
+
+### Patch Changes
+
+- Fix VS Code LM API model picker
+
## [3.8.2] - 2025-03-08
- Create an auto-approval toggle for subtask creation and completion (thanks @shaybc!)
diff --git a/package-lock.json b/package-lock.json
index 61b8eea298..6884f2e626 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "roo-cline",
- "version": "3.8.2",
+ "version": "3.8.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "roo-cline",
- "version": "3.8.2",
+ "version": "3.8.3",
"dependencies": {
"@anthropic-ai/bedrock-sdk": "^0.10.2",
"@anthropic-ai/sdk": "^0.37.0",
diff --git a/package.json b/package.json
index c3adb234b3..e4adffd1d7 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"displayName": "Roo Code (prev. Roo Cline)",
"description": "A whole dev team of AI agents in your editor.",
"publisher": "RooVeterinaryInc",
- "version": "3.8.2",
+ "version": "3.8.3",
"icon": "assets/icons/rocket.png",
"galleryBanner": {
"color": "#617A91",
From edec39b98ea05a1101e87b81619a6c7f7254f04f Mon Sep 17 00:00:00 2001
From: R00-B0T
Date: Sun, 9 Mar 2025 13:47:05 +0000
Subject: [PATCH 21/29] Updating CHANGELOG.md format
---
CHANGELOG.md | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 248bdec9d3..9c69784ac7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,6 @@
# Roo Code Changelog
-## 3.8.3
-
-### Patch Changes
+## [3.8.3]
- Fix VS Code LM API model picker
From a05d7c1c8e65d9e0f086fb7101d33fb765da5a13 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sun, 9 Mar 2025 09:51:44 -0400
Subject: [PATCH 22/29] Update CHANGELOG.md
---
CHANGELOG.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9c69784ac7..7afcfae2d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,8 +1,8 @@
# Roo Code Changelog
-## [3.8.3]
+## [3.8.3] - 2025-03-09
-- Fix VS Code LM API model picker
+- Fix VS Code LM API model picker truncation issue
## [3.8.2] - 2025-03-08
From 445066c430f52d5cb8f1da0cea833a8ec5f9961a Mon Sep 17 00:00:00 2001
From: hannesrudolph
Date: Sun, 9 Mar 2025 15:56:23 -0600
Subject: [PATCH 23/29] refactor: Move custom mode creation setting to a more
appropriate location in PromptsView component
---
.../src/components/prompts/PromptsView.tsx | 55 ++++++++++---------
1 file changed, 29 insertions(+), 26 deletions(-)
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index 3561a80d10..7303f7691d 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -555,32 +555,6 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
- {/*
- NOTE: This setting is placed in PromptsView rather than SettingsView since it
- directly affects the functionality related to modes and custom mode creation,
- which are managed in this component. This is an intentional deviation from
- the standard pattern described in cline_docs/settings.md.
- */}
-
-
{
- // Just update the local state through React context
- // The React context will update the global state
- setEnableCustomModeCreation(e.target.checked)
- }}>
- Enable Custom Mode Creation
-
-
- When enabled, Roo can help you create custom modes. You can disable this to reduce Roo's
- token usage.
-
-
e.stopPropagation()} className="flex justify-between items-center mb-3">
Modes
@@ -1048,6 +1022,35 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
)}
+
+ {/*
+ NOTE: This setting is placed in PromptsView rather than SettingsView since it
+ directly affects the functionality related to modes and custom mode creation,
+ which are managed in this component. This is an intentional deviation from
+ the standard pattern described in cline_docs/settings.md.
+ */}
+
+
{
+ // Just update the local state through React context
+ // The React context will update the global state
+ setEnableCustomModeCreation(e.target.checked)
+ }}>
+ Enable Custom Mode Creation
+
+
+ When enabled, Roo allows you to create custom modes using prompts like ‘Make me a custom
+ mode that…’. Disabling this reduces your system prompt by about 700 tokens when this feature
+ isn’t needed. When disabled you can still manually create custom prompts using the + button
+ above or by editing the related config JSON.
+
+
Date: Sun, 9 Mar 2025 18:35:48 -0400
Subject: [PATCH 24/29] Revert "Clean up the tool progress UX"
This reverts commit 1c8071bbb371f019994c0bf7849ba37df2ef67e7.
---
src/core/diff/strategies/multi-search-replace.ts | 12 +++++-------
src/shared/ExtensionMessage.ts | 1 -
webview-ui/src/components/common/CodeAccordian.tsx | 14 ++++++++------
3 files changed, 13 insertions(+), 14 deletions(-)
diff --git a/src/core/diff/strategies/multi-search-replace.ts b/src/core/diff/strategies/multi-search-replace.ts
index bcf2f65430..0462629b9b 100644
--- a/src/core/diff/strategies/multi-search-replace.ts
+++ b/src/core/diff/strategies/multi-search-replace.ts
@@ -368,20 +368,18 @@ Only use a single line of '=======' between search and replacement content, beca
getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
const diffContent = toolUse.params.diff
if (diffContent) {
- const icon = "diff-multiple"
- const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
if (toolUse.partial) {
if (diffContent.length < 1000 || (diffContent.length / 50) % 10 === 0) {
- return { icon, text: `${searchBlockCount}` }
+ return { text: `progressing ${(diffContent.match(/SEARCH/g) || []).length} blocks...` }
}
} else if (result) {
- if (result.failParts?.length) {
+ const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
+ if (result.failParts) {
return {
- icon,
- text: `${searchBlockCount - result.failParts.length}/${searchBlockCount}`,
+ text: `progressed ${searchBlockCount - result.failParts.length}/${searchBlockCount} blocks.`,
}
} else {
- return { icon, text: `${searchBlockCount}` }
+ return { text: `progressed ${searchBlockCount} blocks.` }
}
}
}
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index b7e3d850cf..0c20669ed1 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -277,6 +277,5 @@ export interface HumanRelayCancelMessage {
export type ClineApiReqCancelReason = "streaming_failed" | "user_cancelled"
export type ToolProgressStatus = {
- icon?: string
text?: string
}
diff --git a/webview-ui/src/components/common/CodeAccordian.tsx b/webview-ui/src/components/common/CodeAccordian.tsx
index 9d2f224ffb..defafdc869 100644
--- a/webview-ui/src/components/common/CodeAccordian.tsx
+++ b/webview-ui/src/components/common/CodeAccordian.tsx
@@ -99,12 +99,14 @@ const CodeAccordian = ({
)}
{progressStatus && progressStatus.text && (
- <>
- {progressStatus.icon &&
}
-
- {progressStatus.text}
-
- >
+
+ {progressStatus.text}
+
)}
From 183e47b1bd14a0432a6a167fe1e1e651e27059c1 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sun, 9 Mar 2025 18:35:56 -0400
Subject: [PATCH 25/29] Revert "support tool progress status"
This reverts commit 80139d88d7d7ab3baee492955a7380ade17550cc.
---
src/core/Cline.ts | 26 +------------------
.../diff/strategies/multi-search-replace.ts | 23 ----------------
src/core/diff/types.ts | 5 ----
src/shared/ExtensionMessage.ts | 5 ----
webview-ui/src/components/chat/ChatRow.tsx | 1 -
.../src/components/common/CodeAccordian.tsx | 13 ----------
6 files changed, 1 insertion(+), 72 deletions(-)
diff --git a/src/core/Cline.ts b/src/core/Cline.ts
index 3d27a50255..3d1f980c7d 100644
--- a/src/core/Cline.ts
+++ b/src/core/Cline.ts
@@ -48,7 +48,6 @@ import {
ClineSay,
ClineSayBrowserAction,
ClineSayTool,
- ToolProgressStatus,
} from "../shared/ExtensionMessage"
import { getApiMetrics } from "../shared/getApiMetrics"
import { HistoryItem } from "../shared/HistoryItem"
@@ -409,7 +408,6 @@ export class Cline {
type: ClineAsk,
text?: string,
partial?: boolean,
- progressStatus?: ToolProgressStatus,
): Promise<{ response: ClineAskResponse; text?: string; images?: string[] }> {
// If this Cline instance was aborted by the provider, then the only thing keeping us alive is a promise still running in the background, in which case we don't want to send its result to the webview as it is attached to a new instance of Cline now. So we can safely ignore the result of any active promises, and this class will be deallocated. (Although we set Cline = undefined in provider, that simply removes the reference to this instance, but the instance is still alive until this promise resolves or rejects.)
if (this.abort) {
@@ -425,7 +423,6 @@ export class Cline {
// existing partial message, so update it
lastMessage.text = text
lastMessage.partial = partial
- lastMessage.progressStatus = progressStatus
// todo be more efficient about saving and posting only new data or one whole message at a time so ignore partial for saves, and only post parts of partial message instead of whole array in new listener
// await this.saveClineMessages()
// await this.providerRef.deref()?.postStateToWebview()
@@ -463,8 +460,6 @@ export class Cline {
// lastMessage.ts = askTs
lastMessage.text = text
lastMessage.partial = false
- lastMessage.progressStatus = progressStatus
-
await this.saveClineMessages()
// await this.providerRef.deref()?.postStateToWebview()
await this.providerRef
@@ -516,7 +511,6 @@ export class Cline {
images?: string[],
partial?: boolean,
checkpoint?: Record,
- progressStatus?: ToolProgressStatus,
): Promise {
if (this.abort) {
throw new Error(`Task: ${this.taskNumber} Roo Code instance aborted (#2)`)
@@ -532,7 +526,6 @@ export class Cline {
lastMessage.text = text
lastMessage.images = images
lastMessage.partial = partial
- lastMessage.progressStatus = progressStatus
await this.providerRef
.deref()
?.postMessageToWebview({ type: "partialMessage", partialMessage: lastMessage })
@@ -552,7 +545,6 @@ export class Cline {
lastMessage.text = text
lastMessage.images = images
lastMessage.partial = false
- lastMessage.progressStatus = progressStatus
// instead of streaming partialMessage events, we do a save and post like normal to persist to disk
await this.saveClineMessages()
@@ -1711,16 +1703,8 @@ export class Cline {
try {
if (block.partial) {
// update gui message
- let toolProgressStatus
- if (this.diffStrategy && this.diffStrategy.getProgressStatus) {
- toolProgressStatus = this.diffStrategy.getProgressStatus(block)
- }
-
const partialMessage = JSON.stringify(sharedMessageProps)
-
- await this.ask("tool", partialMessage, block.partial, toolProgressStatus).catch(
- () => {},
- )
+ await this.ask("tool", partialMessage, block.partial).catch(() => {})
break
} else {
if (!relPath) {
@@ -1815,14 +1799,6 @@ export class Cline {
diff: diffContent,
} satisfies ClineSayTool)
- let toolProgressStatus
- if (this.diffStrategy && this.diffStrategy.getProgressStatus) {
- toolProgressStatus = this.diffStrategy.getProgressStatus(block, diffResult)
- }
- await this.ask("tool", completeMessage, block.partial, toolProgressStatus).catch(
- () => {},
- )
-
const didApprove = await askApproval("tool", completeMessage)
if (!didApprove) {
await this.diffViewProvider.revertChanges() // This likely handles closing the diff view
diff --git a/src/core/diff/strategies/multi-search-replace.ts b/src/core/diff/strategies/multi-search-replace.ts
index 0462629b9b..99c22a31df 100644
--- a/src/core/diff/strategies/multi-search-replace.ts
+++ b/src/core/diff/strategies/multi-search-replace.ts
@@ -1,8 +1,6 @@
import { DiffStrategy, DiffResult } from "../types"
import { addLineNumbers, everyLineHasLineNumbers, stripLineNumbers } from "../../../integrations/misc/extract-text"
import { distance } from "fastest-levenshtein"
-import { ToolProgressStatus } from "../../../shared/ExtensionMessage"
-import { ToolUse } from "../../assistant-message"
const BUFFER_LINES = 40 // Number of extra context lines to show before and after matches
@@ -364,25 +362,4 @@ Only use a single line of '=======' between search and replacement content, beca
failParts: diffResults,
}
}
-
- getProgressStatus(toolUse: ToolUse, result?: DiffResult): ToolProgressStatus {
- const diffContent = toolUse.params.diff
- if (diffContent) {
- if (toolUse.partial) {
- if (diffContent.length < 1000 || (diffContent.length / 50) % 10 === 0) {
- return { text: `progressing ${(diffContent.match(/SEARCH/g) || []).length} blocks...` }
- }
- } else if (result) {
- const searchBlockCount = (diffContent.match(/SEARCH/g) || []).length
- if (result.failParts) {
- return {
- text: `progressed ${searchBlockCount - result.failParts.length}/${searchBlockCount} blocks.`,
- }
- } else {
- return { text: `progressed ${searchBlockCount} blocks.` }
- }
- }
- }
- return {}
- }
}
diff --git a/src/core/diff/types.ts b/src/core/diff/types.ts
index e12a47762d..be6d8cd311 100644
--- a/src/core/diff/types.ts
+++ b/src/core/diff/types.ts
@@ -2,9 +2,6 @@
* Interface for implementing different diff strategies
*/
-import { ToolProgressStatus } from "../../shared/ExtensionMessage"
-import { ToolUse } from "../assistant-message"
-
export type DiffResult =
| { success: true; content: string; failParts?: DiffResult[] }
| ({
@@ -37,6 +34,4 @@ export interface DiffStrategy {
* @returns A DiffResult object containing either the successful result or error details
*/
applyDiff(originalContent: string, diffContent: string, startLine?: number, endLine?: number): Promise
-
- getProgressStatus?(toolUse: ToolUse, result?: any): ToolProgressStatus
}
diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts
index 0c20669ed1..7487d338b1 100644
--- a/src/shared/ExtensionMessage.ts
+++ b/src/shared/ExtensionMessage.ts
@@ -155,7 +155,6 @@ export interface ClineMessage {
reasoning?: string
conversationHistoryIndex?: number
checkpoint?: Record
- progressStatus?: ToolProgressStatus
}
export type ClineAsk =
@@ -275,7 +274,3 @@ export interface HumanRelayCancelMessage {
}
export type ClineApiReqCancelReason = "streaming_failed" | "user_cancelled"
-
-export type ToolProgressStatus = {
- text?: string
-}
diff --git a/webview-ui/src/components/chat/ChatRow.tsx b/webview-ui/src/components/chat/ChatRow.tsx
index b19d67dc05..259c03fa21 100644
--- a/webview-ui/src/components/chat/ChatRow.tsx
+++ b/webview-ui/src/components/chat/ChatRow.tsx
@@ -258,7 +258,6 @@ export const ChatRowContent = ({
Roo wants to edit this file:
void
isLoading?: boolean
- progressStatus?: ToolProgressStatus
}
/*
@@ -34,7 +32,6 @@ const CodeAccordian = ({
isExpanded,
onToggleExpand,
isLoading,
- progressStatus,
}: CodeAccordianProps) => {
const inferredLanguage = useMemo(
() => code && (language ?? (path ? getLanguageFromPath(path) : undefined)),
@@ -98,16 +95,6 @@ const CodeAccordian = ({
>
)}
- {progressStatus && progressStatus.text && (
-
- {progressStatus.text}
-
- )}
)}
From c9794d24525ebc1566f75f5e0b4bf6e757dba0d1 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sun, 9 Mar 2025 18:36:42 -0400
Subject: [PATCH 26/29] Changeset
---
.changeset/empty-bees-suffer.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/empty-bees-suffer.md
diff --git a/.changeset/empty-bees-suffer.md b/.changeset/empty-bees-suffer.md
new file mode 100644
index 0000000000..e3d87a51ad
--- /dev/null
+++ b/.changeset/empty-bees-suffer.md
@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+Revert tool progress for now
From 6bcb39f0a1c1d066363edab18d77d6894f06b2e0 Mon Sep 17 00:00:00 2001
From: Hannes Rudolph <49103247+hannesrudolph@users.noreply.github.com>
Date: Sun, 9 Mar 2025 16:45:47 -0600
Subject: [PATCH 27/29] Update
webview-ui/src/components/prompts/PromptsView.tsx
Co-authored-by: Matt Rubens
---
webview-ui/src/components/prompts/PromptsView.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index 7303f7691d..9307c0d7a8 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -1037,7 +1037,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
// The React context will update the global state
setEnableCustomModeCreation(e.target.checked)
}}>
- Enable Custom Mode Creation
+ Enable Custom Mode Creation Through Prompts
Date: Sun, 9 Mar 2025 16:45:53 -0600
Subject: [PATCH 28/29] Update
webview-ui/src/components/prompts/PromptsView.tsx
Co-authored-by: Matt Rubens
---
webview-ui/src/components/prompts/PromptsView.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx
index 9307c0d7a8..6c69bc4229 100644
--- a/webview-ui/src/components/prompts/PromptsView.tsx
+++ b/webview-ui/src/components/prompts/PromptsView.tsx
@@ -1047,7 +1047,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => {
}}>
When enabled, Roo allows you to create custom modes using prompts like ‘Make me a custom
mode that…’. Disabling this reduces your system prompt by about 700 tokens when this feature
- isn’t needed. When disabled you can still manually create custom prompts using the + button
+ isn’t needed. When disabled you can still manually create custom modes using the + button
above or by editing the related config JSON.
From 6b0e377afc521e31de52d5f3b366ff0fe5269986 Mon Sep 17 00:00:00 2001
From: Matt Rubens
Date: Sun, 9 Mar 2025 19:42:33 -0400
Subject: [PATCH 29/29] v3.8.4
---
.changeset/sixty-ants-begin.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 .changeset/sixty-ants-begin.md
diff --git a/.changeset/sixty-ants-begin.md b/.changeset/sixty-ants-begin.md
new file mode 100644
index 0000000000..5ef9e04868
--- /dev/null
+++ b/.changeset/sixty-ants-begin.md
@@ -0,0 +1,5 @@
+---
+"roo-cline": patch
+---
+
+v3.8.4