mirror of
https://github.com/cline/cline.git
synced 2025-06-03 03:59:07 +00:00
Migrate toggle tool auto approve protobus (#3614)
* migrate toggleToolAutoApprove * changset --------- Co-authored-by: Elephant Lumps <celestial_vault@Elephants-MacBook-Pro.local>
This commit is contained in:
parent
6b243ee826
commit
78c3c5eff2
5
.changeset/good-dingos-try.md
Normal file
5
.changeset/good-dingos-try.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
Migrate toggleToolAutoApprove to protobus
|
@ -13,6 +13,7 @@ service McpService {
|
||||
rpc downloadMcp(StringRequest) returns (Empty);
|
||||
rpc restartMcpServer(StringRequest) returns (McpServers);
|
||||
rpc deleteMcpServer(StringRequest) returns (McpServers);
|
||||
rpc toggleToolAutoApprove(ToggleToolAutoApproveRequest) returns (McpServers);
|
||||
}
|
||||
|
||||
message ToggleMcpServerRequest {
|
||||
@ -33,6 +34,13 @@ message AddRemoteMcpServerRequest {
|
||||
string server_url = 3;
|
||||
}
|
||||
|
||||
message ToggleToolAutoApproveRequest {
|
||||
Metadata metadata = 1;
|
||||
string server_name = 2;
|
||||
repeated string tool_names = 3;
|
||||
bool auto_approve = 4;
|
||||
}
|
||||
|
||||
message McpTool {
|
||||
string name = 1;
|
||||
optional string description = 2;
|
||||
|
@ -394,21 +394,6 @@ export class Controller {
|
||||
|
||||
// break
|
||||
// }
|
||||
case "toggleToolAutoApprove": {
|
||||
try {
|
||||
await this.mcpHub?.toggleToolAutoApprove(message.serverName!, message.toolNames!, message.autoApprove!)
|
||||
} catch (error) {
|
||||
if (message.toolNames?.length === 1) {
|
||||
console.error(
|
||||
`Failed to toggle auto-approve for server ${message.serverName} with tool ${message.toolNames[0]}:`,
|
||||
error,
|
||||
)
|
||||
} else {
|
||||
console.error(`Failed to toggle auto-approve tools for server ${message.serverName}:`, error)
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case "toggleWindsurfRule": {
|
||||
const { rulePath, enabled } = message
|
||||
if (rulePath && typeof enabled === "boolean") {
|
||||
|
@ -8,6 +8,7 @@ import { deleteMcpServer } from "./deleteMcpServer"
|
||||
import { downloadMcp } from "./downloadMcp"
|
||||
import { restartMcpServer } from "./restartMcpServer"
|
||||
import { toggleMcpServer } from "./toggleMcpServer"
|
||||
import { toggleToolAutoApprove } from "./toggleToolAutoApprove"
|
||||
import { updateMcpTimeout } from "./updateMcpTimeout"
|
||||
|
||||
// Register all mcp service methods
|
||||
@ -18,5 +19,6 @@ export function registerAllMethods(): void {
|
||||
registerMethod("downloadMcp", downloadMcp)
|
||||
registerMethod("restartMcpServer", restartMcpServer)
|
||||
registerMethod("toggleMcpServer", toggleMcpServer)
|
||||
registerMethod("toggleToolAutoApprove", toggleToolAutoApprove)
|
||||
registerMethod("updateMcpTimeout", updateMcpTimeout)
|
||||
}
|
||||
|
23
src/core/controller/mcp/toggleToolAutoApprove.ts
Normal file
23
src/core/controller/mcp/toggleToolAutoApprove.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import type { ToggleToolAutoApproveRequest, McpServers } from "@shared/proto/mcp"
|
||||
import type { Controller } from "../index"
|
||||
import { convertMcpServersToProtoMcpServers } from "@shared/proto-conversions/mcp/mcp-server-conversion"
|
||||
|
||||
/**
|
||||
* Toggles auto-approve setting for MCP server tools
|
||||
* @param controller The controller instance
|
||||
* @param request The toggle tool auto-approve request
|
||||
* @returns Updated list of MCP servers
|
||||
*/
|
||||
export async function toggleToolAutoApprove(controller: Controller, request: ToggleToolAutoApproveRequest): Promise<McpServers> {
|
||||
try {
|
||||
// Call the RPC variant that returns the servers directly
|
||||
const mcpServers =
|
||||
(await controller.mcpHub?.toggleToolAutoApproveRPC(request.serverName, request.toolNames, request.autoApprove)) || []
|
||||
|
||||
// Convert application types to proto types
|
||||
return { mcpServers: convertMcpServersToProtoMcpServers(mcpServers) }
|
||||
} catch (error) {
|
||||
console.error(`Failed to toggle tool auto-approve for ${request.serverName}:`, error)
|
||||
throw error
|
||||
}
|
||||
}
|
@ -793,6 +793,58 @@ export class McpHub {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* RPC variant of toggleToolAutoApprove that returns the updated servers instead of notifying the webview
|
||||
* @param serverName The name of the MCP server
|
||||
* @param toolNames Array of tool names to toggle auto-approve for
|
||||
* @param shouldAllow Whether to enable or disable auto-approve
|
||||
* @returns Array of updated MCP servers
|
||||
*/
|
||||
async toggleToolAutoApproveRPC(serverName: string, toolNames: string[], shouldAllow: boolean): Promise<McpServer[]> {
|
||||
try {
|
||||
const settingsPath = await this.getMcpSettingsFilePath()
|
||||
const content = await fs.readFile(settingsPath, "utf-8")
|
||||
const config = JSON.parse(content)
|
||||
|
||||
// Initialize autoApprove if it doesn't exist
|
||||
if (!config.mcpServers[serverName].autoApprove) {
|
||||
config.mcpServers[serverName].autoApprove = []
|
||||
}
|
||||
|
||||
const autoApprove = config.mcpServers[serverName].autoApprove
|
||||
for (const toolName of toolNames) {
|
||||
const toolIndex = autoApprove.indexOf(toolName)
|
||||
|
||||
if (shouldAllow && toolIndex === -1) {
|
||||
// Add tool to autoApprove list
|
||||
autoApprove.push(toolName)
|
||||
} else if (!shouldAllow && toolIndex !== -1) {
|
||||
// Remove tool from autoApprove list
|
||||
autoApprove.splice(toolIndex, 1)
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeFile(settingsPath, JSON.stringify(config, null, 2))
|
||||
|
||||
// Update the tools list to reflect the change
|
||||
const connection = this.connections.find((conn) => conn.server.name === serverName)
|
||||
if (connection && connection.server.tools) {
|
||||
// Update the autoApprove property of each tool in the in-memory server object
|
||||
connection.server.tools = connection.server.tools.map((tool) => ({
|
||||
...tool,
|
||||
autoApprove: autoApprove.includes(tool.name),
|
||||
}))
|
||||
}
|
||||
|
||||
// Return sorted servers without notifying webview
|
||||
const serverOrder = Object.keys(config.mcpServers || {})
|
||||
return this.getSortedMcpServers(serverOrder)
|
||||
} catch (error) {
|
||||
console.error("Failed to update autoApprove settings:", error)
|
||||
throw error // Re-throw to ensure the error is properly handled
|
||||
}
|
||||
}
|
||||
|
||||
async toggleToolAutoApprove(serverName: string, toolNames: string[], shouldAllow: boolean): Promise<void> {
|
||||
try {
|
||||
const settingsPath = await this.getMcpSettingsFilePath()
|
||||
|
@ -24,7 +24,6 @@ export interface WebviewMessage {
|
||||
| "browserRelaunchResult"
|
||||
| "openExtensionSettings"
|
||||
| "requestVsCodeLmModels"
|
||||
| "toggleToolAutoApprove"
|
||||
| "showAccountViewClicked"
|
||||
| "authStateChanged"
|
||||
| "authCallback"
|
||||
|
@ -71,6 +71,13 @@ export interface AddRemoteMcpServerRequest {
|
||||
serverUrl: string
|
||||
}
|
||||
|
||||
export interface ToggleToolAutoApproveRequest {
|
||||
metadata?: Metadata | undefined
|
||||
serverName: string
|
||||
toolNames: string[]
|
||||
autoApprove: boolean
|
||||
}
|
||||
|
||||
export interface McpTool {
|
||||
name: string
|
||||
description?: string | undefined
|
||||
@ -387,6 +394,115 @@ export const AddRemoteMcpServerRequest: MessageFns<AddRemoteMcpServerRequest> =
|
||||
},
|
||||
}
|
||||
|
||||
function createBaseToggleToolAutoApproveRequest(): ToggleToolAutoApproveRequest {
|
||||
return { metadata: undefined, serverName: "", toolNames: [], autoApprove: false }
|
||||
}
|
||||
|
||||
export const ToggleToolAutoApproveRequest: MessageFns<ToggleToolAutoApproveRequest> = {
|
||||
encode(message: ToggleToolAutoApproveRequest, writer: BinaryWriter = new BinaryWriter()): BinaryWriter {
|
||||
if (message.metadata !== undefined) {
|
||||
Metadata.encode(message.metadata, writer.uint32(10).fork()).join()
|
||||
}
|
||||
if (message.serverName !== "") {
|
||||
writer.uint32(18).string(message.serverName)
|
||||
}
|
||||
for (const v of message.toolNames) {
|
||||
writer.uint32(26).string(v!)
|
||||
}
|
||||
if (message.autoApprove !== false) {
|
||||
writer.uint32(32).bool(message.autoApprove)
|
||||
}
|
||||
return writer
|
||||
},
|
||||
|
||||
decode(input: BinaryReader | Uint8Array, length?: number): ToggleToolAutoApproveRequest {
|
||||
const reader = input instanceof BinaryReader ? input : new BinaryReader(input)
|
||||
let end = length === undefined ? reader.len : reader.pos + length
|
||||
const message = createBaseToggleToolAutoApproveRequest()
|
||||
while (reader.pos < end) {
|
||||
const tag = reader.uint32()
|
||||
switch (tag >>> 3) {
|
||||
case 1: {
|
||||
if (tag !== 10) {
|
||||
break
|
||||
}
|
||||
|
||||
message.metadata = Metadata.decode(reader, reader.uint32())
|
||||
continue
|
||||
}
|
||||
case 2: {
|
||||
if (tag !== 18) {
|
||||
break
|
||||
}
|
||||
|
||||
message.serverName = reader.string()
|
||||
continue
|
||||
}
|
||||
case 3: {
|
||||
if (tag !== 26) {
|
||||
break
|
||||
}
|
||||
|
||||
message.toolNames.push(reader.string())
|
||||
continue
|
||||
}
|
||||
case 4: {
|
||||
if (tag !== 32) {
|
||||
break
|
||||
}
|
||||
|
||||
message.autoApprove = reader.bool()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if ((tag & 7) === 4 || tag === 0) {
|
||||
break
|
||||
}
|
||||
reader.skip(tag & 7)
|
||||
}
|
||||
return message
|
||||
},
|
||||
|
||||
fromJSON(object: any): ToggleToolAutoApproveRequest {
|
||||
return {
|
||||
metadata: isSet(object.metadata) ? Metadata.fromJSON(object.metadata) : undefined,
|
||||
serverName: isSet(object.serverName) ? globalThis.String(object.serverName) : "",
|
||||
toolNames: globalThis.Array.isArray(object?.toolNames) ? object.toolNames.map((e: any) => globalThis.String(e)) : [],
|
||||
autoApprove: isSet(object.autoApprove) ? globalThis.Boolean(object.autoApprove) : false,
|
||||
}
|
||||
},
|
||||
|
||||
toJSON(message: ToggleToolAutoApproveRequest): unknown {
|
||||
const obj: any = {}
|
||||
if (message.metadata !== undefined) {
|
||||
obj.metadata = Metadata.toJSON(message.metadata)
|
||||
}
|
||||
if (message.serverName !== "") {
|
||||
obj.serverName = message.serverName
|
||||
}
|
||||
if (message.toolNames?.length) {
|
||||
obj.toolNames = message.toolNames
|
||||
}
|
||||
if (message.autoApprove !== false) {
|
||||
obj.autoApprove = message.autoApprove
|
||||
}
|
||||
return obj
|
||||
},
|
||||
|
||||
create<I extends Exact<DeepPartial<ToggleToolAutoApproveRequest>, I>>(base?: I): ToggleToolAutoApproveRequest {
|
||||
return ToggleToolAutoApproveRequest.fromPartial(base ?? ({} as any))
|
||||
},
|
||||
fromPartial<I extends Exact<DeepPartial<ToggleToolAutoApproveRequest>, I>>(object: I): ToggleToolAutoApproveRequest {
|
||||
const message = createBaseToggleToolAutoApproveRequest()
|
||||
message.metadata =
|
||||
object.metadata !== undefined && object.metadata !== null ? Metadata.fromPartial(object.metadata) : undefined
|
||||
message.serverName = object.serverName ?? ""
|
||||
message.toolNames = object.toolNames?.map((e) => e) || []
|
||||
message.autoApprove = object.autoApprove ?? false
|
||||
return message
|
||||
},
|
||||
}
|
||||
|
||||
function createBaseMcpTool(): McpTool {
|
||||
return { name: "", description: undefined, inputSchema: undefined, autoApprove: undefined }
|
||||
}
|
||||
@ -1028,6 +1144,14 @@ export const McpServiceDefinition = {
|
||||
responseStream: false,
|
||||
options: {},
|
||||
},
|
||||
toggleToolAutoApprove: {
|
||||
name: "toggleToolAutoApprove",
|
||||
requestType: ToggleToolAutoApproveRequest,
|
||||
requestStream: false,
|
||||
responseType: McpServers,
|
||||
responseStream: false,
|
||||
options: {},
|
||||
},
|
||||
},
|
||||
} as const
|
||||
|
||||
|
@ -39,6 +39,7 @@ import { addRemoteMcpServer } from "../core/controller/mcp/addRemoteMcpServer"
|
||||
import { downloadMcp } from "../core/controller/mcp/downloadMcp"
|
||||
import { restartMcpServer } from "../core/controller/mcp/restartMcpServer"
|
||||
import { deleteMcpServer } from "../core/controller/mcp/deleteMcpServer"
|
||||
import { toggleToolAutoApprove } from "../core/controller/mcp/toggleToolAutoApprove"
|
||||
|
||||
// Models Service
|
||||
import { getOllamaModels } from "../core/controller/models/getOllamaModels"
|
||||
@ -131,6 +132,7 @@ export function addServices(
|
||||
downloadMcp: wrapper(downloadMcp, controller),
|
||||
restartMcpServer: wrapper(restartMcpServer, controller),
|
||||
deleteMcpServer: wrapper(deleteMcpServer, controller),
|
||||
toggleToolAutoApprove: wrapper(toggleToolAutoApprove, controller),
|
||||
})
|
||||
|
||||
// Models Service
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
import { McpTool } from "@shared/mcp"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { McpServiceClient } from "@/services/grpc-client"
|
||||
import { convertProtoMcpServersToMcpServers } from "@shared/proto-conversions/mcp/mcp-server-conversion"
|
||||
|
||||
type McpToolRowProps = {
|
||||
tool: McpTool
|
||||
@ -11,20 +12,26 @@ type McpToolRowProps = {
|
||||
const McpToolRow = ({ tool, serverName }: McpToolRowProps) => {
|
||||
const { autoApprovalSettings } = useExtensionState()
|
||||
|
||||
const { setMcpServers } = useExtensionState()
|
||||
|
||||
// Accept the event object
|
||||
const handleAutoApproveChange = (event: any) => {
|
||||
// Only proceed if the event was triggered by a direct user interaction
|
||||
|
||||
if (!serverName) {
|
||||
return
|
||||
}
|
||||
|
||||
vscode.postMessage({
|
||||
type: "toggleToolAutoApprove",
|
||||
McpServiceClient.toggleToolAutoApprove({
|
||||
serverName,
|
||||
toolNames: [tool.name],
|
||||
autoApprove: !tool.autoApprove,
|
||||
})
|
||||
.then((response) => {
|
||||
const mcpServers = convertProtoMcpServersToMcpServers(response.mcpServers)
|
||||
setMcpServers(mcpServers)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error toggling tool auto-approve", error)
|
||||
})
|
||||
}
|
||||
return (
|
||||
<div
|
||||
|
@ -134,12 +134,18 @@ const ServerRow = ({
|
||||
const handleAutoApproveChange = () => {
|
||||
if (!server.name) return
|
||||
|
||||
vscode.postMessage({
|
||||
type: "toggleToolAutoApprove",
|
||||
McpServiceClient.toggleToolAutoApprove({
|
||||
serverName: server.name,
|
||||
toolNames: server.tools?.map((tool) => tool.name) || [],
|
||||
autoApprove: !server.tools?.every((tool) => tool.autoApprove),
|
||||
})
|
||||
.then((response) => {
|
||||
const mcpServers = convertProtoMcpServersToMcpServers(response.mcpServers)
|
||||
setMcpServers(mcpServers)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error toggling all tools auto-approve", error)
|
||||
})
|
||||
}
|
||||
|
||||
const handleToggleMcpServer = () => {
|
||||
|
Loading…
Reference in New Issue
Block a user