@@ -12,7 +12,7 @@ local watch = require("codecompanion.interactions.shared.watch")
1212--- @field reasoning table Reasoning output from the Agent
1313--- @field tools table<string , table> Cache of tool calls by their ID
1414--- @field ui_state table<string , table> Cache of tool call UI states (line_number , icon_id ) by tool call ID
15- --- @field _permission { queue : CodeCompanion.Queue , active : boolean } Internal state for managing permission requests
15+ --- @field _permission { queue : CodeCompanion.Queue , active : boolean , respond : function | nil } Internal state for managing permission requests
1616local ACPHandler = {}
1717
1818--- @param chat CodeCompanion.Chat
@@ -27,6 +27,7 @@ function ACPHandler.new(chat)
2727 _permission = {
2828 active = false ,
2929 queue = Queue .new (),
30+ respond = nil ,
3031 },
3132 }, { __index = ACPHandler })
3233
@@ -196,6 +197,9 @@ function ACPHandler:create_and_send_prompt(payload)
196197 :on_error (function (error )
197198 self :handle_error (error )
198199 end )
200+ :on_cancel (function ()
201+ self :_clear_permission_queue ()
202+ end )
199203 :with_options ({ bufnr = self .chat .bufnr , interaction = " chat" })
200204 :send ()
201205end
@@ -330,11 +334,18 @@ function ACPHandler:_process_next_permission()
330334 end , request .options or {}))
331335 )
332336
337+ -- The original respond function is stored so that if the user cancels the request, we can respond as per the spec
338+ self ._permission .respond = request .respond
339+
333340 -- Ensure that the next item in the queue is processed after the user's response
334341 local send_response = request .respond
335- request .respond = function (option_id , canceled )
336- send_response (option_id , canceled )
342+ request .respond = function (option_id , cancelled )
343+ if not self ._permission .respond then
344+ return
345+ end
346+ send_response (option_id , cancelled )
337347 self ._permission .active = false
348+ self ._permission .respond = nil
338349 self :_process_next_permission ()
339350 end
340351
@@ -344,11 +355,24 @@ end
344355--- Clear any requests in the queue
345356--- @return nil
346357function ACPHandler :_clear_permission_queue ()
358+ local had_pending = self ._permission .respond ~= nil or not self ._permission .queue :is_empty ()
359+
360+ -- Cancel the currently active permission request (if any)
361+ if self ._permission .respond then
362+ pcall (self ._permission .respond , nil , true )
363+ self ._permission .respond = nil
364+ end
365+
366+ -- Cancel all queued permission requests
347367 while not self ._permission .queue :is_empty () do
348368 local request = self ._permission .queue :pop ()
349369 pcall (request .respond , nil , true )
350370 end
351371 self ._permission .active = false
372+
373+ if had_pending then
374+ utils .fire (" ToolApprovalFinished" , { bufnr = self .chat .bufnr , choice = " cancelled" })
375+ end
352376end
353377
354378--- Handle the prompt response when it's complete
0 commit comments