Skip to content

Commit 0df1f0e

Browse files
authored
Merge pull request #12 from damassi/fix/tool-permission-queue
fix: tool permission request handling
2 parents 69f02bc + 8d759da commit 0df1f0e

File tree

5 files changed

+42
-28
lines changed

5 files changed

+42
-28
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/__tests__/canUseTool.test.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe("createCanUseTool", () => {
1616
}
1717
)
1818

19-
queue.sendMessage("yes")
19+
queue.sendPermissionResponse("yes")
2020
const result = await promise
2121

2222
expect(result.behavior).toBe("allow")
@@ -37,7 +37,7 @@ describe("createCanUseTool", () => {
3737
}
3838
)
3939

40-
queue.sendMessage("y")
40+
queue.sendPermissionResponse("y")
4141
const result = await promise
4242

4343
expect(result.behavior).toBe("allow")
@@ -55,7 +55,7 @@ describe("createCanUseTool", () => {
5555
}
5656
)
5757

58-
queue.sendMessage("allow")
58+
queue.sendPermissionResponse("allow")
5959
const result = await promise
6060

6161
expect(result.behavior).toBe("allow")
@@ -73,7 +73,7 @@ describe("createCanUseTool", () => {
7373
}
7474
)
7575

76-
queue.sendMessage("no")
76+
queue.sendPermissionResponse("no")
7777
const result = await promise
7878

7979
expect(result.behavior).toBe("deny")
@@ -95,7 +95,7 @@ describe("createCanUseTool", () => {
9595
}
9696
)
9797

98-
queue.sendMessage("n")
98+
queue.sendPermissionResponse("n")
9999
const result = await promise
100100

101101
expect(result.behavior).toBe("deny")
@@ -113,7 +113,7 @@ describe("createCanUseTool", () => {
113113
}
114114
)
115115

116-
queue.sendMessage("deny")
116+
queue.sendPermissionResponse("deny")
117117
const result = await promise
118118

119119
expect(result.behavior).toBe("deny")
@@ -131,7 +131,7 @@ describe("createCanUseTool", () => {
131131
}
132132
)
133133

134-
queue.sendMessage("YES")
134+
queue.sendPermissionResponse("YES")
135135
const result = await promise
136136

137137
expect(result.behavior).toBe("allow")
@@ -149,7 +149,7 @@ describe("createCanUseTool", () => {
149149
}
150150
)
151151

152-
queue.sendMessage(" yes ")
152+
queue.sendPermissionResponse(" yes ")
153153
const result = await promise
154154

155155
expect(result.behavior).toBe("allow")
@@ -167,7 +167,7 @@ describe("createCanUseTool", () => {
167167
}
168168
)
169169

170-
queue.sendMessage("do something else")
170+
queue.sendPermissionResponse("do something else")
171171
const result = await promise
172172

173173
expect(result.behavior).toBe("deny")
@@ -193,7 +193,7 @@ describe("createCanUseTool", () => {
193193
}
194194
)
195195

196-
queue.sendMessage("yes")
196+
queue.sendPermissionResponse("yes")
197197
await promise
198198

199199
expect(callback).toHaveBeenCalledTimes(1)
@@ -212,7 +212,7 @@ describe("createCanUseTool", () => {
212212
}
213213
)
214214

215-
queue.sendMessage("yes")
215+
queue.sendPermissionResponse("yes")
216216
const result = await promise
217217

218218
expect(result.behavior).toBe("allow")
@@ -250,7 +250,7 @@ describe("createCanUseTool", () => {
250250
}
251251
)
252252

253-
queue.sendMessage("yes")
253+
queue.sendPermissionResponse("yes")
254254
const result = await promise
255255

256256
expect(result.behavior).toBe("allow")
@@ -275,7 +275,7 @@ describe("createCanUseTool", () => {
275275
}
276276
)
277277

278-
queue.sendMessage("no")
278+
queue.sendPermissionResponse("no")
279279
await promise
280280
await new Promise((resolve) => setTimeout(resolve, 100))
281281

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)