Skip to content

Commit 9732958

Browse files
authored
Webview message handler + terminal settings cleanup (#3189)
1 parent 904f71c commit 9732958

File tree

16 files changed

+182
-154
lines changed

16 files changed

+182
-154
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { WebviewMessage } from "../../shared/WebviewMessage"
2+
import { defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes"
3+
import { buildApiHandler } from "../../api"
4+
5+
import { SYSTEM_PROMPT } from "../prompts/system"
6+
import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace"
7+
8+
import { ClineProvider } from "./ClineProvider"
9+
10+
export const generateSystemPrompt = async (provider: ClineProvider, message: WebviewMessage) => {
11+
const {
12+
apiConfiguration,
13+
customModePrompts,
14+
customInstructions,
15+
browserViewportSize,
16+
diffEnabled,
17+
mcpEnabled,
18+
fuzzyMatchThreshold,
19+
experiments,
20+
enableMcpServerCreation,
21+
browserToolEnabled,
22+
language,
23+
} = await provider.getState()
24+
25+
const diffStrategy = new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)
26+
27+
const cwd = provider.cwd
28+
29+
const mode = message.mode ?? defaultModeSlug
30+
const customModes = await provider.customModesManager.getCustomModes()
31+
32+
const rooIgnoreInstructions = provider.getCurrentCline()?.rooIgnoreController?.getInstructions()
33+
34+
// Determine if browser tools can be used based on model support, mode, and user settings
35+
let modelSupportsComputerUse = false
36+
37+
// Create a temporary API handler to check if the model supports computer use
38+
// This avoids relying on an active Cline instance which might not exist during preview
39+
try {
40+
const tempApiHandler = buildApiHandler(apiConfiguration)
41+
modelSupportsComputerUse = tempApiHandler.getModel().info.supportsComputerUse ?? false
42+
} catch (error) {
43+
console.error("Error checking if model supports computer use:", error)
44+
}
45+
46+
// Check if the current mode includes the browser tool group
47+
const modeConfig = getModeBySlug(mode, customModes)
48+
const modeSupportsBrowser = modeConfig?.groups.some((group) => getGroupName(group) === "browser") ?? false
49+
50+
// Only enable browser tools if the model supports it, the mode includes browser tools,
51+
// and browser tools are enabled in settings
52+
const canUseBrowserTool = modelSupportsComputerUse && modeSupportsBrowser && (browserToolEnabled ?? true)
53+
54+
const systemPrompt = await SYSTEM_PROMPT(
55+
provider.context,
56+
cwd,
57+
canUseBrowserTool,
58+
mcpEnabled ? provider.getMcpHub() : undefined,
59+
diffStrategy,
60+
browserViewportSize ?? "900x600",
61+
mode,
62+
customModePrompts,
63+
customModes,
64+
customInstructions,
65+
diffEnabled,
66+
experiments,
67+
enableMcpServerCreation,
68+
language,
69+
rooIgnoreInstructions,
70+
)
71+
72+
return systemPrompt
73+
}

src/core/webview/webviewMessageHandler.ts

Lines changed: 45 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ import { openMention } from "../mentions"
3232
import { telemetryService } from "../../services/telemetry/TelemetryService"
3333
import { TelemetrySetting } from "../../shared/TelemetrySetting"
3434
import { getWorkspacePath } from "../../utils/path"
35-
import { Mode, defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes"
36-
import { SYSTEM_PROMPT } from "../prompts/system"
37-
import { buildApiHandler } from "../../api"
35+
import { Mode, defaultModeSlug } from "../../shared/modes"
3836
import { GlobalState } from "../../schemas"
39-
import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace"
4037
import { getModels } from "../../api/providers/fetchers/cache"
38+
import { generateSystemPrompt } from "./generateSystemPrompt"
39+
40+
const ALLOWED_VSCODE_SETTINGS = new Set(["terminal.integrated.inheritEnv"])
4141

4242
export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => {
4343
// Utility functions provided for concise get/update of global state via contextProxy API.
@@ -128,14 +128,9 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
128128
provider.isViewLaunched = true
129129
break
130130
case "newTask":
131-
// Code that should run in response to the hello message command
132-
//vscode.window.showInformationMessage(message.text!)
133-
134-
// Send a message to our webview.
135-
// You can send any JSON serializable data.
136-
// Could also do this in extension .ts
137-
//provider.postMessageToWebview({ type: "text", text: `Extension: ${Date.now()}` })
138-
// initializing new instance of Cline will make sure that any agentically running promises in old instance don't affect our new task. this essentially creates a fresh slate for the new task
131+
// Initializing new instance of Cline will make sure that any
132+
// agentically running promises in old instance don't affect our new
133+
// task. This essentially creates a fresh slate for the new task.
139134
await provider.initClineWithTask(message.text, message.images)
140135
break
141136
case "apiConfiguration":
@@ -375,16 +370,29 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
375370
break
376371
case "allowedCommands":
377372
await provider.context.globalState.update("allowedCommands", message.commands)
378-
// Also update workspace settings
373+
374+
// Also update workspace settings.
379375
await vscode.workspace
380376
.getConfiguration("roo-cline")
381377
.update("allowedCommands", message.commands, vscode.ConfigurationTarget.Global)
378+
379+
break
380+
case "openCustomModesSettings": {
381+
const customModesFilePath = await provider.customModesManager.getCustomModesFilePath()
382+
383+
if (customModesFilePath) {
384+
openFile(customModesFilePath)
385+
}
386+
382387
break
388+
}
383389
case "openMcpSettings": {
384390
const mcpSettingsFilePath = await provider.getMcpHub()?.getMcpSettingsFilePath()
391+
385392
if (mcpSettingsFilePath) {
386393
openFile(mcpSettingsFilePath)
387394
}
395+
388396
break
389397
}
390398
case "openProjectMcpSettings": {
@@ -400,20 +408,16 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
400408
try {
401409
await fs.mkdir(rooDir, { recursive: true })
402410
const exists = await fileExistsAtPath(mcpPath)
411+
403412
if (!exists) {
404413
await fs.writeFile(mcpPath, JSON.stringify({ mcpServers: {} }, null, 2))
405414
}
415+
406416
await openFile(mcpPath)
407417
} catch (error) {
408418
vscode.window.showErrorMessage(t("common:errors.create_mcp_json", { error: `${error}` }))
409419
}
410-
break
411-
}
412-
case "openCustomModesSettings": {
413-
const customModesFilePath = await provider.customModesManager.getCustomModesFilePath()
414-
if (customModesFilePath) {
415-
openFile(customModesFilePath)
416-
}
420+
417421
break
418422
}
419423
case "deleteMcpServer": {
@@ -559,6 +563,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
559563
if (!message.text) {
560564
// Use testBrowserConnection for auto-discovery
561565
const chromeHostUrl = await discoverChromeHostUrl()
566+
562567
if (chromeHostUrl) {
563568
// Send the result back to the webview
564569
await provider.postMessageToWebview({
@@ -578,6 +583,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
578583
// Test the provided URL
579584
const customHostUrl = message.text
580585
const hostIsValid = await tryChromeHostUrl(message.text)
586+
581587
// Send the result back to the webview
582588
await provider.postMessageToWebview({
583589
type: "browserConnectionResult",
@@ -593,35 +599,40 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
593599
await provider.postStateToWebview()
594600
break
595601
case "updateVSCodeSetting": {
596-
// Allowlist of VSCode settings that can be updated
597-
// Add new settings here when needed for future expansion
598-
const ALLOWED_VSCODE_SETTINGS = ["terminal.integrated.inheritEnv"] as const
599-
600-
if (message.setting && message.value !== undefined) {
601-
if (!ALLOWED_VSCODE_SETTINGS.includes(message.setting as (typeof ALLOWED_VSCODE_SETTINGS)[number])) {
602-
provider.log(`Attempted to update restricted VSCode setting: ${message.setting}`)
603-
vscode.window.showErrorMessage(`Cannot update restricted VSCode setting: ${message.setting}`)
604-
break
602+
const { setting, value } = message
603+
604+
if (setting !== undefined && value !== undefined) {
605+
if (ALLOWED_VSCODE_SETTINGS.has(setting)) {
606+
await vscode.workspace.getConfiguration().update(setting, value, true)
607+
} else {
608+
vscode.window.showErrorMessage(`Cannot update restricted VSCode setting: ${setting}`)
605609
}
606-
await vscode.workspace.getConfiguration().update(message.setting, message.value, true)
607610
}
611+
608612
break
609613
}
610614
case "getVSCodeSetting":
611-
if (message.setting) {
615+
const { setting } = message
616+
617+
if (setting) {
612618
try {
613-
const value = vscode.workspace.getConfiguration().get(message.setting)
614-
await provider.postMessageToWebview({ type: "vsCodeSetting", setting: message.setting, value })
619+
await provider.postMessageToWebview({
620+
type: "vsCodeSetting",
621+
setting,
622+
value: vscode.workspace.getConfiguration().get(setting),
623+
})
615624
} catch (error) {
616625
console.error(`Failed to get VSCode setting ${message.setting}:`, error)
626+
617627
await provider.postMessageToWebview({
618628
type: "vsCodeSetting",
619-
setting: message.setting,
629+
setting,
620630
error: `Failed to get setting: ${error.message}`,
621631
value: undefined,
622632
})
623633
}
624634
}
635+
625636
break
626637
case "alwaysApproveResubmit":
627638
await updateGlobalState("alwaysApproveResubmit", message.bool ?? false)
@@ -1290,68 +1301,3 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
12901301
}
12911302
}
12921303
}
1293-
1294-
const generateSystemPrompt = async (provider: ClineProvider, message: WebviewMessage) => {
1295-
const {
1296-
apiConfiguration,
1297-
customModePrompts,
1298-
customInstructions,
1299-
browserViewportSize,
1300-
diffEnabled,
1301-
mcpEnabled,
1302-
fuzzyMatchThreshold,
1303-
experiments,
1304-
enableMcpServerCreation,
1305-
browserToolEnabled,
1306-
language,
1307-
} = await provider.getState()
1308-
1309-
const diffStrategy = new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)
1310-
1311-
const cwd = provider.cwd
1312-
1313-
const mode = message.mode ?? defaultModeSlug
1314-
const customModes = await provider.customModesManager.getCustomModes()
1315-
1316-
const rooIgnoreInstructions = provider.getCurrentCline()?.rooIgnoreController?.getInstructions()
1317-
1318-
// Determine if browser tools can be used based on model support, mode, and user settings
1319-
let modelSupportsComputerUse = false
1320-
1321-
// Create a temporary API handler to check if the model supports computer use
1322-
// This avoids relying on an active Cline instance which might not exist during preview
1323-
try {
1324-
const tempApiHandler = buildApiHandler(apiConfiguration)
1325-
modelSupportsComputerUse = tempApiHandler.getModel().info.supportsComputerUse ?? false
1326-
} catch (error) {
1327-
console.error("Error checking if model supports computer use:", error)
1328-
}
1329-
1330-
// Check if the current mode includes the browser tool group
1331-
const modeConfig = getModeBySlug(mode, customModes)
1332-
const modeSupportsBrowser = modeConfig?.groups.some((group) => getGroupName(group) === "browser") ?? false
1333-
1334-
// Only enable browser tools if the model supports it, the mode includes browser tools,
1335-
// and browser tools are enabled in settings
1336-
const canUseBrowserTool = modelSupportsComputerUse && modeSupportsBrowser && (browserToolEnabled ?? true)
1337-
1338-
const systemPrompt = await SYSTEM_PROMPT(
1339-
provider.context,
1340-
cwd,
1341-
canUseBrowserTool,
1342-
mcpEnabled ? provider.getMcpHub() : undefined,
1343-
diffStrategy,
1344-
browserViewportSize ?? "900x600",
1345-
mode,
1346-
customModePrompts,
1347-
customModes,
1348-
customInstructions,
1349-
diffEnabled,
1350-
experiments,
1351-
enableMcpServerCreation,
1352-
language,
1353-
rooIgnoreInstructions,
1354-
)
1355-
1356-
return systemPrompt
1357-
}

src/shared/ExtensionMessage.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ export interface ExtensionMessage {
107107
error?: string
108108
setting?: string
109109
value?: any
110-
vscodeSettingValue?: unknown
111110
}
112111

113112
export type ExtensionState = Pick<

src/shared/WebviewMessage.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ export interface WebviewMessage {
137137
images?: string[]
138138
bool?: boolean
139139
value?: number
140-
vscodeSettingValue?: unknown
141140
commands?: string[]
142141
audioType?: AudioType
143142
serverName?: string

0 commit comments

Comments
 (0)