diff --git a/lua/opencode/ui/formatter.lua b/lua/opencode/ui/formatter.lua index 760b6279..1a20f821 100644 --- a/lua/opencode/ui/formatter.lua +++ b/lua/opencode/ui/formatter.lua @@ -246,7 +246,12 @@ function M.format_message_header(message, previous_message) local time = message.info.time and message.info.time.created or nil local role_hl = 'OpencodeMessageRole' .. role:sub(1, 1):upper() .. role:sub(2) - local model_text = message.info.modelID and ' ' .. message.info.modelID or '' + local model_text = message.info.providerID + and message.info.modelID + and (message.info.providerID .. '/' .. message.info.modelID) + or message.info.providerID + or message.info.modelID + or '' local debug_text = config.debug.show_ids and ' [' .. message.info.id .. ']' or '' @@ -299,6 +304,7 @@ function M.format_message_header(message, previous_message) { icon, role_hl }, { ' ' }, { display_name, role_hl }, + { ' ' }, { model_text, 'OpencodeHint' }, { debug_text, 'OpencodeHint' }, }, diff --git a/tests/data/ansi-codes.expected.json b/tests/data/ansi-codes.expected.json index 107e6a07..54c3b41e 100644 --- a/tests/data/ansi-codes.expected.json +++ b/tests/data/ansi-codes.expected.json @@ -22,7 +22,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -8574,6 +8577,7 @@ 409, 0 ], + "effective_bottom": 409, "line_count": 410, "visible_bottom": 410 } diff --git a/tests/data/api-abort.expected.json b/tests/data/api-abort.expected.json index f80a42b7..27fda823 100644 --- a/tests/data/api-abort.expected.json +++ b/tests/data/api-abort.expected.json @@ -1 +1,226 @@ -{"lines":["----","","","can generate 10 numbers?","","[`a-empty.txt`](a-empty.txt)","","----","","","You asked if I can generate 10 numbers, and you referenced reading an empty file ( `a-empty.txt`). However, I'm currently in \"plan mode,\" which means I cannot write or modify any files—I'm only allowed to read, observe,","","> [!ERROR] The operation was aborted.","",""],"timestamp":1773947710,"window":{"cursor":[14,0],"line_count":15,"visible_bottom":15},"extmarks":[[1,1,0,{"virt_text_win_col":-3,"virt_text_pos":"win_col","virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_a27d8299d001nchmBunYlZcPyL]","OpencodeHint"]],"ns_id":3,"virt_text_hide":false,"priority":10,"virt_text_repeat_linebreak":false,"right_gravity":true}],[2,1,0,{"virt_text_pos":"right_align","virt_text":[[" 2025-10-27 22:44:29","OpencodeHint"]],"ns_id":3,"virt_text_hide":false,"priority":9,"virt_text_repeat_linebreak":false,"right_gravity":true}],[3,2,0,{"virt_text_win_col":-3,"virt_text_pos":"win_col","virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false,"priority":4096,"virt_text_repeat_linebreak":true,"right_gravity":true}],[4,3,0,{"virt_text_win_col":-3,"virt_text_pos":"win_col","virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false,"priority":4096,"virt_text_repeat_linebreak":true,"right_gravity":true}],[5,4,0,{"virt_text_win_col":-3,"virt_text_pos":"win_col","virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false,"priority":4096,"virt_text_repeat_linebreak":true,"right_gravity":true}],[6,5,0,{"virt_text_win_col":-3,"virt_text_pos":"win_col","virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false,"priority":4096,"virt_text_repeat_linebreak":true,"right_gravity":true}],[7,8,0,{"virt_text_win_col":-3,"virt_text_pos":"win_col","virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["PLAN","OpencodeMessageRoleAssistant"],[" gpt-4.1","OpencodeHint"],[" [msg_a27d829f9002sfUFPslHq5P2b4]","OpencodeHint"]],"ns_id":3,"virt_text_hide":false,"priority":10,"virt_text_repeat_linebreak":false,"right_gravity":true}],[8,8,0,{"virt_text_pos":"right_align","virt_text":[[" 2025-10-27 22:44:29","OpencodeHint"]],"ns_id":3,"virt_text_hide":false,"priority":9,"virt_text_repeat_linebreak":false,"right_gravity":true}]],"actions":[]} \ No newline at end of file +{ + "actions": [], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_a27d8299d001nchmBunYlZcPyL]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-27 22:44:29", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 2, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 4, + 3, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 5, + 4, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 6, + 5, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 7, + 8, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "PLAN", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/gpt-4.1", + "OpencodeHint" + ], + [ + " [msg_a27d829f9002sfUFPslHq5P2b4]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 8, + 8, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-27 22:44:29", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ] + ], + "lines": [ + "----", + "", + "", + "can generate 10 numbers?", + "", + "[`a-empty.txt`](a-empty.txt)", + "", + "----", + "", + "", + "You asked if I can generate 10 numbers, and you referenced reading an empty file ( `a-empty.txt`). However, I'm currently in \"plan mode,\" which means I cannot write or modify any files—I'm only allowed to read, observe,", + "", + "> [!ERROR] The operation was aborted.", + "", + "" + ], + "timestamp": 1773947710, + "window": { + "cursor": [ + 14, + 0 + ], + "effective_bottom": 14, + "line_count": 15, + "visible_bottom": 15 + } +} diff --git a/tests/data/api-error.expected.json b/tests/data/api-error.expected.json index eddb1f7e..c64ad247 100644 --- a/tests/data/api-error.expected.json +++ b/tests/data/api-error.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -156,7 +159,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4-5-20250929", + " " + ], + [ + "anthropic/claude-sonnet-4-5-20250929", "OpencodeHint" ], [ @@ -210,7 +216,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4-5-20250929", + " " + ], + [ + "anthropic/claude-sonnet-4-5-20250929", "OpencodeHint" ], [ @@ -272,6 +281,7 @@ 19, 0 ], + "effective_bottom": 19, "line_count": 20, "visible_bottom": 20 } diff --git a/tests/data/apply-patch.expected.json b/tests/data/apply-patch.expected.json index b89ebc88..f479ce69 100644 --- a/tests/data/apply-patch.expected.json +++ b/tests/data/apply-patch.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -56,6 +59,9 @@ "BUILD", "OpencodeMessageRoleAssistant" ], + [ + " " + ], [ "", "OpencodeHint" @@ -299,6 +305,7 @@ 14, 0 ], + "effective_bottom": 14, "line_count": 15, "visible_bottom": 15 } diff --git a/tests/data/compaction-after-messages.expected.json b/tests/data/compaction-after-messages.expected.json index 15c0128f..5b3f2d73 100644 --- a/tests/data/compaction-after-messages.expected.json +++ b/tests/data/compaction-after-messages.expected.json @@ -32,6 +32,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -127,7 +130,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5.5", + " " + ], + [ + "openai/gpt-5.5", "OpencodeHint" ], [ @@ -184,6 +190,7 @@ 14, 0 ], + "effective_bottom": 14, "line_count": 15, "visible_bottom": 15 } diff --git a/tests/data/compaction-summary-text.expected.json b/tests/data/compaction-summary-text.expected.json index 9a237d0c..807e99f0 100644 --- a/tests/data/compaction-summary-text.expected.json +++ b/tests/data/compaction-summary-text.expected.json @@ -27,6 +27,7 @@ 5, 0 ], + "effective_bottom": 5, "line_count": 6, "visible_bottom": 6 } diff --git a/tests/data/compaction-user-marker.expected.json b/tests/data/compaction-user-marker.expected.json index 9791c5ad..edd413f3 100644 --- a/tests/data/compaction-user-marker.expected.json +++ b/tests/data/compaction-user-marker.expected.json @@ -24,6 +24,7 @@ 2, 0 ], + "effective_bottom": 2, "line_count": 3, "visible_bottom": 3 } diff --git a/tests/data/cursor_data.expected.json b/tests/data/cursor_data.expected.json index 19933192..ccc95204 100644 --- a/tests/data/cursor_data.expected.json +++ b/tests/data/cursor_data.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -276,7 +279,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -344,6 +350,7 @@ 25, 0 ], + "effective_bottom": 25, "line_count": 26, "visible_bottom": 26 } diff --git a/tests/data/diagnostics.expected.json b/tests/data/diagnostics.expected.json index 33d12e0c..04afd6a3 100644 --- a/tests/data/diagnostics.expected.json +++ b/tests/data/diagnostics.expected.json @@ -100,6 +100,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -295,7 +298,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -1057,7 +1063,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -1715,7 +1724,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -11169,7 +11181,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ diff --git a/tests/data/diff.expected.json b/tests/data/diff.expected.json index 4ba5749f..41322a43 100644 --- a/tests/data/diff.expected.json +++ b/tests/data/diff.expected.json @@ -61,6 +61,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -211,7 +214,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -469,7 +475,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -535,6 +544,7 @@ 23, 0 ], + "effective_bottom": 23, "line_count": 24, "visible_bottom": 24 } diff --git a/tests/data/explore.expected.json b/tests/data/explore.expected.json index 1fe79ddd..711a0449 100644 --- a/tests/data/explore.expected.json +++ b/tests/data/explore.expected.json @@ -35,6 +35,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -130,7 +133,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.6", + " " + ], + [ + "github-copilot/claude-sonnet-4.6", "OpencodeHint" ], [ @@ -1584,7 +1590,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.6", + " " + ], + [ + "github-copilot/claude-sonnet-4.6", "OpencodeHint" ], [ @@ -1720,6 +1729,7 @@ 93, 0 ], + "effective_bottom": 93, "line_count": 94, "visible_bottom": 93 } diff --git a/tests/data/markdown-codefence.expected.json b/tests/data/markdown-codefence.expected.json index b2e83b6f..0d4fc020 100644 --- a/tests/data/markdown-codefence.expected.json +++ b/tests/data/markdown-codefence.expected.json @@ -1 +1,1151 @@ -{"actions":[{"args":["c64ddee834f1b802020a8f880eafa689f0b99406"],"key":"R","range":{"to":23,"from":23},"display_line":23,"type":"diff_revert_selected_file","text":"[R]evert file"},{"args":["c64ddee834f1b802020a8f880eafa689f0b99406"],"key":"A","range":{"to":23,"from":23},"display_line":23,"type":"diff_revert_all","text":"Revert [A]ll"},{"args":["c64ddee834f1b802020a8f880eafa689f0b99406"],"key":"D","range":{"to":23,"from":23},"display_line":23,"type":"diff_open","text":"[D]iff"}],"window":{"cursor":[77,0],"line_count":78,"visible_bottom":78},"timestamp":1773947679,"lines":["----","","","Now let me also update the Run opts examples to use the new command syntax:","","** edit** `/Users/cam/Dev/neovim-dev/opencode.nvim/README.md`","","`````markdown"," "," Run a prompt in a new session using the Plan agent and disabling current file context:"," "," ```vim"," :OpencodeRunNewSession \"Please help me plan a new feature\" agent=plan context.current_file.enabled=false"," :OpencodeRun \"Fix the bug in the current file\" model=github-copilot/claude-sonned-4"," :Opencode run new_session \"Please help me plan a new feature\" agent=plan context.current_file.enabled=false"," :Opencode run \"Fix the bug in the current file\" model=github-copilot/claude-sonned-4"," ```"," "," ##👮 Permissions"," ","","`````","","**󰻛 Created Snapshot** `c64ddee8`","","----","","","README updated with the new nested command structure. The documentation now shows the new `:Opencode` subcommand syntax and includes a note that legacy `Opencode*` commands are still available by default but will be removed in the future.","","----","","","can you rename Opencode stop to Opencode cancel (and rename the api call)","","[`README.md`](README.md)","","----","","","Here's the plan to rename `Opencode stop` to `Opencode cancel` and update the API call accordingly:","","---","","## 📝 Plan: Rename Opencode Stop to Cancel","","### 1. Update Command Table and Documentation","- In README.md, change:"," - Command: `:Opencode stop` → `:Opencode cancel`"," - API: `require('opencode.api').stop()` → `require('opencode.api').cancel()`"," - Keymap: `` remains the same (unless you want to change it)","","### 2. Update Codebase","- In  `lua/opencode/api.lua`:"," - Rename the function `M.stop()` to `M.cancel()`"," - Update all references to `stop` (command registration, legacy command map, subcommand routing, etc.) to use `cancel`"," - Ensure legacy command `OpencodeStop` still works (with deprecation warning), but routes to `cancel`","- In any other files (keymap config, tests, etc.) update references to `stop` to `cancel` as needed","","### 3. Update Tests","- In  `tests/unit/api_spec.lua`:"," - Update any tests that check for `stop` to check for `cancel`","","### 4. Update Slash Commands (if applicable)","- If there is a `/stop` slash command, rename it to `/cancel`","","### 5. Verify","- Run all tests to ensure everything works","- Check that both `:Opencode cancel` and legacy `:OpencodeStop` work (with warning)","","---","","**Note:** You are currently in \"Plan mode\" (read-only phase), so I cannot make edits right now. ","When you switch to edit mode, I will execute this plan step by step and verify all changes.","","Would you like to proceed with this plan when edits are allowed?","",""],"extmarks":[[1,1,0,{"virt_text_repeat_linebreak":false,"priority":10,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["BUILD","OpencodeMessageRoleAssistant"],[" claude-sonnet-4.5","OpencodeHint"],[" [msg_a2cd04588001P9plKmrFnsNH3M]","OpencodeHint"]],"ns_id":3}],[2,1,0,{"virt_text_repeat_linebreak":false,"priority":9,"virt_text_hide":false,"ns_id":3,"right_gravity":true,"virt_text":[[" 2025-10-28 21:53:58","OpencodeHint"]],"virt_text_pos":"right_align"}],[3,5,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[4,6,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[5,7,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[6,8,0,{"virt_text_repeat_linebreak":false,"end_row":9,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["382","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[7,8,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[8,9,0,{"virt_text_repeat_linebreak":false,"end_row":10,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["383","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[9,9,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[10,10,0,{"virt_text_repeat_linebreak":false,"end_row":11,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["384","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[11,10,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[12,11,0,{"virt_text_repeat_linebreak":false,"end_row":12,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["385","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[13,11,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[14,12,0,{"virt_text_repeat_linebreak":false,"end_row":13,"virt_text_hide":false,"hl_eol":true,"virt_text_pos":"overlay","hl_group":"OpencodeDiffDelete","end_col":0,"priority":5000,"right_gravity":true,"end_right_gravity":false,"virt_text":[["386","OpencodeDiffDeleteGutter"],["-","OpencodeDiffDeleteGutter"],[" ","OpencodeDiffDeleteGutter"]],"ns_id":3}],[15,12,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[16,13,0,{"virt_text_repeat_linebreak":false,"end_row":14,"virt_text_hide":false,"hl_eol":true,"virt_text_pos":"overlay","hl_group":"OpencodeDiffDelete","end_col":0,"priority":5000,"right_gravity":true,"end_right_gravity":false,"virt_text":[["387","OpencodeDiffDeleteGutter"],["-","OpencodeDiffDeleteGutter"],[" ","OpencodeDiffDeleteGutter"]],"ns_id":3}],[17,13,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[18,14,0,{"virt_text_repeat_linebreak":false,"end_row":15,"virt_text_hide":false,"hl_eol":true,"virt_text_pos":"overlay","hl_group":"OpencodeDiffAdd","end_col":0,"priority":5000,"right_gravity":true,"end_right_gravity":false,"virt_text":[["386","OpencodeDiffAddGutter"],["+","OpencodeDiffAddGutter"],[" ","OpencodeDiffAddGutter"]],"ns_id":3}],[19,14,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[20,15,0,{"virt_text_repeat_linebreak":false,"end_row":16,"virt_text_hide":false,"hl_eol":true,"virt_text_pos":"overlay","hl_group":"OpencodeDiffAdd","end_col":0,"priority":5000,"right_gravity":true,"end_right_gravity":false,"virt_text":[["387","OpencodeDiffAddGutter"],["+","OpencodeDiffAddGutter"],[" ","OpencodeDiffAddGutter"]],"ns_id":3}],[21,15,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[22,16,0,{"virt_text_repeat_linebreak":false,"end_row":17,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["388","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[23,16,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[24,17,0,{"virt_text_repeat_linebreak":false,"end_row":18,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["389","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[25,17,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[26,18,0,{"virt_text_repeat_linebreak":false,"end_row":19,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["390","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[27,18,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[28,19,0,{"virt_text_repeat_linebreak":false,"end_row":20,"priority":5000,"virt_text_pos":"overlay","end_col":0,"right_gravity":true,"virt_text":[["391","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"],[" ","OpencodeDiffGutter"]],"end_right_gravity":false,"virt_text_hide":false,"ns_id":3}],[29,19,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[30,20,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[31,21,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[32,26,0,{"virt_text_repeat_linebreak":false,"priority":10,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["BUILD","OpencodeMessageRoleAssistant"],[" claude-sonnet-4.5","OpencodeHint"],[" [msg_a2cd062fb001UA0ZzR6JxgLxDQ]","OpencodeHint"]],"ns_id":3}],[33,26,0,{"virt_text_repeat_linebreak":false,"priority":9,"virt_text_hide":false,"ns_id":3,"right_gravity":true,"virt_text":[[" 2025-10-28 21:54:05","OpencodeHint"]],"virt_text_pos":"right_align"}],[34,31,0,{"virt_text_repeat_linebreak":false,"priority":10,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_a2cf5ce65001YLvVsYxIboFcP4]","OpencodeHint"]],"ns_id":3}],[35,31,0,{"virt_text_repeat_linebreak":false,"priority":9,"virt_text_hide":false,"ns_id":3,"right_gravity":true,"virt_text":[[" 2025-10-28 22:34:58","OpencodeHint"]],"virt_text_pos":"right_align"}],[36,32,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3}],[37,33,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3}],[38,34,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3}],[39,35,0,{"virt_text_repeat_linebreak":true,"priority":4096,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3}],[40,38,0,{"virt_text_repeat_linebreak":false,"priority":10,"virt_text_hide":false,"right_gravity":true,"virt_text_pos":"win_col","virt_text_win_col":-3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["PLAN","OpencodeMessageRoleAssistant"],[" gpt-4.1","OpencodeHint"],[" [msg_a2cf5cf0f002oBAjmnGIMGXjez]","OpencodeHint"]],"ns_id":3}],[41,38,0,{"virt_text_repeat_linebreak":false,"priority":9,"virt_text_hide":false,"ns_id":3,"right_gravity":true,"virt_text":[[" 2025-10-28 22:34:58","OpencodeHint"]],"virt_text_pos":"right_align"}]]} \ No newline at end of file +{ + "actions": [ + { + "args": [ + "c64ddee834f1b802020a8f880eafa689f0b99406" + ], + "display_line": 23, + "key": "R", + "range": { + "from": 23, + "to": 23 + }, + "text": "[R]evert file", + "type": "diff_revert_selected_file" + }, + { + "args": [ + "c64ddee834f1b802020a8f880eafa689f0b99406" + ], + "display_line": 23, + "key": "A", + "range": { + "from": 23, + "to": 23 + }, + "text": "Revert [A]ll", + "type": "diff_revert_all" + }, + { + "args": [ + "c64ddee834f1b802020a8f880eafa689f0b99406" + ], + "display_line": 23, + "key": "D", + "range": { + "from": 23, + "to": 23 + }, + "text": "[D]iff", + "type": "diff_open" + } + ], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "BUILD", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/claude-sonnet-4.5", + "OpencodeHint" + ], + [ + " [msg_a2cd04588001P9plKmrFnsNH3M]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-28 21:53:58", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 5, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 4, + 6, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 5, + 7, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 6, + 8, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 9, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "382", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 7, + 8, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 8, + 9, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 10, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "383", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 9, + 9, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 10, + 10, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 11, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "384", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 11, + 10, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 12, + 11, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 12, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "385", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 13, + 11, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 14, + 12, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 13, + "hl_eol": true, + "hl_group": "OpencodeDiffDelete", + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "386", + "OpencodeDiffDeleteGutter" + ], + [ + "-", + "OpencodeDiffDeleteGutter" + ], + [ + " ", + "OpencodeDiffDeleteGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 15, + 12, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 16, + 13, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 14, + "hl_eol": true, + "hl_group": "OpencodeDiffDelete", + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "387", + "OpencodeDiffDeleteGutter" + ], + [ + "-", + "OpencodeDiffDeleteGutter" + ], + [ + " ", + "OpencodeDiffDeleteGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 17, + 13, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 18, + 14, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 15, + "hl_eol": true, + "hl_group": "OpencodeDiffAdd", + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "386", + "OpencodeDiffAddGutter" + ], + [ + "+", + "OpencodeDiffAddGutter" + ], + [ + " ", + "OpencodeDiffAddGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 19, + 14, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 20, + 15, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 16, + "hl_eol": true, + "hl_group": "OpencodeDiffAdd", + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "387", + "OpencodeDiffAddGutter" + ], + [ + "+", + "OpencodeDiffAddGutter" + ], + [ + " ", + "OpencodeDiffAddGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 21, + 15, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 22, + 16, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 17, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "388", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 23, + 16, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 24, + 17, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 18, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "389", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 25, + 17, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 26, + 18, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 19, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "390", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 27, + 18, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 28, + 19, + 0, + { + "end_col": 0, + "end_right_gravity": false, + "end_row": 20, + "ns_id": 3, + "priority": 5000, + "right_gravity": true, + "virt_text": [ + [ + "391", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ], + [ + " ", + "OpencodeDiffGutter" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "overlay", + "virt_text_repeat_linebreak": false + } + ], + [ + 29, + 19, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 30, + 20, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 31, + 21, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 32, + 26, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "BUILD", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/claude-sonnet-4.5", + "OpencodeHint" + ], + [ + " [msg_a2cd062fb001UA0ZzR6JxgLxDQ]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 33, + 26, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-28 21:54:05", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 34, + 31, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_a2cf5ce65001YLvVsYxIboFcP4]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 35, + 31, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-28 22:34:58", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 36, + 32, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 37, + 33, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 38, + 34, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 39, + 35, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 40, + 38, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "PLAN", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/gpt-4.1", + "OpencodeHint" + ], + [ + " [msg_a2cf5cf0f002oBAjmnGIMGXjez]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 41, + 38, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-28 22:34:58", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ] + ], + "lines": [ + "----", + "", + "", + "Now let me also update the Run opts examples to use the new command syntax:", + "", + "** edit** `/Users/cam/Dev/neovim-dev/opencode.nvim/README.md`", + "", + "`````markdown", + " ", + " Run a prompt in a new session using the Plan agent and disabling current file context:", + " ", + " ```vim", + " :OpencodeRunNewSession \"Please help me plan a new feature\" agent=plan context.current_file.enabled=false", + " :OpencodeRun \"Fix the bug in the current file\" model=github-copilot/claude-sonned-4", + " :Opencode run new_session \"Please help me plan a new feature\" agent=plan context.current_file.enabled=false", + " :Opencode run \"Fix the bug in the current file\" model=github-copilot/claude-sonned-4", + " ```", + " ", + " ##👮 Permissions", + " ", + "", + "`````", + "", + "**󰻛 Created Snapshot** `c64ddee8`", + "", + "----", + "", + "", + "README updated with the new nested command structure. The documentation now shows the new `:Opencode` subcommand syntax and includes a note that legacy `Opencode*` commands are still available by default but will be removed in the future.", + "", + "----", + "", + "", + "can you rename Opencode stop to Opencode cancel (and rename the api call)", + "", + "[`README.md`](README.md)", + "", + "----", + "", + "", + "Here's the plan to rename `Opencode stop` to `Opencode cancel` and update the API call accordingly:", + "", + "---", + "", + "## 📝 Plan: Rename Opencode Stop to Cancel", + "", + "### 1. Update Command Table and Documentation", + "- In README.md, change:", + " - Command: `:Opencode stop` → `:Opencode cancel`", + " - API: `require('opencode.api').stop()` → `require('opencode.api').cancel()`", + " - Keymap: `` remains the same (unless you want to change it)", + "", + "### 2. Update Codebase", + "- In  `lua/opencode/api.lua`:", + " - Rename the function `M.stop()` to `M.cancel()`", + " - Update all references to `stop` (command registration, legacy command map, subcommand routing, etc.) to use `cancel`", + " - Ensure legacy command `OpencodeStop` still works (with deprecation warning), but routes to `cancel`", + "- In any other files (keymap config, tests, etc.) update references to `stop` to `cancel` as needed", + "", + "### 3. Update Tests", + "- In  `tests/unit/api_spec.lua`:", + " - Update any tests that check for `stop` to check for `cancel`", + "", + "### 4. Update Slash Commands (if applicable)", + "- If there is a `/stop` slash command, rename it to `/cancel`", + "", + "### 5. Verify", + "- Run all tests to ensure everything works", + "- Check that both `:Opencode cancel` and legacy `:OpencodeStop` work (with warning)", + "", + "---", + "", + "**Note:** You are currently in \"Plan mode\" (read-only phase), so I cannot make edits right now. ", + "When you switch to edit mode, I will execute this plan step by step and verify all changes.", + "", + "Would you like to proceed with this plan when edits are allowed?", + "", + "" + ], + "timestamp": 1773947679, + "window": { + "cursor": [ + 77, + 0 + ], + "effective_bottom": 77, + "line_count": 78, + "visible_bottom": 78 + } +} diff --git a/tests/data/mcp-tool.expected.json b/tests/data/mcp-tool.expected.json index 1535b401..6be5668d 100644 --- a/tests/data/mcp-tool.expected.json +++ b/tests/data/mcp-tool.expected.json @@ -1 +1,629 @@ -{"actions":[],"extmarks":[[1,1,0,{"virt_text_hide":false,"virt_text_win_col":-3,"virt_text_repeat_linebreak":false,"virt_text_pos":"win_col","right_gravity":true,"priority":10,"virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_mcp_user1]","OpencodeHint"]],"ns_id":3}],[2,1,0,{"virt_text_hide":false,"virt_text":[[" 2025-12-17 19:33:20","OpencodeHint"]],"virt_text_pos":"right_align","right_gravity":true,"ns_id":3,"virt_text_repeat_linebreak":false,"priority":9}],[3,2,0,{"virt_text_hide":false,"virt_text_win_col":-3,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3}],[4,3,0,{"virt_text_hide":false,"virt_text_win_col":-3,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3}],[5,6,0,{"virt_text_hide":false,"virt_text_win_col":-3,"virt_text_repeat_linebreak":false,"virt_text_pos":"win_col","right_gravity":true,"priority":10,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["BUILD","OpencodeMessageRoleAssistant"],["","OpencodeHint"],[" [msg_mcp_asst1]","OpencodeHint"]],"ns_id":3}],[6,6,0,{"virt_text_hide":false,"virt_text":[[" 2025-12-17 19:33:20","OpencodeHint"]],"virt_text_pos":"right_align","right_gravity":true,"ns_id":3,"virt_text_repeat_linebreak":false,"priority":9}],[7,8,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[8,8,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[9,9,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[10,9,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[11,10,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[12,10,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[13,11,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[14,11,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[15,12,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[16,12,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[17,13,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[18,13,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[19,14,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[20,14,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[21,15,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[22,15,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[23,16,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[24,16,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[25,17,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[26,17,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[27,18,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[28,18,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[29,19,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[30,19,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[31,20,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[32,20,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}],[33,21,0,{"right_gravity":true,"ns_id":3,"line_hl_group":"OpencodeHint","priority":5000}],[34,21,0,{"virt_text_hide":false,"virt_text_win_col":-1,"virt_text_repeat_linebreak":true,"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text":[["▌","OpencodeToolBorder"]],"ns_id":3}]],"lines":["----","","","Think about this step by step.","","----","",""," sequential-thinking: sequentialthinking","","Let me analyze this problem step by step.","","First, I need to understand the core issue.",""," sequential-thinking: sequentialthinking","","Second thought: the analysis is complete.","","Key findings:","- Finding A","- Finding B","","Based on my analysis, here is the answer.","",""],"window":{"line_count":25,"cursor":[24,0],"visible_bottom":25}} \ No newline at end of file +{ + "actions": [], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_mcp_user1]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-12-17 19:33:20", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 2, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 4, + 3, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 5, + 6, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "BUILD", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_mcp_asst1]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 6, + 6, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-12-17 19:33:20", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 7, + 8, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 8, + 8, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 9, + 9, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 10, + 9, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 11, + 10, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 12, + 10, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 13, + 11, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 14, + 11, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 15, + 12, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 16, + 12, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 17, + 13, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 18, + 13, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 19, + 14, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 20, + 14, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 21, + 15, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 22, + 15, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 23, + 16, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 24, + 16, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 25, + 17, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 26, + 17, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 27, + 18, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 28, + 18, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 29, + 19, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 30, + 19, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 31, + 20, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 32, + 20, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 33, + 21, + 0, + { + "line_hl_group": "OpencodeHint", + "ns_id": 3, + "priority": 5000, + "right_gravity": true + } + ], + [ + 34, + 21, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ] + ], + "lines": [ + "----", + "", + "", + "Think about this step by step.", + "", + "----", + "", + "", + " sequential-thinking: sequentialthinking", + "", + "Let me analyze this problem step by step.", + "", + "First, I need to understand the core issue.", + "", + " sequential-thinking: sequentialthinking", + "", + "Second thought: the analysis is complete.", + "", + "Key findings:", + "- Finding A", + "- Finding B", + "", + "Based on my analysis, here is the answer.", + "", + "" + ], + "window": { + "cursor": [ + 24, + 0 + ], + "effective_bottom": 24, + "line_count": 25, + "visible_bottom": 25 + } +} diff --git a/tests/data/mentions-with-ranges.expected.json b/tests/data/mentions-with-ranges.expected.json index b2c37053..9b7ea15a 100644 --- a/tests/data/mentions-with-ranges.expected.json +++ b/tests/data/mentions-with-ranges.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -518,6 +521,7 @@ 23, 0 ], + "effective_bottom": 23, "line_count": 24, "visible_bottom": 24 } diff --git a/tests/data/message-removal.expected.json b/tests/data/message-removal.expected.json index 5d2ced12..e5002d90 100644 --- a/tests/data/message-removal.expected.json +++ b/tests/data/message-removal.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -235,6 +238,9 @@ "BUILD", "OpencodeMessageRoleAssistant" ], + [ + " " + ], [ "", "OpencodeHint" @@ -289,6 +295,9 @@ "BUILD", "OpencodeMessageRoleAssistant" ], + [ + " " + ], [ "", "OpencodeHint" @@ -360,6 +369,7 @@ 27, 0 ], + "effective_bottom": 27, "line_count": 28, "visible_bottom": 28 } diff --git a/tests/data/multiple-messages-synthetic.expected.json b/tests/data/multiple-messages-synthetic.expected.json index f60ede1d..3de3cb7f 100644 --- a/tests/data/multiple-messages-synthetic.expected.json +++ b/tests/data/multiple-messages-synthetic.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -115,6 +118,9 @@ "BUILD", "OpencodeMessageRoleAssistant" ], + [ + " " + ], [ "", "OpencodeHint" @@ -169,6 +175,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -263,6 +272,9 @@ "BUILD", "OpencodeMessageRoleAssistant" ], + [ + " " + ], [ "", "OpencodeHint" @@ -317,6 +329,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -411,6 +426,9 @@ "BUILD", "OpencodeMessageRoleAssistant" ], + [ + " " + ], [ "", "OpencodeHint" @@ -501,6 +519,7 @@ 46, 0 ], + "effective_bottom": 46, "line_count": 47, "visible_bottom": 47 } diff --git a/tests/data/multiple-messages.expected.json b/tests/data/multiple-messages.expected.json index a846aac0..b8dbc4bf 100644 --- a/tests/data/multiple-messages.expected.json +++ b/tests/data/multiple-messages.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -156,7 +159,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -209,6 +215,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -344,7 +353,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -482,6 +494,7 @@ 95, 0 ], + "effective_bottom": 95, "line_count": 96, "visible_bottom": 96 } diff --git a/tests/data/multiple-question-ask-reply-all.expected.json b/tests/data/multiple-question-ask-reply-all.expected.json index 1b260c5d..f8bc8c3c 100644 --- a/tests/data/multiple-question-ask-reply-all.expected.json +++ b/tests/data/multiple-question-ask-reply-all.expected.json @@ -1 +1,604 @@ -{"timestamp":1773947664,"actions":[{"key":"R","text":"[R]evert file","args":["be64b6205f0da4c9240df2476dc35495429161b5"],"type":"diff_revert_selected_file","range":{"to":23,"from":23},"display_line":23},{"key":"A","text":"Revert [A]ll","args":["be64b6205f0da4c9240df2476dc35495429161b5"],"type":"diff_revert_all","range":{"to":23,"from":23},"display_line":23},{"key":"D","text":"[D]iff","args":["be64b6205f0da4c9240df2476dc35495429161b5"],"type":"diff_open","range":{"to":23,"from":23},"display_line":23}],"window":{"cursor":[35,0],"visible_bottom":36,"line_count":36},"extmarks":[[1,1,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"right_gravity":true,"priority":10,"ns_id":3,"virt_text_win_col":-3,"virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_bfab6dbf3001ZOVHTFKR1CMUE5]","OpencodeHint"]],"virt_text_pos":"win_col"}],[2,1,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"priority":9,"right_gravity":true,"ns_id":3,"virt_text":[[" 2026-01-26 14:30:46","OpencodeHint"]],"virt_text_pos":"right_align"}],[3,2,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col"}],[4,3,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col"}],[5,4,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col"}],[6,5,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col"}],[7,6,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col"}],[8,8,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"right_gravity":true,"priority":10,"ns_id":3,"virt_text_win_col":-3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["BUILD","OpencodeMessageRoleAssistant"],[" gpt-4.1","OpencodeHint"],[" [msg_bfab6dc80001FueCN7E2691J2R]","OpencodeHint"]],"virt_text_pos":"win_col"}],[9,8,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"priority":9,"right_gravity":true,"ns_id":3,"virt_text":[[" 2026-01-26 14:30:46","OpencodeHint"]],"virt_text_pos":"right_align"}],[10,10,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[11,11,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[12,12,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[13,13,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[14,14,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[15,15,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[16,16,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[17,17,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[18,18,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[19,19,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[20,20,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[21,21,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"right_gravity":true,"priority":4096,"ns_id":3,"virt_text_win_col":-1,"virt_text":[["▌","OpencodeToolBorder"]],"virt_text_pos":"win_col"}],[22,26,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"right_gravity":true,"priority":10,"ns_id":3,"virt_text_win_col":-3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["BUILD","OpencodeMessageRoleAssistant"],[" gpt-4.1","OpencodeHint"],[" [msg_bfab7e7fd0018kA9yLHMkJM3fA]","OpencodeHint"]],"virt_text_pos":"win_col"}],[23,26,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"priority":9,"right_gravity":true,"ns_id":3,"virt_text":[[" 2026-01-26 14:31:55","OpencodeHint"]],"virt_text_pos":"right_align"}]],"lines":["----","","","[`tests/replay/renderer_spec.lua`](tests/replay/renderer_spec.lua)","","can you use the question tool and ask me a couple of questions","","----","","","** question** ","","**Q1:** Which Lua testing framework do you use or prefer for your Neovim Lua plugins?","**A1:** busted","","**Q2:** How do you usually run your tests in this codebase?","**A2:** run_tests.sh (Recommended)","","**Q3:** multi-line question","The most important question of all:","Which team are you on?","**A3:** Coffee","","**󰻛 Created Snapshot** `be64b620`","","----","","","Thanks for your answers! You've indicated:","","- Preferred testing framework: **busted**","- Typical test running method: **run_tests.sh (Recommended)**","","I have this in mind for any future testing, troubleshooting, or automation tasks you request for this Neovim Lua codebase. If you have any follow-up questions or tasks (such as test writing, modification, running, debugging, or reporting), let me know—I'll tailor my workflow to these preferences for maximal compatibility and consistency!","",""]} \ No newline at end of file +{ + "actions": [ + { + "args": [ + "be64b6205f0da4c9240df2476dc35495429161b5" + ], + "display_line": 23, + "key": "R", + "range": { + "from": 23, + "to": 23 + }, + "text": "[R]evert file", + "type": "diff_revert_selected_file" + }, + { + "args": [ + "be64b6205f0da4c9240df2476dc35495429161b5" + ], + "display_line": 23, + "key": "A", + "range": { + "from": 23, + "to": 23 + }, + "text": "Revert [A]ll", + "type": "diff_revert_all" + }, + { + "args": [ + "be64b6205f0da4c9240df2476dc35495429161b5" + ], + "display_line": 23, + "key": "D", + "range": { + "from": 23, + "to": 23 + }, + "text": "[D]iff", + "type": "diff_open" + } + ], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_bfab6dbf3001ZOVHTFKR1CMUE5]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2026-01-26 14:30:46", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 2, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 4, + 3, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 5, + 4, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 6, + 5, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 7, + 6, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 8, + 8, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "BUILD", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/gpt-4.1", + "OpencodeHint" + ], + [ + " [msg_bfab6dc80001FueCN7E2691J2R]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 9, + 8, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2026-01-26 14:30:46", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 10, + 10, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 11, + 11, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 12, + 12, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 13, + 13, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 14, + 14, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 15, + 15, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 16, + 16, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 17, + 17, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 18, + 18, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 19, + 19, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 20, + 20, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 21, + 21, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeToolBorder" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -1 + } + ], + [ + 22, + 26, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "BUILD", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/gpt-4.1", + "OpencodeHint" + ], + [ + " [msg_bfab7e7fd0018kA9yLHMkJM3fA]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 23, + 26, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2026-01-26 14:31:55", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ] + ], + "lines": [ + "----", + "", + "", + "[`tests/replay/renderer_spec.lua`](tests/replay/renderer_spec.lua)", + "", + "can you use the question tool and ask me a couple of questions", + "", + "----", + "", + "", + "** question** ", + "", + "**Q1:** Which Lua testing framework do you use or prefer for your Neovim Lua plugins?", + "**A1:** busted", + "", + "**Q2:** How do you usually run your tests in this codebase?", + "**A2:** run_tests.sh (Recommended)", + "", + "**Q3:** multi-line question", + "The most important question of all:", + "Which team are you on?", + "**A3:** Coffee", + "", + "**󰻛 Created Snapshot** `be64b620`", + "", + "----", + "", + "", + "Thanks for your answers! You've indicated:", + "", + "- Preferred testing framework: **busted**", + "- Typical test running method: **run_tests.sh (Recommended)**", + "", + "I have this in mind for any future testing, troubleshooting, or automation tasks you request for this Neovim Lua codebase. If you have any follow-up questions or tasks (such as test writing, modification, running, debugging, or reporting), let me know—I'll tailor my workflow to these preferences for maximal compatibility and consistency!", + "", + "" + ], + "timestamp": 1773947664, + "window": { + "cursor": [ + 35, + 0 + ], + "effective_bottom": 35, + "line_count": 36, + "visible_bottom": 36 + } +} diff --git a/tests/data/multiple-question-ask.expected.json b/tests/data/multiple-question-ask.expected.json index a83dcfc8..a0b9921c 100644 --- a/tests/data/multiple-question-ask.expected.json +++ b/tests/data/multiple-question-ask.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -176,7 +179,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -229,6 +235,9 @@ "SYSTEM", "OpencodeMessageRoleSystem" ], + [ + " " + ], [ "", "OpencodeHint" @@ -595,6 +604,7 @@ 30, 0 ], + "effective_bottom": 30, "line_count": 31, "visible_bottom": 31 } diff --git a/tests/data/part-before-message-delta.expected.json b/tests/data/part-before-message-delta.expected.json index 46611fba..8b47f8fd 100644 --- a/tests/data/part-before-message-delta.expected.json +++ b/tests/data/part-before-message-delta.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -116,7 +119,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4-5", + " " + ], + [ + "anthropic/claude-sonnet-4-5", "OpencodeHint" ], [ @@ -169,6 +175,7 @@ 10, 0 ], + "effective_bottom": 10, "line_count": 11, "visible_bottom": 11 } diff --git a/tests/data/perf.expected.json b/tests/data/perf.expected.json index 1f0c6ac9..5b062622 100644 --- a/tests/data/perf.expected.json +++ b/tests/data/perf.expected.json @@ -1 +1,528 @@ -{"extmarks":[[1,1,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"virt_text_pos":"win_col","priority":10,"ns_id":3,"virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_a17b4dc4c001x19oFZANB8CsEB]","OpencodeHint"]],"virt_text_win_col":-3,"right_gravity":true}],[2,1,0,{"virt_text":[[" 2025-10-24 19:32:00","OpencodeHint"]],"virt_text_hide":false,"priority":9,"ns_id":3,"virt_text_repeat_linebreak":false,"virt_text_pos":"right_align","right_gravity":true}],[3,2,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"virt_text_pos":"win_col","priority":4096,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_win_col":-3,"right_gravity":true}],[4,3,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"virt_text_pos":"win_col","priority":4096,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_win_col":-3,"right_gravity":true}],[5,4,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"virt_text_pos":"win_col","priority":4096,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_win_col":-3,"right_gravity":true}],[6,5,0,{"virt_text_repeat_linebreak":true,"virt_text_hide":false,"virt_text_pos":"win_col","priority":4096,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_win_col":-3,"right_gravity":true}],[7,8,0,{"virt_text_repeat_linebreak":false,"virt_text_hide":false,"virt_text_pos":"win_col","priority":10,"ns_id":3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["BUILD","OpencodeMessageRoleAssistant"],[" gpt-5-mini","OpencodeHint"],[" [msg_a17b4e166001vCnLczdZXvqLL6]","OpencodeHint"]],"virt_text_win_col":-3,"right_gravity":true}],[8,8,0,{"virt_text":[[" 2025-10-24 19:32:01","OpencodeHint"]],"virt_text_hide":false,"priority":9,"ns_id":3,"virt_text_repeat_linebreak":false,"virt_text_pos":"right_align","right_gravity":true}]],"lines":["----","","","I just want to test the markdown rendering, please write as long session with codeblocksto","","[`lua/opencode/ui/output_window.lua`](lua/opencode/ui/output_window.lua)","","----","","","Here's a long markdown-rich session with many fenced code blocks to help test rendering. I include the file you provided plus a variety of smaller snippets in different languages and formats.","","**File Contents**","-  `lua/opencode/ui/output_window.lua:1`","","```lua","--  lua/opencode/ui/output_window.lua","local state = require('opencode.state')","local config = require('opencode.config')","","local M = {}","M.namespace = vim.api.nvim_create_namespace('opencode_output')","","function M.create_buf()"," local output_buf = vim.api.nvim_create_buf(false, true)"," vim.api.nvim_set_option_value('filetype', 'opencode_output', { buf = output_buf })"," return output_buf","end","","function M._build_output_win_config()"," return {"," relative = 'editor',"," width = config.ui.window_width or 80,"," row = 2,"," col = 2,"," style = 'minimal',"," border = 'rounded',"," zindex = 40,"," }","end","","function M.mounted(windows)"," windows = windows or state.windows"," if"," not state.windows"," or not state.windows.output_buf"," or not state.windows.output_win"," or not vim.api.nvim_win_is_valid(windows.output_win)"," then"," return false"," end",""," return true","end","","function M.setup(windows)"," vim.api.nvim_set_option_value('winhighlight', config.ui.window_highlight, { win = windows.output_win })"," vim.api.nvim_set_option_value('wrap', true, { win = windows.output_win })"," vim.api.nvim_set_option_value('number', false, { win = windows.output_win })"," vim.api.nvim_set_option_value('relativenumber', false, { win = windows.output_win })"," vim.api.nvim_set_option_value('modifiable', false, { buf = windows.output_buf })"," vim.api.nvim_set_option_value('buftype', 'nofile', { buf = windows.output_buf })"," vim.api.nvim_set_option_value('swapfile', false, { buf = windows.output_buf })"," vim.api.nvim_set_option_value('winfixbuf', true, { win = windows.output_win })"," vim.api.nvim_set_option_value('winfixheight', true, { win = windows.output_win })"," vim.api.nvim_set_option_value('winfixwidth', true, { win = windows.output_win })"," vim.api.nvim_set_option_value('signcolumn', 'yes', { scope = 'local', win = windows.output_win })"," vim.api.nvim_set_option_value('list', false, { scope = 'local', win = windows.output_win })",""," M.update_dimensions(windows)"," M.setup_keymaps(windows)","end","","function M.update_dimensions(windows)"," local total_width = vim.api.nvim_get_option_value('columns', {})"," local width = math.floor(total_width * config.ui.window_width)",""," vim.api.nvim_win_set_config(windows.output_win, { width = width })","end","","function M.get_buf_line_count()"," if not M.mounted() then"," return 0"," end",""," return vim.api.nvim_buf_line_count(state.windows.output_buf)","end","","---Set the output buffer contents","---@param lines string[] The lines to set","---@param start_line? integer The starting line to set, defaults to 0","---@param end_line? integer The last line to set, defaults to -1","function M.set_lines(lines, start_line, end_line)"," if not M.mounted() then"," return"," end",""," start_line = start_line or 0"," end_line = end_line or -1",""," local windows = state.windows"," if not windows or not windows.output_buf then"," return"," end",""," vim.api.nvim_set_option_value('modifiable', true, { buf = windows.output_buf })"," vim.api.nvim_buf_set_lines(windows.output_buf, start_line, end_line, false, lines)"," vim.api.nvim_set_option_value('modifiable', false, { buf = windows.output_buf })","end","","---Clear output buf extmarks","---@param start_line? integer Line to start clearing, defaults 0","---@param end_line? integer Line to to clear until, defaults to -1","function M.clear_extmarks(start_line, end_line)"," if not M.mounted() or not state.windows.output_buf then"," return"," end",""," start_line = start_line or 0"," end_line = end_line or -1",""," vim.api.nvim_buf_clear_namespace(state.windows.output_buf, M.namespace, start_line, end_line)","end","","---Apply extmarks to the output buffer","---@param extmarks table Extmarks indexed by line","---@param line_offset? integer Line offset to apply to extmarks, defaults to 0","function M.set_extmarks(extmarks, line_offset)"," if not M.mounted() or not extmarks or type(extmarks) ~= 'table' then"," return"," end",""," line_offset = line_offset or 0",""," local output_buf = state.windows.output_buf",""," for line_idx, marks in pairs(extmarks) do"," for _, mark in ipairs(marks) do"," local actual_mark = type(mark) == 'function' and mark() or mark"," local target_line = line_offset + line_idx"," if actual_mark.end_row then"," actual_mark.end_row = actual_mark.end_row + line_offset"," end"," local start_col = actual_mark.start_col"," if actual_mark.start_col then"," actual_mark.start_col = nil"," end"," pcall(vim.api.nvim_buf_set_extmark, output_buf, M.namespace, target_line, start_col or 0, actual_mark)"," end"," end","end","","function M.focus_output(should_stop_insert)"," if should_stop_insert then"," vim.cmd('stopinsert')"," end"," vim.api.nvim_set_current_win(state.windows.output_win)","end","","function M.close()"," if M.mounted() then"," return"," end"," pcall(vim.api.nvim_win_close, state.windows.output_win, true)"," pcall(vim.api.nvim_buf_delete, state.windows.output_buf, { force = true })","end","","function M.setup_keymaps(windows)"," local keymap = require('opencode.keymap')"," keymap.setup_window_keymaps(config.keymap.output_window, windows.output_buf)","end","","function M.setup_autocmds(windows, group)"," vim.api.nvim_create_autocmd('WinEnter', {"," group = group,"," buffer = windows.output_buf,"," callback = function()"," vim.cmd('stopinsert')"," state.last_focused_opencode_window = 'output'"," require('opencode.ui.input_window').refresh_placeholder(state.windows)"," end,"," })",""," vim.api.nvim_create_autocmd('BufEnter', {"," group = group,"," buffer = windows.output_buf,"," callback = function()"," vim.cmd('stopinsert')"," state.last_focused_opencode_window = 'output'"," require('opencode.ui.input_window').refresh_placeholder(state.windows)"," end,"," })",""," state.subscribe('current_permission', function()"," require('opencode.keymap').toggle_permission_keymap(windows.output_buf)"," end)","end","","function M.clear()"," M.set_lines({})"," M.clear_extmarks()","end","","return M","```","","**Shell / Commands**","","```bash","# show project root and run tests","pwd","ls -la","./run_tests.sh","```","","**Short Lua examples**","","```lua","-- Print buffer line count if mounted","local out = require('opencode.ui.output_window')","if out.mounted() then"," print('Lines:', out.get_buf_line_count())","else"," print('Output window not mounted.')","end","```","","**JSON sample**","","```json","{"," \"name\": \"opencode.nvim\","," \"version\": \"0.0.0\","," \"tests\": {"," \"unit\": 128,"," \"manual\": 12"," }","}","```","","**YAML sample**","","```yaml","ui:"," window_width: 0.5"," window_highlight: \"Normal:NormalFloat\"","keymap:"," output_window:"," close: \"\""," focus: \"\"","```","","**Unified Diff example**","","```diff","***  before/lua/opencode/ui/output_window.lua","@@","- vim.api.nvim_set_option_value('winhighlight', config.ui.window_highlight, { win = windows.output_win })","+ vim.api.nvim_set_option_value('winhighlight', config.ui.window_highlight or '', { win = windows.output_win })","```","","**Python snippet**","","```python","# small helper to format lines","def format_lines(lines):"," return [line.rstrip() for line in lines if line is not None]","```","","**SQL example**","","```sql","-- List recent sessions","SELECT id, created_at, user_id","FROM sessions","WHERE created_at > now() - interval '7 days'","ORDER BY created_at DESC","LIMIT 10;","```","","**HTML fragment**","","```html","",""," Render Test"," ","
-- sample Lua inside HTML
"," ","","```","","**Indented (classic) code block**",""," This is an indented code block."," It should render as preformatted text without language highlighting.","","**Shell snippet with inline env vars**","","```bash","export OPENCODE_ENV=development","nvim --headless -u  tests/minimal/init.lua -c \"lua require('plenary.test_harness').test_directory('./tests/unit', {minimal_init = ' ./tests/minimal/init.lua'})\"","```","","**Mixed inline code examples**","- Use backticks for commands:  `./run_tests.sh`","- File path with start line: `lua/opencode/ui/output_window.lua:1`","- API call: `vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)`","","**Small checklist**","- [x] Lua file included (`lua/opencode/ui/output_window.lua:1`)","- [x] Multiple fenced code blocks","- [x] Several languages: Lua, Bash, JSON, YAML, Python, SQL, HTML, Diff","","If you want more variations (many short blocks, nested lists, tables, or extremely long blocks), tell me which formats or languages to expand and I’ll produce them.","",""],"actions":[],"timestamp":1773947644,"window":{"cursor":[316,0],"visible_bottom":317,"line_count":317}} \ No newline at end of file +{ + "actions": [], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_a17b4dc4c001x19oFZANB8CsEB]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-24 19:32:00", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 2, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 4, + 3, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 5, + 4, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 6, + 5, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 7, + 8, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "BUILD", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/gpt-5-mini", + "OpencodeHint" + ], + [ + " [msg_a17b4e166001vCnLczdZXvqLL6]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 8, + 8, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-24 19:32:01", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ] + ], + "lines": [ + "----", + "", + "", + "I just want to test the markdown rendering, please write as long session with codeblocksto", + "", + "[`lua/opencode/ui/output_window.lua`](lua/opencode/ui/output_window.lua)", + "", + "----", + "", + "", + "Here's a long markdown-rich session with many fenced code blocks to help test rendering. I include the file you provided plus a variety of smaller snippets in different languages and formats.", + "", + "**File Contents**", + "-  `lua/opencode/ui/output_window.lua:1`", + "", + "```lua", + "--  lua/opencode/ui/output_window.lua", + "local state = require('opencode.state')", + "local config = require('opencode.config')", + "", + "local M = {}", + "M.namespace = vim.api.nvim_create_namespace('opencode_output')", + "", + "function M.create_buf()", + " local output_buf = vim.api.nvim_create_buf(false, true)", + " vim.api.nvim_set_option_value('filetype', 'opencode_output', { buf = output_buf })", + " return output_buf", + "end", + "", + "function M._build_output_win_config()", + " return {", + " relative = 'editor',", + " width = config.ui.window_width or 80,", + " row = 2,", + " col = 2,", + " style = 'minimal',", + " border = 'rounded',", + " zindex = 40,", + " }", + "end", + "", + "function M.mounted(windows)", + " windows = windows or state.windows", + " if", + " not state.windows", + " or not state.windows.output_buf", + " or not state.windows.output_win", + " or not vim.api.nvim_win_is_valid(windows.output_win)", + " then", + " return false", + " end", + "", + " return true", + "end", + "", + "function M.setup(windows)", + " vim.api.nvim_set_option_value('winhighlight', config.ui.window_highlight, { win = windows.output_win })", + " vim.api.nvim_set_option_value('wrap', true, { win = windows.output_win })", + " vim.api.nvim_set_option_value('number', false, { win = windows.output_win })", + " vim.api.nvim_set_option_value('relativenumber', false, { win = windows.output_win })", + " vim.api.nvim_set_option_value('modifiable', false, { buf = windows.output_buf })", + " vim.api.nvim_set_option_value('buftype', 'nofile', { buf = windows.output_buf })", + " vim.api.nvim_set_option_value('swapfile', false, { buf = windows.output_buf })", + " vim.api.nvim_set_option_value('winfixbuf', true, { win = windows.output_win })", + " vim.api.nvim_set_option_value('winfixheight', true, { win = windows.output_win })", + " vim.api.nvim_set_option_value('winfixwidth', true, { win = windows.output_win })", + " vim.api.nvim_set_option_value('signcolumn', 'yes', { scope = 'local', win = windows.output_win })", + " vim.api.nvim_set_option_value('list', false, { scope = 'local', win = windows.output_win })", + "", + " M.update_dimensions(windows)", + " M.setup_keymaps(windows)", + "end", + "", + "function M.update_dimensions(windows)", + " local total_width = vim.api.nvim_get_option_value('columns', {})", + " local width = math.floor(total_width * config.ui.window_width)", + "", + " vim.api.nvim_win_set_config(windows.output_win, { width = width })", + "end", + "", + "function M.get_buf_line_count()", + " if not M.mounted() then", + " return 0", + " end", + "", + " return vim.api.nvim_buf_line_count(state.windows.output_buf)", + "end", + "", + "---Set the output buffer contents", + "---@param lines string[] The lines to set", + "---@param start_line? integer The starting line to set, defaults to 0", + "---@param end_line? integer The last line to set, defaults to -1", + "function M.set_lines(lines, start_line, end_line)", + " if not M.mounted() then", + " return", + " end", + "", + " start_line = start_line or 0", + " end_line = end_line or -1", + "", + " local windows = state.windows", + " if not windows or not windows.output_buf then", + " return", + " end", + "", + " vim.api.nvim_set_option_value('modifiable', true, { buf = windows.output_buf })", + " vim.api.nvim_buf_set_lines(windows.output_buf, start_line, end_line, false, lines)", + " vim.api.nvim_set_option_value('modifiable', false, { buf = windows.output_buf })", + "end", + "", + "---Clear output buf extmarks", + "---@param start_line? integer Line to start clearing, defaults 0", + "---@param end_line? integer Line to to clear until, defaults to -1", + "function M.clear_extmarks(start_line, end_line)", + " if not M.mounted() or not state.windows.output_buf then", + " return", + " end", + "", + " start_line = start_line or 0", + " end_line = end_line or -1", + "", + " vim.api.nvim_buf_clear_namespace(state.windows.output_buf, M.namespace, start_line, end_line)", + "end", + "", + "---Apply extmarks to the output buffer", + "---@param extmarks table Extmarks indexed by line", + "---@param line_offset? integer Line offset to apply to extmarks, defaults to 0", + "function M.set_extmarks(extmarks, line_offset)", + " if not M.mounted() or not extmarks or type(extmarks) ~= 'table' then", + " return", + " end", + "", + " line_offset = line_offset or 0", + "", + " local output_buf = state.windows.output_buf", + "", + " for line_idx, marks in pairs(extmarks) do", + " for _, mark in ipairs(marks) do", + " local actual_mark = type(mark) == 'function' and mark() or mark", + " local target_line = line_offset + line_idx", + " if actual_mark.end_row then", + " actual_mark.end_row = actual_mark.end_row + line_offset", + " end", + " local start_col = actual_mark.start_col", + " if actual_mark.start_col then", + " actual_mark.start_col = nil", + " end", + " pcall(vim.api.nvim_buf_set_extmark, output_buf, M.namespace, target_line, start_col or 0, actual_mark)", + " end", + " end", + "end", + "", + "function M.focus_output(should_stop_insert)", + " if should_stop_insert then", + " vim.cmd('stopinsert')", + " end", + " vim.api.nvim_set_current_win(state.windows.output_win)", + "end", + "", + "function M.close()", + " if M.mounted() then", + " return", + " end", + " pcall(vim.api.nvim_win_close, state.windows.output_win, true)", + " pcall(vim.api.nvim_buf_delete, state.windows.output_buf, { force = true })", + "end", + "", + "function M.setup_keymaps(windows)", + " local keymap = require('opencode.keymap')", + " keymap.setup_window_keymaps(config.keymap.output_window, windows.output_buf)", + "end", + "", + "function M.setup_autocmds(windows, group)", + " vim.api.nvim_create_autocmd('WinEnter', {", + " group = group,", + " buffer = windows.output_buf,", + " callback = function()", + " vim.cmd('stopinsert')", + " state.last_focused_opencode_window = 'output'", + " require('opencode.ui.input_window').refresh_placeholder(state.windows)", + " end,", + " })", + "", + " vim.api.nvim_create_autocmd('BufEnter', {", + " group = group,", + " buffer = windows.output_buf,", + " callback = function()", + " vim.cmd('stopinsert')", + " state.last_focused_opencode_window = 'output'", + " require('opencode.ui.input_window').refresh_placeholder(state.windows)", + " end,", + " })", + "", + " state.subscribe('current_permission', function()", + " require('opencode.keymap').toggle_permission_keymap(windows.output_buf)", + " end)", + "end", + "", + "function M.clear()", + " M.set_lines({})", + " M.clear_extmarks()", + "end", + "", + "return M", + "```", + "", + "**Shell / Commands**", + "", + "```bash", + "# show project root and run tests", + "pwd", + "ls -la", + "./run_tests.sh", + "```", + "", + "**Short Lua examples**", + "", + "```lua", + "-- Print buffer line count if mounted", + "local out = require('opencode.ui.output_window')", + "if out.mounted() then", + " print('Lines:', out.get_buf_line_count())", + "else", + " print('Output window not mounted.')", + "end", + "```", + "", + "**JSON sample**", + "", + "```json", + "{", + " \"name\": \"opencode.nvim\",", + " \"version\": \"0.0.0\",", + " \"tests\": {", + " \"unit\": 128,", + " \"manual\": 12", + " }", + "}", + "```", + "", + "**YAML sample**", + "", + "```yaml", + "ui:", + " window_width: 0.5", + " window_highlight: \"Normal:NormalFloat\"", + "keymap:", + " output_window:", + " close: \"\"", + " focus: \"\"", + "```", + "", + "**Unified Diff example**", + "", + "```diff", + "***  before/lua/opencode/ui/output_window.lua", + "@@", + "- vim.api.nvim_set_option_value('winhighlight', config.ui.window_highlight, { win = windows.output_win })", + "+ vim.api.nvim_set_option_value('winhighlight', config.ui.window_highlight or '', { win = windows.output_win })", + "```", + "", + "**Python snippet**", + "", + "```python", + "# small helper to format lines", + "def format_lines(lines):", + " return [line.rstrip() for line in lines if line is not None]", + "```", + "", + "**SQL example**", + "", + "```sql", + "-- List recent sessions", + "SELECT id, created_at, user_id", + "FROM sessions", + "WHERE created_at > now() - interval '7 days'", + "ORDER BY created_at DESC", + "LIMIT 10;", + "```", + "", + "**HTML fragment**", + "", + "```html", + "", + "", + " Render Test", + " ", + "
-- sample Lua inside HTML
", + " ", + "", + "```", + "", + "**Indented (classic) code block**", + "", + " This is an indented code block.", + " It should render as preformatted text without language highlighting.", + "", + "**Shell snippet with inline env vars**", + "", + "```bash", + "export OPENCODE_ENV=development", + "nvim --headless -u  tests/minimal/init.lua -c \"lua require('plenary.test_harness').test_directory('./tests/unit', {minimal_init = ' ./tests/minimal/init.lua'})\"", + "```", + "", + "**Mixed inline code examples**", + "- Use backticks for commands:  `./run_tests.sh`", + "- File path with start line: `lua/opencode/ui/output_window.lua:1`", + "- API call: `vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)`", + "", + "**Small checklist**", + "- [x] Lua file included (`lua/opencode/ui/output_window.lua:1`)", + "- [x] Multiple fenced code blocks", + "- [x] Several languages: Lua, Bash, JSON, YAML, Python, SQL, HTML, Diff", + "", + "If you want more variations (many short blocks, nested lists, tables, or extremely long blocks), tell me which formats or languages to expand and I’ll produce them.", + "", + "" + ], + "timestamp": 1773947644, + "window": { + "cursor": [ + 316, + 0 + ], + "effective_bottom": 316, + "line_count": 317, + "visible_bottom": 317 + } +} diff --git a/tests/data/permission-ask-new-approve.expected.json b/tests/data/permission-ask-new-approve.expected.json index a6b50192..81bf4a2b 100644 --- a/tests/data/permission-ask-new-approve.expected.json +++ b/tests/data/permission-ask-new-approve.expected.json @@ -61,6 +61,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -256,7 +259,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -770,7 +776,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ diff --git a/tests/data/permission-ask-new-deny.expected.json b/tests/data/permission-ask-new-deny.expected.json index 48634d79..bd6fdd9f 100644 --- a/tests/data/permission-ask-new-deny.expected.json +++ b/tests/data/permission-ask-new-deny.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -156,7 +159,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -378,6 +384,7 @@ 19, 0 ], + "effective_bottom": 19, "line_count": 20, "visible_bottom": 20 } diff --git a/tests/data/permission-ask-new.expected.json b/tests/data/permission-ask-new.expected.json index a8ed1f69..296fecb6 100644 --- a/tests/data/permission-ask-new.expected.json +++ b/tests/data/permission-ask-new.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -216,7 +219,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -389,6 +395,9 @@ "SYSTEM", "OpencodeMessageRoleSystem" ], + [ + " " + ], [ "", "OpencodeHint" diff --git a/tests/data/permission-prompt.expected.json b/tests/data/permission-prompt.expected.json index 680d46f6..0f0764ca 100644 --- a/tests/data/permission-prompt.expected.json +++ b/tests/data/permission-prompt.expected.json @@ -22,7 +22,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -195,6 +198,9 @@ "SYSTEM", "OpencodeMessageRoleSystem" ], + [ + " " + ], [ "", "OpencodeHint" @@ -571,6 +577,7 @@ 30, 0 ], + "effective_bottom": 30, "line_count": 31, "visible_bottom": 31 } diff --git a/tests/data/permission.expected.json b/tests/data/permission.expected.json index 004fa309..03f08feb 100644 --- a/tests/data/permission.expected.json +++ b/tests/data/permission.expected.json @@ -61,6 +61,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -156,7 +159,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -310,7 +316,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -372,6 +381,7 @@ 19, 0 ], + "effective_bottom": 19, "line_count": 20, "visible_bottom": 20 } diff --git a/tests/data/planning.expected.json b/tests/data/planning.expected.json index 67ffe777..960ed8c6 100644 --- a/tests/data/planning.expected.json +++ b/tests/data/planning.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -156,7 +159,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4", + " " + ], + [ + "github-copilot/claude-sonnet-4", "OpencodeHint" ], [ @@ -310,7 +316,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4", + " " + ], + [ + "github-copilot/claude-sonnet-4", "OpencodeHint" ], [ @@ -364,7 +373,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4", + " " + ], + [ + "github-copilot/claude-sonnet-4", "OpencodeHint" ], [ @@ -518,7 +530,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4", + " " + ], + [ + "github-copilot/claude-sonnet-4", "OpencodeHint" ], [ @@ -604,6 +619,7 @@ 43, 0 ], + "effective_bottom": 43, "line_count": 44, "visible_bottom": 44 } diff --git a/tests/data/provider-overloaded-status.expected.json b/tests/data/provider-overloaded-status.expected.json index 46611fba..8b47f8fd 100644 --- a/tests/data/provider-overloaded-status.expected.json +++ b/tests/data/provider-overloaded-status.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -116,7 +119,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4-5", + " " + ], + [ + "anthropic/claude-sonnet-4-5", "OpencodeHint" ], [ @@ -169,6 +175,7 @@ 10, 0 ], + "effective_bottom": 10, "line_count": 11, "visible_bottom": 11 } diff --git a/tests/data/question-ask-other.expected.json b/tests/data/question-ask-other.expected.json index f8fbcce0..7ca2abd4 100644 --- a/tests/data/question-ask-other.expected.json +++ b/tests/data/question-ask-other.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -176,7 +179,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4-5", + " " + ], + [ + "anthropic/claude-sonnet-4-5", "OpencodeHint" ], [ @@ -229,6 +235,9 @@ "SYSTEM", "OpencodeMessageRoleSystem" ], + [ + " " + ], [ "", "OpencodeHint" @@ -586,6 +595,7 @@ 31, 0 ], + "effective_bottom": 31, "line_count": 32, "visible_bottom": 32 } diff --git a/tests/data/question-ask-replied.expected.json b/tests/data/question-ask-replied.expected.json index 0c8d761d..04a0d2d7 100644 --- a/tests/data/question-ask-replied.expected.json +++ b/tests/data/question-ask-replied.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -176,7 +179,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -310,7 +316,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -373,6 +382,7 @@ 20, 0 ], + "effective_bottom": 20, "line_count": 21, "visible_bottom": 21 } diff --git a/tests/data/question-ask.expected.json b/tests/data/question-ask.expected.json index cf2efc95..9d93bc3a 100644 --- a/tests/data/question-ask.expected.json +++ b/tests/data/question-ask.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -176,7 +179,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -229,6 +235,9 @@ "SYSTEM", "OpencodeMessageRoleSystem" ], + [ + " " + ], [ "", "OpencodeHint" @@ -563,6 +572,7 @@ 28, 0 ], + "effective_bottom": 28, "line_count": 29, "visible_bottom": 29 } diff --git a/tests/data/reasoning.expected.json b/tests/data/reasoning.expected.json index a01fbb9e..8216267d 100644 --- a/tests/data/reasoning.expected.json +++ b/tests/data/reasoning.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -116,7 +119,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4", + " " + ], + [ + "github-copilot/claude-sonnet-4", "OpencodeHint" ], [ @@ -421,6 +427,7 @@ 31, 0 ], + "effective_bottom": 31, "line_count": 32, "visible_bottom": 32 } diff --git a/tests/data/redo-all.expected.json b/tests/data/redo-all.expected.json index 0baf057e..b07d8795 100644 --- a/tests/data/redo-all.expected.json +++ b/tests/data/redo-all.expected.json @@ -139,6 +139,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -274,7 +277,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -632,7 +638,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -685,6 +694,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -780,7 +792,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -834,7 +849,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1192,7 +1210,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1245,6 +1266,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -1340,7 +1364,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1394,7 +1421,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1752,7 +1782,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1892,6 +1925,7 @@ 97, 0 ], + "effective_bottom": 97, "line_count": 98, "visible_bottom": 97 } diff --git a/tests/data/redo-once.expected.json b/tests/data/redo-once.expected.json index d889d4e3..aab1051d 100644 --- a/tests/data/redo-once.expected.json +++ b/tests/data/redo-once.expected.json @@ -100,6 +100,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -235,7 +238,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -593,7 +599,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -646,6 +655,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -741,7 +753,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -795,7 +810,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1153,7 +1171,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-5-mini", + " " + ], + [ + "github-copilot/gpt-5-mini", "OpencodeHint" ], [ @@ -1307,6 +1328,7 @@ 71, 0 ], + "effective_bottom": 71, "line_count": 72, "visible_bottom": 71 } diff --git a/tests/data/revert.expected.json b/tests/data/revert.expected.json index 6560d8d6..5d4ef945 100644 --- a/tests/data/revert.expected.json +++ b/tests/data/revert.expected.json @@ -61,6 +61,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -196,7 +199,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -249,6 +255,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -344,7 +353,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -698,7 +710,10 @@ "OpencodeMessageRoleAssistant" ], [ - " gpt-4.1", + " " + ], + [ + "github-copilot/gpt-4.1", "OpencodeHint" ], [ @@ -829,6 +844,7 @@ 68, 0 ], + "effective_bottom": 68, "line_count": 69, "visible_bottom": 68 } diff --git a/tests/data/selection.expected.json b/tests/data/selection.expected.json index b445a9ce..9a15d207 100644 --- a/tests/data/selection.expected.json +++ b/tests/data/selection.expected.json @@ -1 +1,438 @@ -{"timestamp":1773947587,"lines":["----","","","here's some context","","```txt","this is a string","```","","```txt","this is a selection test","```","","[`diff-test.txt`](diff-test.txt)","","----","","","I can see the file  `/Users/cam/tmp/a/diff-test.txt` contains \"this is a string\" on line 1.","","The two selection contexts you provided show:","1. Current content: \"this is a string\"","2. Expected/desired content: \"this is a selection test\"","","Since I'm in read-only mode, I can only observe that there's a difference between what's currently in the file and what one of the selections indicates should be there.","",""],"window":{"visible_bottom":27,"cursor":[26,0],"line_count":27},"actions":[],"extmarks":[[1,1,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_9f5b29fea001z6jYXF7CG9omHa]","OpencodeHint"]],"virt_text_pos":"win_col","right_gravity":true,"priority":10,"virt_text_repeat_linebreak":false}],[2,1,0,{"virt_text_hide":false,"virt_text_repeat_linebreak":false,"virt_text":[[" 2025-10-18 05:02:28","OpencodeHint"]],"virt_text_pos":"right_align","right_gravity":true,"priority":9,"ns_id":3}],[3,2,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[4,3,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[5,4,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[6,5,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[7,6,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[8,7,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[9,8,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[10,8,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[11,9,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[12,10,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[13,11,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[14,12,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[15,12,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[16,13,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[["▌","OpencodeMessageRoleUser"]],"virt_text_pos":"win_col","right_gravity":true,"priority":4096,"virt_text_repeat_linebreak":true}],[17,16,0,{"virt_text_win_col":-3,"virt_text_hide":false,"ns_id":3,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["PLAN","OpencodeMessageRoleAssistant"],[" claude-sonnet-4.5","OpencodeHint"],[" [msg_9f5b2a039001xop8ITmXQq0Gjh]","OpencodeHint"]],"virt_text_pos":"win_col","right_gravity":true,"priority":10,"virt_text_repeat_linebreak":false}],[18,16,0,{"virt_text_hide":false,"virt_text_repeat_linebreak":false,"virt_text":[[" 2025-10-18 05:02:28","OpencodeHint"]],"virt_text_pos":"right_align","right_gravity":true,"priority":9,"ns_id":3}]]} \ No newline at end of file +{ + "actions": [], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_9f5b29fea001z6jYXF7CG9omHa]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-18 05:02:28", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 2, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 4, + 3, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 5, + 4, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 6, + 5, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 7, + 6, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 8, + 7, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 9, + 8, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 10, + 8, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 11, + 9, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 12, + 10, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 13, + 11, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 14, + 12, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 15, + 12, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 16, + 13, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 17, + 16, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "PLAN", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/claude-sonnet-4.5", + "OpencodeHint" + ], + [ + " [msg_9f5b2a039001xop8ITmXQq0Gjh]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 18, + 16, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-18 05:02:28", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ] + ], + "lines": [ + "----", + "", + "", + "here's some context", + "", + "```txt", + "this is a string", + "```", + "", + "```txt", + "this is a selection test", + "```", + "", + "[`diff-test.txt`](diff-test.txt)", + "", + "----", + "", + "", + "I can see the file  `/Users/cam/tmp/a/diff-test.txt` contains \"this is a string\" on line 1.", + "", + "The two selection contexts you provided show:", + "1. Current content: \"this is a string\"", + "2. Expected/desired content: \"this is a selection test\"", + "", + "Since I'm in read-only mode, I can only observe that there's a difference between what's currently in the file and what one of the selections indicates should be there.", + "", + "" + ], + "timestamp": 1773947587, + "window": { + "cursor": [ + 26, + 0 + ], + "effective_bottom": 26, + "line_count": 27, + "visible_bottom": 27 + } +} diff --git a/tests/data/shifting-and-multiple-perms.expected.json b/tests/data/shifting-and-multiple-perms.expected.json index 40a74bea..7d11115f 100644 --- a/tests/data/shifting-and-multiple-perms.expected.json +++ b/tests/data/shifting-and-multiple-perms.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -156,7 +159,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -209,6 +215,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -304,7 +313,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -357,6 +369,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -452,7 +467,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -505,6 +523,9 @@ "SYSTEM", "OpencodeMessageRoleSystem" ], + [ + " " + ], [ "", "OpencodeHint" @@ -1475,6 +1496,7 @@ 152, 0 ], + "effective_bottom": 152, "line_count": 153, "visible_bottom": 153 } diff --git a/tests/data/simple-session.expected.json b/tests/data/simple-session.expected.json index 5eb2ae5d..088404d2 100644 --- a/tests/data/simple-session.expected.json +++ b/tests/data/simple-session.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -196,7 +199,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4", + " " + ], + [ + "github-copilot/claude-sonnet-4", "OpencodeHint" ], [ @@ -253,6 +259,7 @@ 14, 0 ], + "effective_bottom": 14, "line_count": 15, "visible_bottom": 15 } diff --git a/tests/data/tool-invalid.expected.json b/tests/data/tool-invalid.expected.json index c9c7b811..e5a09415 100644 --- a/tests/data/tool-invalid.expected.json +++ b/tests/data/tool-invalid.expected.json @@ -22,7 +22,10 @@ "OpencodeMessageRoleAssistant" ], [ - " claude-sonnet-4.5", + " " + ], + [ + "github-copilot/claude-sonnet-4.5", "OpencodeHint" ], [ @@ -195,6 +198,7 @@ 10, 0 ], + "effective_bottom": 10, "line_count": 11, "visible_bottom": 11 } diff --git a/tests/data/updating-text.expected.json b/tests/data/updating-text.expected.json index 1f01f956..bab3074f 100644 --- a/tests/data/updating-text.expected.json +++ b/tests/data/updating-text.expected.json @@ -1 +1,273 @@ -{"window":{"cursor":[61,0],"visible_bottom":62,"line_count":62},"lines":["----","","","What would a new neovim lua plugin look like?","","[`a-empty.txt`](a-empty.txt)","","----","","","A new Neovim Lua plugin typically follows this structure:","","```","plugin-name/","├── lua/","│ └── plugin-name/","│ ├── init.lua -- Main entry point","│ ├── config.lua -- Configuration handling","│ └── utils.lua -- Utility functions","├── plugin/","│ └── plugin-name.lua -- Plugin registration","└── README.md","```","","**Minimal example:**",""," `plugin/example.lua`:","```lua","if vim.g.loaded_example then"," return","end","vim.g.loaded_example = 1","","vim.api.nvim_create_user_command('Example', function()"," require('example').hello()","end, {})","```",""," `lua/example/init.lua`:","```lua","local M = {}","","M.setup = function(opts)"," opts = opts or {}"," -- Handle configuration","end","","M.hello = function()"," print(\"Hello from my plugin!\")","end","","return M","```","","Key components:","- Use  `vim.api` for Neovim API calls","- Provide a `setup()` function for configuration","- Create user commands with `nvim_create_user_command`","- Use autocommands with `nvim_create_autocmd`","- Follow Lua module patterns with `local M = {}`","",""],"timestamp":1773947559,"extmarks":[[1,1,0,{"virt_text_repeat_linebreak":false,"virt_text_win_col":-3,"priority":10,"virt_text_pos":"win_col","right_gravity":true,"virt_text":[["▌󰭻 ","OpencodeMessageRoleUser"],[" "],["USER","OpencodeMessageRoleUser"],["","OpencodeHint"],[" [msg_9d0297a630014CA5ly3Vvw8Kt5]","OpencodeHint"]],"ns_id":3,"virt_text_hide":false}],[2,1,0,{"virt_text_repeat_linebreak":false,"virt_text":[[" 2025-10-10 22:06:43","OpencodeHint"]],"virt_text_pos":"right_align","right_gravity":true,"ns_id":3,"priority":9,"virt_text_hide":false}],[3,2,0,{"virt_text_repeat_linebreak":true,"virt_text_win_col":-3,"priority":4096,"virt_text_pos":"win_col","right_gravity":true,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false}],[4,3,0,{"virt_text_repeat_linebreak":true,"virt_text_win_col":-3,"priority":4096,"virt_text_pos":"win_col","right_gravity":true,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false}],[5,4,0,{"virt_text_repeat_linebreak":true,"virt_text_win_col":-3,"priority":4096,"virt_text_pos":"win_col","right_gravity":true,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false}],[6,5,0,{"virt_text_repeat_linebreak":true,"virt_text_win_col":-3,"priority":4096,"virt_text_pos":"win_col","right_gravity":true,"virt_text":[["▌","OpencodeMessageRoleUser"]],"ns_id":3,"virt_text_hide":false}],[7,8,0,{"virt_text_repeat_linebreak":false,"virt_text_win_col":-3,"priority":10,"virt_text_pos":"win_col","right_gravity":true,"virt_text":[[" ","OpencodeMessageRoleAssistant"],[" "],["PLAN","OpencodeMessageRoleAssistant"],[" claude-sonnet-4","OpencodeHint"],[" [msg_9d0297ab3001UGZU9fDJM4Y75w]","OpencodeHint"]],"ns_id":3,"virt_text_hide":false}],[8,8,0,{"virt_text_repeat_linebreak":false,"virt_text":[[" 2025-10-10 22:06:43","OpencodeHint"]],"virt_text_pos":"right_align","right_gravity":true,"ns_id":3,"priority":9,"virt_text_hide":false}]],"actions":[]} \ No newline at end of file +{ + "actions": [], + "extmarks": [ + [ + 1, + 1, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + "▌󰭻 ", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "USER", + "OpencodeMessageRoleUser" + ], + [ + " " + ], + [ + "", + "OpencodeHint" + ], + [ + " [msg_9d0297a630014CA5ly3Vvw8Kt5]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 2, + 1, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-10 22:06:43", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ], + [ + 3, + 2, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 4, + 3, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 5, + 4, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 6, + 5, + 0, + { + "ns_id": 3, + "priority": 4096, + "right_gravity": true, + "virt_text": [ + [ + "▌", + "OpencodeMessageRoleUser" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": true, + "virt_text_win_col": -3 + } + ], + [ + 7, + 8, + 0, + { + "ns_id": 3, + "priority": 10, + "right_gravity": true, + "virt_text": [ + [ + " ", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "PLAN", + "OpencodeMessageRoleAssistant" + ], + [ + " " + ], + [ + "github-copilot/claude-sonnet-4", + "OpencodeHint" + ], + [ + " [msg_9d0297ab3001UGZU9fDJM4Y75w]", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "win_col", + "virt_text_repeat_linebreak": false, + "virt_text_win_col": -3 + } + ], + [ + 8, + 8, + 0, + { + "ns_id": 3, + "priority": 9, + "right_gravity": true, + "virt_text": [ + [ + " 2025-10-10 22:06:43", + "OpencodeHint" + ] + ], + "virt_text_hide": false, + "virt_text_pos": "right_align", + "virt_text_repeat_linebreak": false + } + ] + ], + "lines": [ + "----", + "", + "", + "What would a new neovim lua plugin look like?", + "", + "[`a-empty.txt`](a-empty.txt)", + "", + "----", + "", + "", + "A new Neovim Lua plugin typically follows this structure:", + "", + "```", + "plugin-name/", + "├── lua/", + "│ └── plugin-name/", + "│ ├── init.lua -- Main entry point", + "│ ├── config.lua -- Configuration handling", + "│ └── utils.lua -- Utility functions", + "├── plugin/", + "│ └── plugin-name.lua -- Plugin registration", + "└── README.md", + "```", + "", + "**Minimal example:**", + "", + " `plugin/example.lua`:", + "```lua", + "if vim.g.loaded_example then", + " return", + "end", + "vim.g.loaded_example = 1", + "", + "vim.api.nvim_create_user_command('Example', function()", + " require('example').hello()", + "end, {})", + "```", + "", + " `lua/example/init.lua`:", + "```lua", + "local M = {}", + "", + "M.setup = function(opts)", + " opts = opts or {}", + " -- Handle configuration", + "end", + "", + "M.hello = function()", + " print(\"Hello from my plugin!\")", + "end", + "", + "return M", + "```", + "", + "Key components:", + "- Use  `vim.api` for Neovim API calls", + "- Provide a `setup()` function for configuration", + "- Create user commands with `nvim_create_user_command`", + "- Use autocommands with `nvim_create_autocmd`", + "- Follow Lua module patterns with `local M = {}`", + "", + "" + ], + "timestamp": 1773947559, + "window": { + "cursor": [ + 61, + 0 + ], + "effective_bottom": 61, + "line_count": 62, + "visible_bottom": 62 + } +} diff --git a/tests/data/user-message-metadata-update.expected.json b/tests/data/user-message-metadata-update.expected.json index 1c6aad80..53d331dd 100644 --- a/tests/data/user-message-metadata-update.expected.json +++ b/tests/data/user-message-metadata-update.expected.json @@ -21,6 +21,9 @@ "USER", "OpencodeMessageRoleUser" ], + [ + " " + ], [ "", "OpencodeHint" @@ -110,6 +113,7 @@ 5, 0 ], + "effective_bottom": 5, "line_count": 6, "visible_bottom": 6 } diff --git a/tests/helpers.lua b/tests/helpers.lua index bd4ae8dc..7eb181b6 100644 --- a/tests/helpers.lua +++ b/tests/helpers.lua @@ -411,22 +411,6 @@ end local existing_snapshot -local function existing_snapshot_is_minified(filename) - if not filename or vim.fn.filereadable(filename) ~= 1 then - return false - end - - local file = io.open(filename, 'r') - if not file then - return false - end - - local prefix = file:read(2) - file:close() - - return prefix == '{"' -end - local function snapshot_without_window(snapshot) local copy = vim.deepcopy(snapshot) copy.window = nil @@ -465,11 +449,6 @@ function M.encode_snapshot_json(snapshot, existing_file) return content end - if existing_snapshot_is_minified(existing_file) then - existing.window = snapshot.window - return vim.json.encode(existing) - end - if not existing.window then local json = append_window_to_existing_snapshot(content, snapshot.window) if json then @@ -479,10 +458,6 @@ function M.encode_snapshot_json(snapshot, existing_file) end end - if existing_snapshot_is_minified(existing_file) then - return vim.json.encode(snapshot) - end - return M.encode_pretty_json(snapshot) end diff --git a/tests/manual/regenerate_expected.sh b/tests/manual/regenerate_expected.sh index 770936fd..0bb86c3b 100755 --- a/tests/manual/regenerate_expected.sh +++ b/tests/manual/regenerate_expected.sh @@ -10,7 +10,7 @@ PROJECT_ROOT="$SCRIPT_DIR/../.." cd "$PROJECT_ROOT" # Check if specific file was requested -TARGET_FILE="$1" +TARGET_FILE="${1:-}" if [[ -n "$TARGET_FILE" ]]; then # Single file mode @@ -49,7 +49,7 @@ if [[ -n "$TARGET_FILE" ]]; then echo "Processing: $data_file -> $expected_file" nvim --headless -u tests/minimal/init.lua \ -c "lua require('tests.manual.regenerate_expected').run([[$data_file]], [[$expected_file]])" \ - -c "qall!" 2>&1 | grep -v "^$" + -c "qall!" 2>&1 | grep -v "^$" || true echo "Done! Regenerated $expected_file" else @@ -74,11 +74,17 @@ else fi expected_file="${data_file%.json}.expected.json" + + if [[ ! -f "$expected_file" ]]; then + echo "Skipping (no .expected.json): $data_file" + continue + fi + echo "Processing: $data_file -> $expected_file" nvim --headless -u tests/minimal/init.lua \ -c "lua require('tests.manual.regenerate_expected').run([[$data_file]], [[$expected_file]])" \ - -c "qall!" 2>&1 | grep -v "^$" + -c "qall!" 2>&1 | grep -v "^$" || true done echo "" @@ -86,7 +92,7 @@ else expected_count=0 for file in tests/data/*.expected.json; do if [[ -f "$file" ]]; then - ((expected_count++)) + ((expected_count++)) || true fi done echo "Done! Regenerated $expected_count expected files"