Skip to content

Commit 362d9ea

Browse files
committed
fix: tool permission request handling
Refactor tool permission flow to use dedicated permission queue instead of generic message queue. Adds waitForPermissionResponse and sendPermissionResponse methods to handle tool permission confirmations separately, ensuring proper sequencing of permission requests.
1 parent 69f02bc commit 362d9ea

File tree

4 files changed

+29
-15
lines changed

4 files changed

+29
-15
lines changed

src/components/AgentChat.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const AgentChat: React.FC = () => {
107107
}
108108
})()}
109109

110-
<UserInput />
110+
{!state.pendingToolPermission && <UserInput />}
111111

112112
<Box marginTop={1} />
113113
</Box>

src/components/ToolPermissionPrompt.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,8 @@ export const ToolPermissionPrompt: React.FC = () => {
1919
const handleSubmit = (value: string) => {
2020
const response = value.trim() || "yes"
2121

22-
// Resolve ALL pending tool permission requests with the same response
23-
// This handles the case where multiple tools are called in parallel
24-
while (
25-
store.messageQueue.hasPendingRequests() &&
26-
store.pendingToolPermission
27-
) {
28-
store.messageQueue.sendMessage(response)
29-
30-
// Check if there are still more requests after sending
31-
if (!store.messageQueue.hasPendingRequests()) {
32-
break
33-
}
34-
}
22+
// Send the permission response to the waiting canUseTool call
23+
store.messageQueue.sendPermissionResponse(response)
3524

3625
actions.setPendingToolPermission(undefined)
3726
actions.setInput("")

src/utils/MessageQueue.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { EventEmitter } from "events"
22

33
export class MessageQueue extends EventEmitter {
44
private messageBuffer: string[] = []
5+
private permissionBuffer: string[] = []
56

67
constructor() {
78
super()
@@ -25,15 +26,39 @@ export class MessageQueue extends EventEmitter {
2526
}
2627
}
2728

29+
async waitForPermissionResponse(): Promise<string> {
30+
if (this.permissionBuffer.length > 0) {
31+
return this.permissionBuffer.shift()!
32+
}
33+
34+
return new Promise<string>((resolve) => {
35+
this.once("permissionResponse", resolve)
36+
})
37+
}
38+
39+
sendPermissionResponse(value: string): void {
40+
if (this.listenerCount("permissionResponse") > 0) {
41+
this.emit("permissionResponse", value)
42+
} else {
43+
this.permissionBuffer.push(value)
44+
}
45+
}
46+
2847
clear(): void {
2948
this.removeAllListeners("message")
49+
this.removeAllListeners("permissionResponse")
3050
this.messageBuffer = []
51+
this.permissionBuffer = []
3152
}
3253

3354
hasPendingRequests(): boolean {
3455
return this.listenerCount("message") > 0
3556
}
3657

58+
hasPendingPermissionRequest(): boolean {
59+
return this.listenerCount("permissionResponse") > 0
60+
}
61+
3762
subscribe(callback: (message: string) => void): () => void {
3863
this.on("message", callback)
3964
return () => {

src/utils/canUseTool.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const createCanUseTool = (options: CanUseToolOptions) => {
2525
onToolPermissionRequest(toolName, input)
2626
}
2727

28-
const userResponse = await messageQueue.waitForMessage()
28+
const userResponse = await messageQueue.waitForPermissionResponse()
2929
const response = userResponse.toLowerCase().trim()
3030

3131
const CONFIRM = ["y", "yes", "allow"].includes(response)

0 commit comments

Comments
 (0)