-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathClientToolConfirmationEventHandler.swift
More file actions
126 lines (109 loc) · 4.33 KB
/
Copy pathClientToolConfirmationEventHandler.swift
File metadata and controls
126 lines (109 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import Foundation
import ConversationServiceProvider
import JSONRPC
extension ChatService {
typealias ToolConfirmationCompletion = (AnyJSONRPCResponse) -> Void
func handleClientToolConfirmationEvent(
request: InvokeClientToolConfirmationRequest,
completion: @escaping ToolConfirmationCompletion
) {
guard let params = request.params else { return }
guard isConversationIdValid(params.conversationId) else { return }
Task { [weak self] in
guard let self else { return }
let shouldAutoApprove = await shouldAutoApprove(params: params)
let parentTurnId = parentTurnIdForTurnId(params.turnId)
let toolCallStatus: AgentToolCall.ToolCallStatus = shouldAutoApprove
? .accepted
: .waitForConfirmation
appendToolCallHistory(
turnId: params.turnId,
editAgentRounds: makeEditAgentRounds(params: params, status: toolCallStatus),
parentTurnId: parentTurnId
)
let toolCallRequest = ToolCallRequest(
requestId: request.id,
turnId: params.turnId,
roundId: params.roundId,
toolCallId: params.toolCallId,
completion: completion
)
if shouldAutoApprove {
sendToolConfirmationResponse(toolCallRequest, accepted: true)
} else {
storePendingToolCallRequest(toolCallId: params.toolCallId, request: toolCallRequest)
}
}
}
private func shouldAutoApprove(params: InvokeClientToolParams) async -> Bool {
let mcpServerName = ToolAutoApprovalManager.extractMCPServerName(from: params.title ?? "")
let confirmationMessage = params.message ?? ""
if ToolAutoApprovalManager.isTerminalOperation(name: params.name) {
let commandLine = params.input?["command"]?.value as? String
let allowed = await ToolAutoApprovalManager.shared.isTerminalAllowed(
conversationId: params.conversationId,
commandLine: commandLine
)
if allowed {
return true
}
}
if ToolAutoApprovalManager.isFetchWebPageOperation(name: params.name) {
let urls = ToolAutoApprovalManager.extractFetchWebPageURLs(from: params.input)
let allowed = await ToolAutoApprovalManager.shared.isFetchWebPageAllowed(
conversationId: params.conversationId,
urls: urls
)
if allowed {
return true
}
}
if let mcpServerName {
let allowed = await ToolAutoApprovalManager.shared.isMCPAllowed(
conversationId: params.conversationId,
serverName: mcpServerName,
toolName: params.name
)
if allowed {
return true
}
let globalAllowed = await ToolAutoApprovalManager.shared.isMCPAllowedGlobally(
serverName: mcpServerName,
toolName: params.name
)
if globalAllowed {
return true
}
}
if ToolAutoApprovalManager.isSensitiveFileOperation(message: confirmationMessage) {
let info = ToolAutoApprovalManager.extractSensitiveFileConfirmationInfo(from: confirmationMessage)
let fileKey = info.sessionKey
let allowed = await ToolAutoApprovalManager.shared.isSensitiveFileAllowed(
conversationId: params.conversationId,
toolName: params.name,
fileKey: fileKey
)
if allowed {
return true
}
}
return false
}
func makeEditAgentRounds(params: InvokeClientToolParams, status: AgentToolCall.ToolCallStatus) -> [AgentRound] {
[
AgentRound(
roundId: params.roundId,
reply: "",
toolCalls: [
AgentToolCall(
id: params.toolCallId,
name: params.name,
status: status,
invokeParams: params,
title: params.title
)
]
)
]
}
}