From 44097cdb374b37a6a71e6638cfc468886f6b12aa Mon Sep 17 00:00:00 2001 From: phanium <91544758+phanen@users.noreply.github.com> Date: Sat, 4 Jul 2026 00:01:26 +0800 Subject: [PATCH] feat(session_picker): to toggle project/global session --- lua/opencode/config.lua | 1 + lua/opencode/services/session_runtime.lua | 31 ++++++++++++++++------- lua/opencode/types.lua | 1 + lua/opencode/ui/session_picker.lua | 13 ++++++++++ 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/lua/opencode/config.lua b/lua/opencode/config.lua index cc1b4b46..f7b181c2 100644 --- a/lua/opencode/config.lua +++ b/lua/opencode/config.lua @@ -114,6 +114,7 @@ M.defaults = { delete_session = { '', desc = 'Delete selected sessions' }, new_session = { '', desc = 'Create a new session' }, fork_session = { '', desc = 'Fork selected session' }, + toggle_scope = { '', desc = 'Toggle between project/global scope' }, }, timeline_picker = { undo = { '', mode = { 'i', 'n' }, desc = 'Undo to selected message' }, diff --git a/lua/opencode/services/session_runtime.lua b/lua/opencode/services/session_runtime.lua index 77895c2d..8183b94a 100644 --- a/lua/opencode/services/session_runtime.lua +++ b/lua/opencode/services/session_runtime.lua @@ -34,6 +34,26 @@ function M.toggle_session_lock() return M.set_session_lock(not M.is_session_locked()) end +---List sessions in the given scope. Always returns a non-nil array. +---@param scope? 'project' | 'global' defaults to project-scoped +---@return Session[]|GlobalSession[] +function M.list_sessions_by_scope(scope) + if scope == 'global' then + return session.get_all_global_sessions():await() or {} + end + return session.get_all_workspace_sessions():await() or {} +end + +---Keep only pickable sessions: non-empty title and matching parent_id. +---@param sessions Session[]|GlobalSession[] +---@param parent_id? string nil selects mainline (no parent), otherwise children of parent_id +---@return Session[] +function M.filter_pickable_sessions(sessions, parent_id) + return vim.tbl_filter(function(s) + return s ~= nil and s.title ~= '' and s.parentID == parent_id + end, sessions) +end + local function focus_after_session_switch(selected_session) if not state.ui.is_visible() then M.open() @@ -57,17 +77,10 @@ end ---@param parent_id string? ---@param scope? 'project' | 'global' when nil, defaults to project-scoped M.select_session = Promise.async(function(parent_id, scope) - local all_sessions - if scope == 'global' then - all_sessions = session.get_all_global_sessions():await() or {} - else - all_sessions = session.get_all_workspace_sessions():await() or {} - end + local all_sessions = M.list_sessions_by_scope(scope) ---@cast all_sessions Session[] - local filtered_sessions = vim.tbl_filter(function(s) - return s.title ~= '' and s ~= nil and s.parentID == parent_id - end, all_sessions) + local filtered_sessions = M.filter_pickable_sessions(all_sessions, parent_id) if #filtered_sessions == 0 then vim.notify(parent_id and 'No child sessions found' or 'No sessions found', vim.log.levels.INFO) diff --git a/lua/opencode/types.lua b/lua/opencode/types.lua index 7c01caec..a0dc2017 100644 --- a/lua/opencode/types.lua +++ b/lua/opencode/types.lua @@ -170,6 +170,7 @@ ---@field new_session OpencodeKeymapEntry ---@field rename_session OpencodeKeymapEntry ---@field fork_session OpencodeKeymapEntry +---@field toggle_scope OpencodeKeymapEntry ---@class OpencodeTimelinePickerKeymap ---@field undo OpencodeKeymapEntry diff --git a/lua/opencode/ui/session_picker.lua b/lua/opencode/ui/session_picker.lua index d6888759..d884674e 100644 --- a/lua/opencode/ui/session_picker.lua +++ b/lua/opencode/ui/session_picker.lua @@ -351,6 +351,19 @@ function M.pick(sessions, callback, opts) end), reload = true, }, + toggle = { + key = config.keymap.session_picker.toggle_scope, + label = 'toggle scope', + fn = Promise.async(function(_, _) + local session_runtime = require('opencode.services.session_runtime') + local new_scope = (opts.scope == 'global') and 'project' or 'global' + local new_sessions = session_runtime.list_sessions_by_scope(new_scope) + local filtered_sessions = session_runtime.filter_pickable_sessions(new_sessions, nil) + opts.scope = new_scope + return filtered_sessions + end), + reload = true, + }, } -- Preview state for race condition protection