From aca68e5f3db72acec0c98a093f4521f3a4a180b4 Mon Sep 17 00:00:00 2001 From: Francis Belanger Date: Mon, 31 Aug 2026 07:45:08 -0400 Subject: [PATCH] fix(renderer): keep interactive prompts visible with max_messages (#482) --- lua/opencode/ui/renderer.lua | 7 ++- tests/replay/renderer_spec.lua | 91 ++++++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/lua/opencode/ui/renderer.lua b/lua/opencode/ui/renderer.lua index f1cc2966..cf069b3f 100644 --- a/lua/opencode/ui/renderer.lua +++ b/lua/opencode/ui/renderer.lua @@ -13,6 +13,8 @@ local scroll = require('opencode.ui.renderer.scroll') local M = {} local HIDDEN_MESSAGES_NOTICE_MESSAGE_ID = '__opencode_hidden_messages_notice__' local HIDDEN_MESSAGES_NOTICE_PART_ID = '__opencode_hidden_messages_notice_part__' +local PERMISSION_DISPLAY_MESSAGE_ID = 'permission-display-message' +local QUESTION_DISPLAY_MESSAGE_ID = 'question-display-message' local LAZYRENDER_EST_LINES_PER_MSG = 5 local LAZYRENDER_VIEWPORT_BUFFER = 1.5 @@ -44,7 +46,10 @@ end ---@return boolean local function is_renderer_synthetic_message(message) local message_id = message and message.info and message.info.id - return message_id == '__opencode_revert_message__' or message_id == HIDDEN_MESSAGES_NOTICE_MESSAGE_ID + return message_id == '__opencode_revert_message__' + or message_id == HIDDEN_MESSAGES_NOTICE_MESSAGE_ID + or message_id == PERMISSION_DISPLAY_MESSAGE_ID + or message_id == QUESTION_DISPLAY_MESSAGE_ID end ---@param message OpencodeMessage|nil diff --git a/tests/replay/renderer_spec.lua b/tests/replay/renderer_spec.lua index b0ea2830..92d08cf9 100644 --- a/tests/replay/renderer_spec.lua +++ b/tests/replay/renderer_spec.lua @@ -715,6 +715,97 @@ describe('renderer unit tests', function() config.ui.output.max_messages = nil end) + describe('interactive displays with max_messages', function() + local function make_message(id, text, timestamp) + return { + info = { + id = id, + role = 'assistant', + sessionID = 'ses_123', + time = { created = timestamp }, + }, + parts = { + { + id = id .. '_part', + messageID = id, + sessionID = 'ses_123', + type = 'text', + text = text, + }, + }, + } + end + + local function add_message(events, id, text, timestamp) + local message = make_message(id, text, timestamp) + events.on_message_updated({ info = message.info }) + events.on_part_updated({ part = message.parts[1] }) + end + + before_each(function() + helpers.replay_setup() + config.ui.output.max_messages = 2 + state.session.set_active({ id = 'ses_123', title = 'Session' }) + end) + + after_each(function() + config.ui.output.max_messages = nil + if state.windows then + ui.close_windows(state.windows) + end + end) + + it('keeps permission displays visible after later messages', function() + local renderer = require('opencode.ui.renderer') + local events = require('opencode.ui.renderer.events') + local flush = require('opencode.ui.renderer.flush') + + renderer._render_full_session_data({ make_message('msg_1', 'first', 1), make_message('msg_2', 'second', 2) }) + events.on_permission_updated({ + id = 'perm_1', + sessionID = 'ses_123', + permission = 'bash', + title = 'Run command', + }) + add_message(events, 'msg_3', 'third', 3) + add_message(events, 'msg_4', 'fourth', 4) + flush.flush() + + assert.is_not_nil(renderer.get_rendered_message('permission-display-message')) + assert.is_truthy( + table.concat(vim.api.nvim_buf_get_lines(state.windows.output_buf, 0, -1, false), '\n') + :find('Permission Required', 1, true) + ) + end) + + it('keeps question displays visible after later messages', function() + local renderer = require('opencode.ui.renderer') + local events = require('opencode.ui.renderer.events') + local flush = require('opencode.ui.renderer.flush') + + renderer._render_full_session_data({ make_message('msg_1', 'first', 1), make_message('msg_2', 'second', 2) }) + events.on_question_asked({ + id = 'question_1', + sessionID = 'ses_123', + questions = { + { + question = 'Pick one', + options = { { label = 'One' } }, + }, + }, + }) + add_message(events, 'msg_3', 'third', 3) + add_message(events, 'msg_4', 'fourth', 4) + flush.flush() + + assert.is_not_nil(renderer.get_rendered_message('question-display-message')) + assert.is_truthy( + table.concat(vim.api.nvim_buf_get_lines(state.windows.output_buf, 0, -1, false), '\n') + :find('Question', 1, true) + ) + end) + end) + it('ignores session.updated for non-active session IDs', function() local renderer = require('opencode.ui.renderer')