Skip to content

Commit 0f85a44

Browse files
nkabbarakp-nash-kabbaranickjvandyke
authored
feat(sessions): select session (#139)
closes #123 --------- Co-authored-by: Nash Kabbara <nash.kabbara@kape.com> Co-authored-by: Nick van Dyke <nickjvandyke15@gmail.com>
1 parent 63ef26f commit 0f85a44

6 files changed

Lines changed: 81 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ Command `opencode`:
286286
| ------------------------ | -------------------------------------------------- |
287287
| `session.list` | List sessions |
288288
| `session.new` | Start a new session |
289+
| `session.select` | Select a session |
289290
| `session.share` | Share the current session |
290291
| `session.interrupt` | Interrupt the current session |
291292
| `session.compact` | Compact the current session (reduce context size) |

lua/opencode.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local M = {}
33

44
M.ask = require("opencode.ui.ask").ask
55
M.select = require("opencode.ui.select").select
6+
M.select_session = require("opencode.ui.select_session").select_session
67

78
M.prompt = require("opencode.api.prompt").prompt
89
M.operator = require("opencode.api.operator").operator

lua/opencode/cli/client.lua

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,31 @@ function M.get_commands(port, callback)
226226
M.call(port, "/command", "GET", nil, callback)
227227
end
228228

229+
---@class opencode.cli.client.SessionTime
230+
---@field created integer time in milliseconds
231+
---@field updated integer time in milliseconds
232+
233+
---@class opencode.cli.client.Session
234+
---@field id string
235+
---@field title string
236+
---@field time opencode.cli.client.SessionTime
237+
238+
---Get sessions from `opencode`.
239+
---
240+
---@param port number
241+
---@param callback fun(sessions: opencode.cli.client.Session[])
242+
function M.get_sessions(port, callback)
243+
M.call(port, "/session", "GET", nil, callback)
244+
end
245+
246+
---Select session in `opencode`.
247+
---
248+
---@param port number
249+
---@param session_id number
250+
function M.select_session(port, session_id)
251+
M.call(port, "/tui/select-session", "POST", { sessionID = session_id }, nil)
252+
end
253+
229254
---@class opencode.cli.client.PathResponse
230255
---@field directory string
231256
---@field worktree string

lua/opencode/config.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ local defaults = {
8989
prompts = true,
9090
commands = {
9191
["session.new"] = "Start a new session",
92+
["session.select"] = "Select a session",
9293
["session.share"] = "Share the current session",
9394
["session.interrupt"] = "Interrupt the current session",
9495
["session.compact"] = "Compact the current session (reduce context size)",

lua/opencode/ui/select.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,11 @@ function M.select(opts)
221221
require("opencode").prompt(prompt.prompt, prompt)
222222
end
223223
elseif choice.__type == "command" then
224-
require("opencode").command(choice.name)
224+
if choice.name == "session.select" then
225+
require("opencode").select_session()
226+
else
227+
require("opencode").command(choice.name)
228+
end
225229
elseif choice.__type == "provider" then
226230
if choice.name == "toggle" then
227231
require("opencode").toggle()

lua/opencode/ui/select_session.lua

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
local M = {}
2+
3+
local function ellipsize(s, max_len)
4+
if vim.fn.strdisplaywidth(s) <= max_len then
5+
return s
6+
end
7+
local truncated = vim.fn.strcharpart(s, 0, max_len - 3)
8+
truncated = truncated:gsub("%s+%S*$", "")
9+
10+
return truncated .. "..."
11+
end
12+
13+
function M.select_session()
14+
require("opencode.cli.server")
15+
.get_port()
16+
:next(function(port)
17+
return require("opencode.promise").new(function(resolve)
18+
require("opencode.cli.client").get_sessions(port, function(sessions)
19+
resolve({ sessions = sessions, port = port })
20+
end)
21+
end)
22+
end)
23+
:next(function(session_data)
24+
local sessions = session_data.sessions
25+
table.sort(sessions, function(a, b)
26+
return a.time.updated > b.time.updated
27+
end)
28+
29+
vim.ui.select(sessions, {
30+
prompt = "Select session (recently updated first):",
31+
format_item = function(item)
32+
local title_length = 60
33+
local updated = os.date("%b %d, %Y %H:%M:%S", item.time.updated / 1000)
34+
local title = ellipsize(item.title, title_length)
35+
return ("%s%s%s"):format(title, string.rep(" ", title_length - #title), updated)
36+
end,
37+
}, function(choice)
38+
if choice then
39+
require("opencode.cli.client").select_session(session_data.port, choice.id)
40+
end
41+
end)
42+
end)
43+
:catch(function(err)
44+
vim.notify(err, vim.log.levels.ERROR)
45+
end)
46+
end
47+
48+
return M

0 commit comments

Comments
 (0)