Skip to content

Commit 0771d43

Browse files
committed
fix: core review comments
1 parent bfb1d76 commit 0771d43

File tree

8 files changed

+60
-45
lines changed

8 files changed

+60
-45
lines changed

lua/opencode/api.lua

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ function M.debug_session()
334334
debug_helper.debug_session()
335335
end
336336

337+
---@type fun(): Promise<void>
337338
M.initialize = Promise.async(function()
338339
local id = require('opencode.id')
339340

@@ -368,8 +369,8 @@ function M.agent_build()
368369
require('opencode.core').switch_to_mode('build')
369370
end
370371

371-
function M.select_agent()
372-
local modes = config_file.get_opencode_agents()
372+
M.select_agent = Promise.async(function()
373+
local modes = config_file.get_opencode_agents():await()
373374
vim.ui.select(modes, {
374375
prompt = 'Select mode:',
375376
}, function(selection)
@@ -379,10 +380,10 @@ function M.select_agent()
379380

380381
require('opencode.core').switch_to_mode(selection)
381382
end)
382-
end
383+
end)
383384

384-
function M.switch_mode()
385-
local modes = config_file.get_opencode_agents() --[[@as string[] ]]
385+
M.switch_mode = Promise.async(function()
386+
local modes = config_file.get_opencode_agents():await() --[[@as string[] ]]
386387

387388
local current_index = util.index_of(modes, state.current_mode)
388389

@@ -394,7 +395,7 @@ function M.switch_mode()
394395
local next_index = (current_index % #modes) + 1
395396

396397
require('opencode.core').switch_to_mode(modes[next_index])
397-
end
398+
end)
398399

399400
function M.with_header(lines, show_welcome)
400401
show_welcome = show_welcome or show_welcome
@@ -506,7 +507,7 @@ M.mcp = Promise.async(function()
506507
end)
507508

508509
function M.commands_list()
509-
local commands = config_file.get_user_commands():await()
510+
local commands = config_file.get_user_commands():wait()
510511
if not commands then
511512
vim.notify('No user commands found. Please check your opencode config file.', vim.log.levels.WARN)
512513
return
@@ -566,7 +567,7 @@ M.run_user_command = Promise.async(function(name, args)
566567
require('opencode.history').write('/' .. name .. ' ' .. table.concat(args or {}, ' '))
567568
end)
568569
end)
569-
end)
570+
end) --[[@as Promise<void> ]]
570571
end)
571572

572573
--- Compacts the current session by removing unnecessary data.
@@ -754,7 +755,7 @@ M.rename_session = Promise.async(function(current_session, new_title)
754755
vim.notify('Failed to rename session: ' .. vim.inspect(err), vim.log.levels.ERROR)
755756
end)
756757
end)
757-
:and_then(function()
758+
:and_then(Promise.async(function()
758759
current_session.title = title
759760
if state.active_session and state.active_session.id == current_session.id then
760761
local session_obj = session.get_by_id(current_session.id):await()
@@ -764,7 +765,7 @@ M.rename_session = Promise.async(function(current_session, new_title)
764765
end
765766
end
766767
promise:resolve(current_session)
767-
end)
768+
end))
768769
end
769770

770771
if new_title and new_title ~= '' then
@@ -967,18 +968,20 @@ M.commands = {
967968
fn = function(args)
968969
local subcmd = args[1]
969970
if subcmd == 'new' then
970-
local title = table.concat(vim.list_slice(args, 2), ' ')
971-
if title and title ~= '' then
972-
local new_session = core.create_new_session(title)
973-
if not new_session then
974-
vim.notify('Failed to create new session', vim.log.levels.ERROR)
975-
return
971+
Promise.spawn(function()
972+
local title = table.concat(vim.list_slice(args, 2), ' ')
973+
if title and title ~= '' then
974+
local new_session = core.create_new_session(title):await()
975+
if not new_session then
976+
vim.notify('Failed to create new session', vim.log.levels.ERROR)
977+
return
978+
end
979+
state.active_session = new_session
980+
M.open_input()
981+
else
982+
M.open_input_new_session()
976983
end
977-
state.active_session = new_session:await()
978-
M.open_input()
979-
else
980-
M.open_input_new_session()
981-
end
984+
end)
982985
elseif subcmd == 'select' then
983986
M.select_session()
984987
elseif subcmd == 'child' then
@@ -1230,6 +1233,7 @@ M.slash_commands_map = {
12301233
['/timeline'] = { fn = M.timeline, desc = 'Open timeline picker' },
12311234
['/undo'] = { fn = M.undo, desc = 'Undo last action' },
12321235
['/unshare'] = { fn = M.unshare, desc = 'Unshare current session' },
1236+
['/rename'] = { fn = M.rename_session, desc = 'Rename current session' },
12331237
}
12341238

12351239
M.legacy_command_map = {

lua/opencode/core.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ M.open = Promise.async(function(opts)
124124

125125
if not ok then
126126
vim.notify('Error opening panel: ' .. tostring(err), vim.log.levels.ERROR)
127-
return Promise:new():reject(err)
127+
return Promise.new():reject(err)
128128
end
129-
return Promise:new():resolve('ok')
129+
return Promise.new():resolve('ok')
130130
end)
131131

132132
--- Sends a message to the active session, creating one if necessary.

lua/opencode/promise.lua

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
---@generic T
2+
---@generic U
23
---@class Promise<T>
4+
---@field __index Promise<T>
35
---@field _resolved boolean
46
---@field _value T
57
---@field _error any
68
---@field _then_callbacks fun(value: T)[]
79
---@field _catch_callbacks fun(err: any)[]
810
---@field _coroutines thread[]
11+
---@field new fun(): Promise<T>
12+
---@field resolve fun(self: Promise<T>, value: T): Promise<T>
13+
---@field reject fun(self: Promise<T>, err: any): Promise<T>
14+
---@field and_then fun(self: Promise<T>, callback: fun(value: T): U | Promise<U> | nil): Promise<U>
15+
---@field catch fun(self: Promise<T>, error_callback: fun(err: any): any | Promise<any> | nil): Promise<T>
16+
---@field wait fun(self: Promise<T>, timeout?: integer, interval?: integer): T
17+
---@field peek fun(self: Promise<T>): T
18+
---@field is_resolved fun(self: Promise<T>): boolean
19+
---@field is_rejected fun(self: Promise<T>): boolean
20+
---@field await fun(self: Promise<T>): T
21+
---@field is_promise fun(obj: any): boolean
22+
---@field wrap fun(obj: T | Promise<T>): Promise<T>
23+
---@field spawn fun(fn: fun(): T|nil): Promise<T>
24+
---@field async fun(fn: fun(...): T?): fun(...): Promise<T>
925
local Promise = {}
1026
Promise.__index = Promise
1127

1228
---Resume waiting coroutines with result
29+
---@generic T
1330
---@param coroutines thread[]
1431
---@param value T
1532
---@param err any
@@ -37,7 +54,6 @@ function Promise.new()
3754
return self
3855
end
3956

40-
---@param self Promise<T>
4157
---@param value T
4258
---@return Promise<T>
4359
function Promise:resolve(value)
@@ -59,7 +75,6 @@ function Promise:resolve(value)
5975
return self
6076
end
6177

62-
---@param self Promise<T>
6378
---@param err any
6479
---@return Promise<T>
6580
function Promise:reject(err)
@@ -82,9 +97,8 @@ function Promise:reject(err)
8297
end
8398

8499
---@generic U
85-
---@param self Promise<T>
86-
---@param callback fun(value: T): U | Promise<U>
87-
---@return Promise<U>
100+
---@param callback fun(value: T): U | Promise<U> | nil
101+
---@return Promise<U>?
88102
function Promise:and_then(callback)
89103
if not callback then
90104
error('callback is required')
@@ -127,8 +141,7 @@ function Promise:and_then(callback)
127141
return new_promise
128142
end
129143

130-
---@param self Promise<T>
131-
---@param error_callback fun(err: any): any | Promise<any>
144+
---@param error_callback fun(err: any): any | Promise<any> | nil
132145
---@return Promise<T>
133146
function Promise:catch(error_callback)
134147
local new_promise = Promise.new()
@@ -174,7 +187,6 @@ end
174187
--- This will block the main thread, so use with caution
175188
--- But is useful for synchronous code paths that need the result
176189
---@generic T
177-
---@param self Promise<T>
178190
---@param timeout integer|nil Timeout in milliseconds (default: 5000)
179191
---@param interval integer|nil Interval in milliseconds to check (default: 20)
180192
---@return T
@@ -207,7 +219,6 @@ end
207219
-- Tries to get the value without waiting
208220
-- Useful for status checks where you don't want to block
209221
---@generic T
210-
---@param self Promise<T>
211222
---@return T
212223
function Promise:peek()
213224
return self._value
@@ -225,7 +236,6 @@ end
225236
---This function can only be called from within `coroutine.create` or `Promise.spawn` or `Promise.async`
226237
---This will yield the coroutine until the promise resolves or rejects
227238
---@generic T
228-
---@param self Promise<T>
229239
---@return T
230240
function Promise:await()
231241
-- If already resolved, return immediately
@@ -267,9 +277,10 @@ end
267277

268278
---@param obj T | Promise<T>
269279
---@return Promise<T>
280+
---@return_cast T Promise<T>
270281
function Promise.wrap(obj)
271282
if Promise.is_promise(obj) then
272-
return obj
283+
return obj --[[@as Promise<T>]]
273284
else
274285
return Promise.new():resolve(obj)
275286
end

lua/opencode/session.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ end
2525
---Get the session storage path for the current workspace
2626
---@return string
2727
M.get_workspace_session_path = Promise.async(function(project_id)
28-
project_id = project_id or M.project_id() or ''
28+
project_id = project_id or M.project_id():await() or ''
2929
local home = vim.uv.os_homedir()
3030
return home .. '/.local/share/opencode/storage/session/' .. project_id
3131
end)

lua/opencode/ui/completion/engines/vim_complete.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
local Promise = require('lua.opencode.promise')
1+
local Promise = require('opencode.promise')
22
local M = {}
33

44
local completion_active = false

lua/opencode/ui/debug_helper.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
local M = {}
88

99
local state = require('opencode.state')
10+
local Promise = require('opencode.promise')
1011

1112
function M.open_json_file(data)
1213
local tmpfile = vim.fn.tempname() .. '.json'
@@ -47,10 +48,10 @@ function M.debug_message()
4748
vim.notify('No message found in previous lines', vim.log.levels.WARN)
4849
end
4950

50-
function M.debug_session()
51+
M.debug_session = Promise.async(function()
5152
local session = require('opencode.session')
5253

53-
local session_path = session.get_workspace_session_path()
54+
local session_path = session.get_workspace_session_path():await()
5455
if not state.active_session then
5556
print('No active session')
5657
return
@@ -59,7 +60,7 @@ function M.debug_session()
5960
vim.api.nvim_set_current_win(state.last_code_win_before_opencode --[[@as integer]])
6061
end
6162
vim.cmd('e ' .. session_path .. '/' .. state.active_session.id .. '.json')
62-
end
63+
end)
6364

6465
function M.save_captured_events(filename)
6566
if not state.event_manager then

lua/opencode/ui/session_picker.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ local Promise = require('opencode.promise')
1010
---@return PickerItem
1111
function format_session_item(session, width)
1212
local debug_text = 'ID: ' .. (session.id or 'N/A')
13-
return base_picker.create_picker_item(session.title, session.time.updated, debug_text, width)
13+
local updated_time = (session.time and session.time.updated) or 'N/A'
14+
return base_picker.create_picker_item(session.title, updated_time, debug_text, width)
1415
end
1516

1617
function M.pick(sessions, callback)

lua/opencode/ui/topbar.lua

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ local function update_winbar_highlights(win_id)
6363
table.insert(parts, 'Normal:OpencodeNormal')
6464
end
6565

66-
table.insert(parts, 'WinBar:OpencodeSessionDecription')
66+
table.insert(parts, 'WinBar:OpencodeSessionDescription')
6767
table.insert(parts, 'WinBarNC:OpencodeSessionDescription')
6868

6969
vim.api.nvim_set_option_value('winhighlight', table.concat(parts, ','), { win = win_id })
@@ -76,10 +76,8 @@ local function get_session_desc()
7676

7777
local session_title = LABELS.NEW_SESSION_TITLE
7878

79-
if state.active_session then
80-
if state.active_session and state.active_session ~= '' then
81-
session_title = state.active_session.title
82-
end
79+
if state.active_session and state.active_session.title ~= '' then
80+
session_title = state.active_session.title
8381
end
8482

8583
if not session_title or type(session_title) ~= 'string' then

0 commit comments

Comments
 (0)