Skip to content

Commit 9a67f66

Browse files
committed
WIP
1 parent bc85505 commit 9a67f66

21 files changed

+493
-296
lines changed

lua/opencode/api.lua

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ local icons = require('opencode.ui.icons')
1010
local git_review = require('opencode.git_review')
1111
local history = require('opencode.history')
1212
local config = require('opencode.config')
13+
local Promise = require('opencode.promise')
1314

1415
local M = {}
1516

@@ -49,14 +50,14 @@ function M.paste_image()
4950
core.paste_image_from_clipboard()
5051
end
5152

52-
function M.toggle(new_session)
53+
M.toggle = Promise.async(function(new_session)
54+
local focus = state.last_focused_opencode_window or 'input' ---@cast focus 'input' | 'output'
5355
if state.windows == nil then
54-
local focus = state.last_focused_opencode_window or 'input' ---@cast focus 'input' | 'output'
55-
core.open({ new_session = new_session == true, focus = focus, start_insert = false })
56+
core.open({ new_session = new_session == true, focus = focus, start_insert = false }):await()
5657
else
5758
M.close()
5859
end
59-
end
60+
end)
6061

6162
function M.toggle_focus(new_session)
6263
if not ui.is_opencode_focused() then
@@ -115,7 +116,7 @@ end
115116
---@param from_snapshot_id? string
116117
---@param to_snapshot_id? string|number
117118
function M.diff_open(from_snapshot_id, to_snapshot_id)
118-
core.open({ new_session = false, focus = 'output' }):and_then(function()
119+
core.open_if_closed({ new_session = false, focus = 'output' }):and_then(function()
119120
git_review.review(from_snapshot_id)
120121
end)
121122
end
@@ -333,15 +334,15 @@ function M.debug_session()
333334
debug_helper.debug_session()
334335
end
335336

336-
function M.initialize()
337+
M.initialize = Promise.async(function()
337338
local id = require('opencode.id')
338339

339-
local new_session = core.create_new_session('AGENTS.md Initialization')
340+
local new_session = core.create_new_session('AGENTS.md Initialization'):await()
340341
if not new_session then
341342
vim.notify('Failed to create new session', vim.log.levels.ERROR)
342343
return
343344
end
344-
if not core.initialize_current_model() or not state.current_model then
345+
if not core.initialize_current_model():await() or not state.current_model then
345346
vim.notify('No model selected', vim.log.levels.ERROR)
346347
return
347348
end
@@ -357,7 +358,7 @@ function M.initialize()
357358
modelID = modelId,
358359
messageID = id.ascending('message'),
359360
})
360-
end
361+
end)
361362

362363
function M.agent_plan()
363364
require('opencode.core').switch_to_mode('plan')
@@ -463,8 +464,8 @@ function M.help()
463464
ui.render_lines(msg)
464465
end
465466

466-
function M.mcp()
467-
local mcp = config_file.get_mcp_servers()
467+
M.mcp = Promise.async(function()
468+
local mcp = config_file.get_mcp_servers():await()
468469
if not mcp then
469470
vim.notify('No MCP configuration found. Please check your opencode config file.', vim.log.levels.WARN)
470471
return
@@ -502,7 +503,7 @@ function M.mcp()
502503

503504
table.insert(msg, '')
504505
ui.render_lines(msg)
505-
end
506+
end)
506507

507508
function M.commands_list()
508509
local commands = config_file.get_user_commands()
@@ -530,14 +531,14 @@ function M.commands_list()
530531
ui.render_lines(msg)
531532
end
532533

533-
function M.current_model()
534+
M.current_model = Promise.async(function()
534535
return core.initialize_current_model()
535-
end
536+
end)
536537

537538
--- Runs a user-defined command by name.
538539
--- @param name string The name of the user command to run.
539540
--- @param args? string[] Additional arguments to pass to the command.
540-
function M.run_user_command(name, args)
541+
M.run_user_command = Promise.async(function(name, args)
541542
return M.open_input():and_then(function()
542543
local user_commands = config_file.get_user_commands()
543544
local command_cfg = user_commands and user_commands[name]
@@ -566,7 +567,7 @@ function M.run_user_command(name, args)
566567
end)
567568
end)
568569
end)
569-
end
570+
end)
570571

571572
--- Compacts the current session by removing unnecessary data.
572573
--- @param current_session? Session The session to compact. Defaults to the active session.
@@ -737,9 +738,9 @@ end
737738

738739
---@param current_session? Session
739740
--- @param new_title? string
740-
function M.rename_session(current_session, new_title)
741+
M.rename_session = Promise.async(function(current_session, new_title)
741742
local promise = require('opencode.promise').new()
742-
current_session = current_session or vim.deepcopy(state.active_session) --[[@as Session]]
743+
current_session = current_session or (state.active_session and vim.deepcopy(state.active_session) or nil) --[[@as Session]]
743744
if not current_session then
744745
vim.notify('No active session to rename', vim.log.levels.WARN)
745746
promise:resolve(nil)
@@ -756,7 +757,7 @@ function M.rename_session(current_session, new_title)
756757
:and_then(function()
757758
current_session.title = title
758759
if state.active_session and state.active_session.id == current_session.id then
759-
local session_obj = session.get_by_id(current_session.id)
760+
local session_obj = session.get_by_id(current_session.id):await()
760761
if session_obj then
761762
session_obj.title = title
762763
state.active_session = vim.deepcopy(session_obj)
@@ -781,7 +782,7 @@ function M.rename_session(current_session, new_title)
781782
end)
782783
end)
783784
return promise
784-
end
785+
end)
785786

786787
-- Returns the ID of the next user message after the current undo point
787788
-- This is a port of the opencode tui logic
@@ -906,6 +907,7 @@ function M.toggle_tool_output()
906907
ui.render_output()
907908
end
908909

910+
---@type table<string, OpencodeUICommand>
909911
M.commands = {
910912
open = {
911913
desc = 'Open opencode window (input/output)',
@@ -972,7 +974,7 @@ M.commands = {
972974
vim.notify('Failed to create new session', vim.log.levels.ERROR)
973975
return
974976
end
975-
state.active_session = new_session
977+
state.active_session = new_session:await()
976978
M.open_input()
977979
else
978980
M.open_input_new_session()
@@ -1351,7 +1353,7 @@ function M.setup_legacy_commands()
13511353
end
13521354
end
13531355

1354-
function M.get_slash_commands()
1356+
M.get_slash_commands = Promise.async(function()
13551357
local result = {}
13561358
for slash_cmd, def in pairs(M.slash_commands_map) do
13571359
table.insert(result, {
@@ -1361,7 +1363,7 @@ function M.get_slash_commands()
13611363
})
13621364
end
13631365

1364-
local user_commands = config_file.get_user_commands()
1366+
local user_commands = config_file.get_user_commands():await()
13651367
if user_commands then
13661368
for name, def in pairs(user_commands) do
13671369
table.insert(result, {
@@ -1376,7 +1378,7 @@ function M.get_slash_commands()
13761378
end
13771379

13781380
return result
1379-
end
1381+
end)
13801382

13811383
function M.setup()
13821384
vim.api.nvim_create_user_command('Opencode', M.route_command, {

lua/opencode/config_file.lua

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,64 +1,71 @@
1+
local Promise = require('opencode.promise')
12
local M = {
23
config_promise = nil,
34
project_promise = nil,
45
providers_promise = nil,
56
}
67

78
---@return OpencodeConfigFile|nil
8-
function M.get_opencode_config()
9+
M.get_opencode_config = Promise.async(function()
910
if not M.config_promise then
1011
local state = require('opencode.state')
1112
M.config_promise = state.api_client:get_config()
1213
end
1314
local ok, result = pcall(function()
14-
return M.config_promise:wait()
15+
return M.config_promise:await()
1516
end)
1617

1718
if not ok then
1819
vim.notify('Error fetching Opencode config: ' .. vim.inspect(result), vim.log.levels.ERROR)
1920
return nil
2021
end
2122

22-
return result --[[@as OpencodeConfigFile|nil]]
23-
end
23+
return result
24+
end)
2425

2526
---@return OpencodeProject|nil
26-
function M.get_opencode_project()
27+
M.get_opencode_project = Promise.async(function()
2728
if not M.project_promise then
2829
local state = require('opencode.state')
2930
M.project_promise = state.api_client:get_current_project()
3031
end
3132
local ok, result = pcall(function()
32-
return M.project_promise:wait()
33+
return M.project_promise:await()
3334
end)
3435
if not ok then
3536
vim.notify('Error fetching Opencode project: ' .. vim.inspect(result), vim.log.levels.ERROR)
3637
return nil
3738
end
3839

3940
return result --[[@as OpencodeProject|nil]]
40-
end
41+
end)
42+
43+
---Get the snapshot storage path for the current workspace
44+
---@return string
45+
M.get_workspace_snapshot_path = Promise.async(function()
46+
local project = M.get_opencode_project():await()
47+
if not project then
48+
return ''
49+
end
50+
local home = vim.uv.os_homedir()
51+
return home .. '/.local/share/opencode/snapshot/' .. project.id
52+
end)
4153

42-
---@return OpencodeProvidersResponse|nil
54+
---@return Promise<OpencodeProvidersResponse|nil>
4355
function M.get_opencode_providers()
4456
if not M.providers_promise then
4557
local state = require('opencode.state')
4658
M.providers_promise = state.api_client:list_providers()
4759
end
48-
local ok, result = pcall(function()
49-
return M.providers_promise:wait()
50-
end)
51-
if not ok then
52-
vim.notify('Error fetching Opencode providers: ' .. vim.inspect(result), vim.log.levels.ERROR)
60+
return M.providers_promise:catch(function(err)
61+
vim.notify('Error fetching Opencode providers: ' .. vim.inspect(err), vim.log.levels.ERROR)
5362
return nil
54-
end
55-
56-
return result --[[@as OpencodeProvidersResponse|nil]]
63+
end)
5764
end
5865

59-
function M.get_model_info(provider, model)
60-
local config_file = require('opencode.config_file')
61-
local providers_response = config_file.get_opencode_providers()
66+
M.get_model_info = function(provider, model)
67+
local providers_response = M.get_opencode_providers():peek()
68+
6269
local providers = providers_response and providers_response.providers or {}
6370

6471
local filtered_providers = vim.tbl_filter(function(p)
@@ -72,8 +79,8 @@ function M.get_model_info(provider, model)
7279
return filtered_providers[1] and filtered_providers[1].models and filtered_providers[1].models[model] or nil
7380
end
7481

75-
function M.get_opencode_agents()
76-
local cfg = M.get_opencode_config() --[[@as OpencodeConfigFile]]
82+
M.get_opencode_agents = Promise.async(function()
83+
local cfg = M.get_opencode_config():await()
7784
if not cfg then
7885
return {}
7986
end
@@ -96,10 +103,10 @@ function M.get_opencode_agents()
96103
end
97104
end
98105
return agents
99-
end
106+
end)
100107

101-
function M.get_subagents()
102-
local cfg = M.get_opencode_config()
108+
M.get_subagents = Promise.async(function()
109+
local cfg = M.get_opencode_config():await()
103110
if not cfg then
104111
return {}
105112
end
@@ -113,17 +120,17 @@ function M.get_subagents()
113120
table.insert(subagents, 1, 'general')
114121

115122
return subagents
116-
end
123+
end)
117124

118-
function M.get_user_commands()
119-
local cfg = M.get_opencode_config() --[[@as OpencodeConfigFile]]
125+
M.get_user_commands = Promise.async(function()
126+
local cfg = M.get_opencode_config():await() --[[@as OpencodeConfigFile]]
120127
return cfg and cfg.command or nil
121-
end
128+
end)
122129

123-
function M.get_mcp_servers()
124-
local cfg = M.get_opencode_config() --[[@as OpencodeConfigFile]]
130+
M.get_mcp_servers = Promise.async(function()
131+
local cfg = M.get_opencode_config():await() --[[@as OpencodeConfigFile]]
125132
return cfg and cfg.mcp or nil
126-
end
133+
end)
127134

128135
---Does this opencode user command take arguments?
129136
---@param command OpencodeCommand

0 commit comments

Comments
 (0)