Skip to content

Commit ad3a7b0

Browse files
committed
feat(ui/output): extend compact_assistant_headers to 'minimal' | 'hidden' | 'full'
Allow more granular control over assistant header rendering
1 parent 62b81d0 commit ad3a7b0

4 files changed

Lines changed: 55 additions & 8 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ require('opencode').setup({
234234
},
235235
output = {
236236
filetype = 'opencode_output', -- Filetype assigned to the output buffer (default: 'opencode_output')
237-
compact_assistant_headers = false, -- Collapse consecutive assistant headers in the same mode to a right-aligned timestamp only
237+
compact_assistant_headers = false, -- 'full' (default), 'minimal' (compact if same mode), or 'hidden' (no headers for assistant)
238238
tools = {
239239
show_output = true, -- Show tools output [diffs, cmd output, etc.] (default: true)
240240
show_reasoning_output = true, -- Show reasoning/thinking steps output (default: true)

lua/opencode/types.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@
246246
---@field rendering OpencodeUIOutputRenderingConfig
247247
---@field always_scroll_to_bottom boolean
248248
---@field filetype string
249-
---@field compact_assistant_headers boolean
249+
---@field compact_assistant_headers boolean | 'minimal' | 'hidden' | 'full'
250250

251251
---@class OpencodeUIPickerConfig
252252
---@field snacks_layout? snacks.picker.layout.Config

lua/opencode/ui/formatter.lua

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,16 @@ function M.format_message_header(message, previous_message)
190190
display_name = role:upper()
191191
end
192192

193+
local header_style = config.ui.output.compact_assistant_headers
194+
if header_style == true then
195+
header_style = 'minimal'
196+
end
197+
if header_style == false then
198+
header_style = 'full'
199+
end
200+
193201
local same_mode_as_previous = false
194-
if config.ui.output.compact_assistant_headers and role == 'assistant' and previous_message then
202+
if (header_style == 'minimal' or header_style == 'hidden') and role == 'assistant' and previous_message then
195203
local previous_role = previous_message.info and previous_message.info.role or nil
196204
local previous_mode = previous_message.info and previous_message.info.mode or state.current_mode
197205
local current_mode = message.info.mode or state.current_mode
@@ -206,7 +214,9 @@ function M.format_message_header(message, previous_message)
206214
if not same_mode_as_previous then
207215
output:add_lines(M.separator)
208216
else
209-
output:add_line('')
217+
if header_style ~= 'hidden' then
218+
output:add_line('')
219+
end
210220
end
211221

212222
if not same_mode_as_previous then
@@ -223,7 +233,7 @@ function M.format_message_header(message, previous_message)
223233
} --[[@as OutputExtmark]])
224234
end
225235

226-
if time then
236+
if time and (role ~= 'assistant' or header_style ~= 'hidden') then
227237
output:add_extmark(output:get_line_count() - 1, {
228238
virt_text = { { (same_mode_as_previous and '' or ' ') .. util.format_time(time), 'OpencodeHint' } },
229239
virt_text_pos = 'right_align',

tests/unit/formatter_spec.lua

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,12 @@ describe('formatter', function()
349349

350350
snapshot.get_restore_points_by_parent = original_get_restore_points_by_parent
351351

352-
assert.are.same({ 0, 0, 0, 1, 1 }, vim.tbl_map(function(action)
353-
return action.display_line
354-
end, output.actions))
352+
assert.are.same(
353+
{ 0, 0, 0, 1, 1 },
354+
vim.tbl_map(function(action)
355+
return action.display_line
356+
end, output.actions)
357+
)
355358
end)
356359

357360
it('falls back to current mode for assistant messages without a stamped mode', function()
@@ -404,6 +407,40 @@ describe('formatter', function()
404407
assert.are.equal('right_align', output.extmarks[0][1].virt_text_pos)
405408
end)
406409

410+
it('renders hidden assistant headers without any header content', function()
411+
config.setup({
412+
ui = {
413+
output = {
414+
compact_assistant_headers = 'hidden',
415+
},
416+
},
417+
})
418+
419+
local output = formatter.format_message_header({
420+
info = {
421+
id = 'msg_current',
422+
role = 'assistant',
423+
sessionID = 'ses_1',
424+
mode = 'build',
425+
time = {
426+
created = 1,
427+
},
428+
},
429+
parts = {},
430+
}, {
431+
info = {
432+
id = 'msg_prev',
433+
role = 'assistant',
434+
sessionID = 'ses_1',
435+
mode = 'build',
436+
},
437+
parts = {},
438+
})
439+
440+
assert.are.same({ '' }, output.lines)
441+
assert.is_nil(output.extmarks[0])
442+
end)
443+
407444
it('keeps full assistant headers when the mode changes', function()
408445
config.setup({
409446
ui = {

0 commit comments

Comments
 (0)