Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ Command `opencode`:
| ------------------------ | -------------------------------------------------- |
| `session.list` | List sessions |
| `session.new` | Start a new session |
| `session.select` | Select a session |
| `session.share` | Share the current session |
| `session.interrupt` | Interrupt the current session |
| `session.compact` | Compact the current session (reduce context size) |
Expand Down
1 change: 1 addition & 0 deletions lua/opencode.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local M = {}

M.ask = require("opencode.ui.ask").ask
M.select = require("opencode.ui.select").select
M.select_session = require("opencode.ui.select_session").select_session

M.prompt = require("opencode.api.prompt").prompt
M.operator = require("opencode.api.operator").operator
Expand Down
25 changes: 25 additions & 0 deletions lua/opencode/cli/client.lua
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,31 @@ function M.get_commands(port, callback)
M.call(port, "/command", "GET", nil, callback)
end

---@class opencode.cli.client.SessionTime
---@field created integer time in milliseconds
---@field updated integer time in milliseconds

---@class opencode.cli.client.Session
---@field id string
---@field title string
---@field time opencode.cli.client.SessionTime

---Get sessions from `opencode`.
---
---@param port number
---@param callback fun(sessions: opencode.cli.client.Session[])
function M.get_sessions(port, callback)
M.call(port, "/session", "GET", nil, callback)
end

---Select session in `opencode`.
---
---@param port number
---@param session_id number
function M.select_session(port, session_id)
M.call(port, "/tui/select-session", "POST", { sessionID = session_id }, nil)
end

---@class opencode.cli.client.PathResponse
---@field directory string
---@field worktree string
Expand Down
1 change: 1 addition & 0 deletions lua/opencode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ local defaults = {
prompts = true,
commands = {
["session.new"] = "Start a new session",
["session.select"] = "Select a session",
["session.share"] = "Share the current session",
["session.interrupt"] = "Interrupt the current session",
["session.compact"] = "Compact the current session (reduce context size)",
Expand Down
6 changes: 5 additions & 1 deletion lua/opencode/ui/select.lua
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@ function M.select(opts)
require("opencode").prompt(prompt.prompt, prompt)
end
elseif choice.__type == "command" then
require("opencode").command(choice.name)
if choice.name == "session.select" then
require("opencode").select_session()
else
require("opencode").command(choice.name)
end
elseif choice.__type == "provider" then
if choice.name == "toggle" then
require("opencode").toggle()
Expand Down
48 changes: 48 additions & 0 deletions lua/opencode/ui/select_session.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
local M = {}

local function ellipsize(s, max_len)
if vim.fn.strdisplaywidth(s) <= max_len then
return s
end
local truncated = vim.fn.strcharpart(s, 0, max_len - 3)
truncated = truncated:gsub("%s+%S*$", "")

return truncated .. "..."
end

function M.select_session()
require("opencode.cli.server")
.get_port()
:next(function(port)
return require("opencode.promise").new(function(resolve)
require("opencode.cli.client").get_sessions(port, function(sessions)
resolve({ sessions = sessions, port = port })
end)
end)
end)
:next(function(session_data)
local sessions = session_data.sessions
table.sort(sessions, function(a, b)
return a.time.updated > b.time.updated
end)

vim.ui.select(sessions, {
prompt = "Select session (recently updated first):",
format_item = function(item)
local title_length = 60
local updated = os.date("%b %d, %Y %H:%M:%S", item.time.updated / 1000)
local title = ellipsize(item.title, title_length)
return ("%s%s%s"):format(title, string.rep(" ", title_length - #title), updated)
end,
}, function(choice)
if choice then
require("opencode.cli.client").select_session(session_data.port, choice.id)
end
end)
end)
:catch(function(err)
vim.notify(err, vim.log.levels.ERROR)
end)
end

return M