|
|
@@ -32,12 +32,12 @@ import { openMention } from "../mentions"
|
|
|
import { telemetryService } from "../../services/telemetry/TelemetryService"
|
|
|
import { TelemetrySetting } from "../../shared/TelemetrySetting"
|
|
|
import { getWorkspacePath } from "../../utils/path"
|
|
|
-import { Mode, defaultModeSlug, getModeBySlug, getGroupName } from "../../shared/modes"
|
|
|
-import { SYSTEM_PROMPT } from "../prompts/system"
|
|
|
-import { buildApiHandler } from "../../api"
|
|
|
+import { Mode, defaultModeSlug } from "../../shared/modes"
|
|
|
import { GlobalState } from "../../schemas"
|
|
|
-import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace"
|
|
|
import { getModels } from "../../api/providers/fetchers/cache"
|
|
|
+import { generateSystemPrompt } from "./generateSystemPrompt"
|
|
|
+
|
|
|
+const ALLOWED_VSCODE_SETTINGS = new Set(["terminal.integrated.inheritEnv"])
|
|
|
|
|
|
export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => {
|
|
|
// 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
|
|
|
provider.isViewLaunched = true
|
|
|
break
|
|
|
case "newTask":
|
|
|
- // Code that should run in response to the hello message command
|
|
|
- //vscode.window.showInformationMessage(message.text!)
|
|
|
-
|
|
|
- // Send a message to our webview.
|
|
|
- // You can send any JSON serializable data.
|
|
|
- // Could also do this in extension .ts
|
|
|
- //provider.postMessageToWebview({ type: "text", text: `Extension: ${Date.now()}` })
|
|
|
- // 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
|
|
|
+ // 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.
|
|
|
await provider.initClineWithTask(message.text, message.images)
|
|
|
break
|
|
|
case "apiConfiguration":
|
|
|
@@ -375,16 +370,29 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|
|
break
|
|
|
case "allowedCommands":
|
|
|
await provider.context.globalState.update("allowedCommands", message.commands)
|
|
|
- // Also update workspace settings
|
|
|
+
|
|
|
+ // Also update workspace settings.
|
|
|
await vscode.workspace
|
|
|
.getConfiguration("roo-cline")
|
|
|
.update("allowedCommands", message.commands, vscode.ConfigurationTarget.Global)
|
|
|
+
|
|
|
+ break
|
|
|
+ case "openCustomModesSettings": {
|
|
|
+ const customModesFilePath = await provider.customModesManager.getCustomModesFilePath()
|
|
|
+
|
|
|
+ if (customModesFilePath) {
|
|
|
+ openFile(customModesFilePath)
|
|
|
+ }
|
|
|
+
|
|
|
break
|
|
|
+ }
|
|
|
case "openMcpSettings": {
|
|
|
const mcpSettingsFilePath = await provider.getMcpHub()?.getMcpSettingsFilePath()
|
|
|
+
|
|
|
if (mcpSettingsFilePath) {
|
|
|
openFile(mcpSettingsFilePath)
|
|
|
}
|
|
|
+
|
|
|
break
|
|
|
}
|
|
|
case "openProjectMcpSettings": {
|
|
|
@@ -400,20 +408,16 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|
|
try {
|
|
|
await fs.mkdir(rooDir, { recursive: true })
|
|
|
const exists = await fileExistsAtPath(mcpPath)
|
|
|
+
|
|
|
if (!exists) {
|
|
|
await fs.writeFile(mcpPath, JSON.stringify({ mcpServers: {} }, null, 2))
|
|
|
}
|
|
|
+
|
|
|
await openFile(mcpPath)
|
|
|
} catch (error) {
|
|
|
vscode.window.showErrorMessage(t("common:errors.create_mcp_json", { error: `${error}` }))
|
|
|
}
|
|
|
- break
|
|
|
- }
|
|
|
- case "openCustomModesSettings": {
|
|
|
- const customModesFilePath = await provider.customModesManager.getCustomModesFilePath()
|
|
|
- if (customModesFilePath) {
|
|
|
- openFile(customModesFilePath)
|
|
|
- }
|
|
|
+
|
|
|
break
|
|
|
}
|
|
|
case "deleteMcpServer": {
|
|
|
@@ -559,6 +563,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|
|
if (!message.text) {
|
|
|
// Use testBrowserConnection for auto-discovery
|
|
|
const chromeHostUrl = await discoverChromeHostUrl()
|
|
|
+
|
|
|
if (chromeHostUrl) {
|
|
|
// Send the result back to the webview
|
|
|
await provider.postMessageToWebview({
|
|
|
@@ -578,6 +583,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|
|
// Test the provided URL
|
|
|
const customHostUrl = message.text
|
|
|
const hostIsValid = await tryChromeHostUrl(message.text)
|
|
|
+
|
|
|
// Send the result back to the webview
|
|
|
await provider.postMessageToWebview({
|
|
|
type: "browserConnectionResult",
|
|
|
@@ -593,35 +599,40 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|
|
await provider.postStateToWebview()
|
|
|
break
|
|
|
case "updateVSCodeSetting": {
|
|
|
- // Allowlist of VSCode settings that can be updated
|
|
|
- // Add new settings here when needed for future expansion
|
|
|
- const ALLOWED_VSCODE_SETTINGS = ["terminal.integrated.inheritEnv"] as const
|
|
|
-
|
|
|
- if (message.setting && message.value !== undefined) {
|
|
|
- if (!ALLOWED_VSCODE_SETTINGS.includes(message.setting as (typeof ALLOWED_VSCODE_SETTINGS)[number])) {
|
|
|
- provider.log(`Attempted to update restricted VSCode setting: ${message.setting}`)
|
|
|
- vscode.window.showErrorMessage(`Cannot update restricted VSCode setting: ${message.setting}`)
|
|
|
- break
|
|
|
+ const { setting, value } = message
|
|
|
+
|
|
|
+ if (setting !== undefined && value !== undefined) {
|
|
|
+ if (ALLOWED_VSCODE_SETTINGS.has(setting)) {
|
|
|
+ await vscode.workspace.getConfiguration().update(setting, value, true)
|
|
|
+ } else {
|
|
|
+ vscode.window.showErrorMessage(`Cannot update restricted VSCode setting: ${setting}`)
|
|
|
}
|
|
|
- await vscode.workspace.getConfiguration().update(message.setting, message.value, true)
|
|
|
}
|
|
|
+
|
|
|
break
|
|
|
}
|
|
|
case "getVSCodeSetting":
|
|
|
- if (message.setting) {
|
|
|
+ const { setting } = message
|
|
|
+
|
|
|
+ if (setting) {
|
|
|
try {
|
|
|
- const value = vscode.workspace.getConfiguration().get(message.setting)
|
|
|
- await provider.postMessageToWebview({ type: "vsCodeSetting", setting: message.setting, value })
|
|
|
+ await provider.postMessageToWebview({
|
|
|
+ type: "vsCodeSetting",
|
|
|
+ setting,
|
|
|
+ value: vscode.workspace.getConfiguration().get(setting),
|
|
|
+ })
|
|
|
} catch (error) {
|
|
|
console.error(`Failed to get VSCode setting ${message.setting}:`, error)
|
|
|
+
|
|
|
await provider.postMessageToWebview({
|
|
|
type: "vsCodeSetting",
|
|
|
- setting: message.setting,
|
|
|
+ setting,
|
|
|
error: `Failed to get setting: ${error.message}`,
|
|
|
value: undefined,
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
break
|
|
|
case "alwaysApproveResubmit":
|
|
|
await updateGlobalState("alwaysApproveResubmit", message.bool ?? false)
|
|
|
@@ -1290,68 +1301,3 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
-const generateSystemPrompt = async (provider: ClineProvider, message: WebviewMessage) => {
|
|
|
- const {
|
|
|
- apiConfiguration,
|
|
|
- customModePrompts,
|
|
|
- customInstructions,
|
|
|
- browserViewportSize,
|
|
|
- diffEnabled,
|
|
|
- mcpEnabled,
|
|
|
- fuzzyMatchThreshold,
|
|
|
- experiments,
|
|
|
- enableMcpServerCreation,
|
|
|
- browserToolEnabled,
|
|
|
- language,
|
|
|
- } = await provider.getState()
|
|
|
-
|
|
|
- const diffStrategy = new MultiSearchReplaceDiffStrategy(fuzzyMatchThreshold)
|
|
|
-
|
|
|
- const cwd = provider.cwd
|
|
|
-
|
|
|
- const mode = message.mode ?? defaultModeSlug
|
|
|
- const customModes = await provider.customModesManager.getCustomModes()
|
|
|
-
|
|
|
- const rooIgnoreInstructions = provider.getCurrentCline()?.rooIgnoreController?.getInstructions()
|
|
|
-
|
|
|
- // Determine if browser tools can be used based on model support, mode, and user settings
|
|
|
- let modelSupportsComputerUse = false
|
|
|
-
|
|
|
- // Create a temporary API handler to check if the model supports computer use
|
|
|
- // This avoids relying on an active Cline instance which might not exist during preview
|
|
|
- try {
|
|
|
- const tempApiHandler = buildApiHandler(apiConfiguration)
|
|
|
- modelSupportsComputerUse = tempApiHandler.getModel().info.supportsComputerUse ?? false
|
|
|
- } catch (error) {
|
|
|
- console.error("Error checking if model supports computer use:", error)
|
|
|
- }
|
|
|
-
|
|
|
- // Check if the current mode includes the browser tool group
|
|
|
- const modeConfig = getModeBySlug(mode, customModes)
|
|
|
- const modeSupportsBrowser = modeConfig?.groups.some((group) => getGroupName(group) === "browser") ?? false
|
|
|
-
|
|
|
- // Only enable browser tools if the model supports it, the mode includes browser tools,
|
|
|
- // and browser tools are enabled in settings
|
|
|
- const canUseBrowserTool = modelSupportsComputerUse && modeSupportsBrowser && (browserToolEnabled ?? true)
|
|
|
-
|
|
|
- const systemPrompt = await SYSTEM_PROMPT(
|
|
|
- provider.context,
|
|
|
- cwd,
|
|
|
- canUseBrowserTool,
|
|
|
- mcpEnabled ? provider.getMcpHub() : undefined,
|
|
|
- diffStrategy,
|
|
|
- browserViewportSize ?? "900x600",
|
|
|
- mode,
|
|
|
- customModePrompts,
|
|
|
- customModes,
|
|
|
- customInstructions,
|
|
|
- diffEnabled,
|
|
|
- experiments,
|
|
|
- enableMcpServerCreation,
|
|
|
- language,
|
|
|
- rooIgnoreInstructions,
|
|
|
- )
|
|
|
-
|
|
|
- return systemPrompt
|
|
|
-}
|