Skip to content

Commit ee140ff

Browse files
committed
fix: restore pending permissions via REST API after session switch
renderer.reset() clears the permission queue on every session change. The previous approach (preserve_permissions flag) tried to keep the queue alive across resets, but permissions that arrived for a different worktree while the user was away were never in the queue to begin with. Mirror the question_window.restore_pending_question pattern instead: after the session loads, query GET /permission for pending permissions, filter for ones belonging to the active session, and show them. This removes all preserve_permissions plumbing and the auto-deny behaviour from reset() (the cancel function handles explicit abort).
1 parent d515b84 commit ee140ff

3 files changed

Lines changed: 73 additions & 9 deletions

File tree

lua/opencode/api_client.lua

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ function OpencodeApiClient:unrevert_messages(id, directory)
304304
return self:_call('/session/' .. id .. '/unrevert', 'POST', nil, { directory = directory })
305305
end
306306

307+
--- List pending permissions
308+
--- @param directory string|nil Directory path
309+
--- @return Promise<OpencodePermission[]>
310+
function OpencodeApiClient:list_permissions(directory)
311+
return self:_call('/permission', 'GET', nil, { directory = directory })
312+
end
313+
307314
--- Respond to a permission request
308315
--- @param id string Session ID (required)
309316
--- @param permissionID string Permission ID (required)

lua/opencode/ui/permission_window.lua

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,68 @@ function M._clear_dialog()
269269
end
270270
end
271271

272+
---Query the server for pending permissions and restore any that belong
273+
---to the active session. Mirrors question_window.restore_pending_question.
274+
---@param session_id string|nil
275+
function M.restore_pending_permissions(session_id)
276+
local Promise = require('opencode.promise')
277+
if not state.api_client or not session_id or session_id == '' then
278+
return Promise.new():resolve(nil)
279+
end
280+
281+
return state.api_client:list_permissions()
282+
:and_then(function(permissions)
283+
if not permissions or type(permissions) ~= 'table' then
284+
return
285+
end
286+
287+
local events = require('opencode.ui.renderer.events')
288+
local render_state = require('opencode.ui.renderer.ctx').render_state
289+
290+
for _, permission in ipairs(permissions) do
291+
if permission and permission.id then
292+
-- Check if this permission belongs to the active session or
293+
-- one of its child sessions (task tool).
294+
local belongs = permission.sessionID == session_id
295+
if not belongs and permission.sessionID and permission.sessionID ~= '' then
296+
belongs = render_state:get_task_part_by_child_session(permission.sessionID) ~= nil
297+
end
298+
if not belongs then
299+
local tool = permission.tool
300+
local tool_message_id = tool and tool.messageID
301+
if tool_message_id and state.messages then
302+
for _, message in ipairs(state.messages) do
303+
if message.info and message.info.id == tool_message_id then
304+
belongs = true
305+
break
306+
end
307+
end
308+
end
309+
end
310+
311+
if belongs then
312+
-- Check if already queued (avoid duplicate)
313+
local already_queued = false
314+
for _, existing in ipairs(M._permission_queue) do
315+
if existing.id == permission.id then
316+
already_queued = true
317+
break
318+
end
319+
end
320+
if not already_queued then
321+
events.on_permission_updated(permission)
322+
end
323+
end
324+
end
325+
end
326+
end)
327+
:catch(function(err)
328+
vim.schedule(function()
329+
vim.notify('Failed to restore pending permissions: ' .. vim.inspect(err), vim.log.levels.WARN)
330+
end)
331+
end)
332+
end
333+
272334
---Check if we have permissions
273335
---@return boolean
274336
function M.has_permissions()

lua/opencode/ui/renderer.lua

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -246,16 +246,8 @@ M.on_session_updated = events.on_session_updated
246246
function M.reset()
247247
ctx:reset()
248248
output_window.clear()
249-
250-
local permissions = state.pending_permissions or {}
251-
if #permissions > 0 and state.api_client then
252-
for _, permission in ipairs(permissions) do
253-
require('opencode.api').permission_deny(permission)
254-
end
255-
end
256249
permission_window.clear_all()
257250
state.renderer.reset()
258-
259251
flush.trigger_on_data_rendered()
260252
end
261253

@@ -405,10 +397,13 @@ function M.render_full_session()
405397
return Promise.new():resolve(nil)
406398
end
407399
return fetch_session():and_then(function(session_data)
408-
M._render_full_session_data(session_data, { restore_model_from_messages = true })
400+
M._render_full_session_data(session_data, {
401+
restore_model_from_messages = true,
402+
})
409403
local active_session = state.active_session
410404
if active_session and active_session.id then
411405
require('opencode.ui.question_window').restore_pending_question(active_session.id)
406+
permission_window.restore_pending_permissions(active_session.id)
412407
end
413408
return session_data
414409
end)

0 commit comments

Comments
 (0)