@@ -680,6 +680,63 @@ function M.undo(messageId)
680680 end )
681681end
682682
683+ function M .timeline ()
684+ local user_messages = {}
685+ for _ , msg in ipairs (state .messages or {}) do
686+ local parts = msg .parts or {}
687+ local is_summary = # parts == 1 and parts [1 ].synthetic == true
688+ if msg .info .role == ' user' and not is_summary then
689+ table.insert (user_messages , msg )
690+ end
691+ end
692+ if # user_messages == 0 then
693+ vim .notify (' No user messages in the current session' , vim .log .levels .WARN )
694+ return
695+ end
696+
697+ local timeline_picker = require (' opencode.ui.timeline_picker' )
698+ timeline_picker .pick (user_messages , function (selected_msg )
699+ if selected_msg then
700+ require (' opencode.ui.navigation' ).goto_message_by_id (selected_msg .info .id )
701+ end
702+ end )
703+ end
704+
705+ --- Forks the current session from a specific user message.
706+ --- @param message_id ? string The ID of the user message to fork from. If not provided , uses the last user message.
707+ function M .fork_session (message_id )
708+ if not state .active_session then
709+ vim .notify (' No active session to fork' , vim .log .levels .WARN )
710+ return
711+ end
712+
713+ local message_to_fork = message_id or state .last_user_message and state .last_user_message .info .id
714+ if not message_to_fork then
715+ vim .notify (' No user message to fork from' , vim .log .levels .WARN )
716+ return
717+ end
718+
719+ state .api_client
720+ :fork_session (state .active_session .id , {
721+ messageID = message_to_fork ,
722+ })
723+ :and_then (function (response )
724+ vim .schedule (function ()
725+ if response and response .id then
726+ vim .notify (' Session forked successfully. New session ID: ' .. response .id , vim .log .levels .INFO )
727+ core .switch_session (response .id )
728+ else
729+ vim .notify (' Session forked but no new session ID received' , vim .log .levels .WARN )
730+ end
731+ end )
732+ end )
733+ :catch (function (err )
734+ vim .schedule (function ()
735+ vim .notify (' Failed to fork session: ' .. vim .inspect (err ), vim .log .levels .ERROR )
736+ end )
737+ end )
738+ end
739+
683740-- Returns the ID of the next user message after the current undo point
684741-- This is a port of the opencode tui logic
685742-- https://github.com/sst/opencode/blob/dev/packages/tui/internal/components/chat/messages.go#L1199
@@ -1074,6 +1131,11 @@ M.commands = {
10741131 end
10751132 end ,
10761133 },
1134+
1135+ timeline = {
1136+ desc = ' Open timeline picker to navigate/undo/redo/fork to message' ,
1137+ fn = M .timeline ,
1138+ },
10771139}
10781140
10791141M .slash_commands_map = {
@@ -1089,6 +1151,7 @@ M.slash_commands_map = {
10891151 [' /redo' ] = { fn = M .redo , desc = ' Redo last action' },
10901152 [' /sessions' ] = { fn = M .select_session , desc = ' Select session' },
10911153 [' /share' ] = { fn = M .share , desc = ' Share current session' },
1154+ [' /timeline' ] = { fn = M .timeline , desc = ' Open timeline picker' },
10921155 [' /undo' ] = { fn = M .undo , desc = ' Undo last action' },
10931156 [' /unshare' ] = { fn = M .unshare , desc = ' Unshare current session' },
10941157}
0 commit comments