Skip to content

Commit 955ca46

Browse files
committed
perf: use promise based waiting for the ensure_server
1 parent 252a220 commit 955ca46

File tree

7 files changed

+48
-44
lines changed

7 files changed

+48
-44
lines changed

lua/opencode/api.lua

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,9 @@ function M.select_history()
107107
end
108108

109109
function M.toggle_pane()
110-
if not state.windows then
111-
core.open({ new_session = false, focus = 'output' })
112-
return
113-
end
114-
115-
ui.toggle_pane()
110+
return core.open({ new_session = false, focus = 'output' }):and_then(function()
111+
ui.toggle_pane()
112+
end)
116113
end
117114

118115
---@param from_snapshot_id? string

lua/opencode/api_client.lua

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ function OpencodeApiClient:_ensure_base_url()
3030
local state = require('opencode.state')
3131

3232
if not state.opencode_server then
33-
state.opencode_server = server_job.ensure_server() --[[@as OpencodeServer]]
33+
-- this is last resort - try to start the server and could be blocking
34+
state.opencode_server = server_job.ensure_server():wait() --[[@as OpencodeServer]]
3435
-- shouldn't normally happen but prevents error in replay tester
3536
if not state.opencode_server then
3637
return false

lua/opencode/core.lua

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,8 @@ function M.open(opts)
6565
state.windows = ui.create_windows()
6666
end
6767

68-
vim.schedule(function()
69-
if not state.opencode_server or not state.opencode_server:is_running() then
70-
state.opencode_server = server_job.ensure_server() --[[@as OpencodeServer]]
71-
end
68+
server_job.ensure_server():and_then(function(server)
69+
state.opencode_server = server
7270

7371
M.ensure_current_mode()
7472

lua/opencode/server_job.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,11 @@ function M.stream_api(url, method, body, on_chunk)
132132
end
133133

134134
function M.ensure_server()
135+
local promise = Promise.new()
135136
if state.opencode_server and state.opencode_server:is_running() then
136-
return state.opencode_server
137+
return promise:resolve(state.opencode_server)
137138
end
138139

139-
local promise = Promise.new()
140140
state.opencode_server = opencode_server.new()
141141

142142
state.opencode_server:spawn({
@@ -151,7 +151,7 @@ function M.ensure_server()
151151
end,
152152
})
153153

154-
return promise:wait()
154+
return promise
155155
end
156156

157157
return M

lua/opencode/ui/footer.lua

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ local function utf8_len(str)
1212
end
1313

1414
local function get_mode_highlight()
15-
local mode = (state.current_mode or ''):lower()
15+
local mode = (state.current_mode or config.default_mode):lower()
1616
local highlights = {
1717
build = 'OpencodeAgentBuild',
1818
plan = 'OpencodeAgentPlan',
@@ -42,17 +42,15 @@ local function build_right_segments()
4242
table.insert(segments, { ' ' })
4343
end
4444

45-
if not state.is_running() and state.current_model then
45+
if not state.is_running() and state.current_model and config.ui.display_model then
4646
table.insert(segments, { state.current_model, 'OpencodeHint' })
4747
table.insert(segments, { ' ' })
4848
end
4949

50-
if state.current_mode then
51-
table.insert(segments, {
52-
string.format(' %s ', state.current_mode:upper()),
53-
get_mode_highlight(),
54-
})
55-
end
50+
table.insert(segments, {
51+
string.format(' %s ', (state.current_mode or config.default_mode):upper()),
52+
get_mode_highlight(),
53+
})
5654

5755
return segments
5856
end

tests/unit/api_spec.lua

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ local ui = require('opencode.ui.ui')
44
local state = require('opencode.state')
55
local stub = require('luassert.stub')
66
local assert = require('luassert')
7+
local Promise = require('opencode.promise')
78

89
describe('opencode.api', function()
910
local created_commands = {}
@@ -17,7 +18,10 @@ describe('opencode.api', function()
1718
opts = opts,
1819
})
1920
end)
20-
stub(core, 'open')
21+
stub(core, 'open').invokes(function()
22+
return Promise.new():resolve('done')
23+
end)
24+
2125
stub(core, 'run')
2226
stub(core, 'cancel')
2327
stub(core, 'send_message')
@@ -118,13 +122,13 @@ describe('opencode.api', function()
118122

119123
-- Test the exported functions
120124
assert.is_function(api.open_input, 'Should export open_input')
121-
api.open_input()
125+
api.open_input():wait()
122126
assert.stub(core.open).was_called()
123127
assert.stub(core.open).was_called_with({ new_session = false, focus = 'input', start_insert = true })
124128

125129
-- Test run function
126130
assert.is_function(api.run, 'Should export run')
127-
api.run('test prompt')
131+
api.run('test prompt'):wait()
128132
assert.stub(core.send_message).was_called()
129133
assert.stub(core.send_message).was_called_with('test prompt', {
130134
new_session = false,
@@ -133,7 +137,7 @@ describe('opencode.api', function()
133137

134138
-- Test run_new_session function
135139
assert.is_function(api.run_new_session, 'Should export run_new_session')
136-
api.run_new_session('test prompt new')
140+
api.run_new_session('test prompt new'):wait()
137141
assert.stub(core.send_message).was_called()
138142
assert.stub(core.send_message).was_called_with('test prompt new', {
139143
new_session = true,
@@ -144,7 +148,7 @@ describe('opencode.api', function()
144148

145149
describe('run command argument parsing', function()
146150
it('parses agent prefix and passes to send_message', function()
147-
api.commands.run.fn({ 'agent=plan', 'analyze', 'this', 'code' })
151+
api.commands.run.fn({ 'agent=plan', 'analyze', 'this', 'code' }):wait()
148152
assert.stub(core.send_message).was_called()
149153
assert.stub(core.send_message).was_called_with('analyze this code', {
150154
new_session = false,
@@ -154,7 +158,7 @@ describe('opencode.api', function()
154158
end)
155159

156160
it('parses model prefix and passes to send_message', function()
157-
api.commands.run.fn({ 'model=openai/gpt-4', 'test', 'prompt' })
161+
api.commands.run.fn({ 'model=openai/gpt-4', 'test', 'prompt' }):wait()
158162
assert.stub(core.send_message).was_called()
159163
assert.stub(core.send_message).was_called_with('test prompt', {
160164
new_session = false,
@@ -164,7 +168,7 @@ describe('opencode.api', function()
164168
end)
165169

166170
it('parses context prefix and passes to send_message', function()
167-
api.commands.run.fn({ 'context=current_file.enabled=false', 'test' })
171+
api.commands.run.fn({ 'context=current_file.enabled=false', 'test' }):wait()
168172
assert.stub(core.send_message).was_called()
169173
assert.stub(core.send_message).was_called_with('test', {
170174
new_session = false,
@@ -174,13 +178,15 @@ describe('opencode.api', function()
174178
end)
175179

176180
it('parses multiple prefixes and passes all to send_message', function()
177-
api.commands.run.fn({
178-
'agent=plan',
179-
'model=openai/gpt-4',
180-
'context=current_file.enabled=false',
181-
'analyze',
182-
'code',
183-
})
181+
api.commands.run
182+
.fn({
183+
'agent=plan',
184+
'model=openai/gpt-4',
185+
'context=current_file.enabled=false',
186+
'analyze',
187+
'code',
188+
})
189+
:wait()
184190
assert.stub(core.send_message).was_called()
185191
assert.stub(core.send_message).was_called_with('analyze code', {
186192
new_session = false,
@@ -192,7 +198,7 @@ describe('opencode.api', function()
192198
end)
193199

194200
it('works with run_new command', function()
195-
api.commands.run_new.fn({ 'agent=plan', 'model=openai/gpt-4', 'new', 'session', 'prompt' })
201+
api.commands.run_new.fn({ 'agent=plan', 'model=openai/gpt-4', 'new', 'session', 'prompt' }):wait()
196202
assert.stub(core.send_message).was_called()
197203
assert.stub(core.send_message).was_called_with('new session prompt', {
198204
new_session = true,
@@ -210,7 +216,7 @@ describe('opencode.api', function()
210216
end)
211217

212218
it('Lua API accepts opts directly without parsing', function()
213-
api.run('test prompt', { agent = 'plan', model = 'openai/gpt-4' })
219+
api.run('test prompt', { agent = 'plan', model = 'openai/gpt-4' }):wait()
214220
assert.stub(core.send_message).was_called()
215221
assert.stub(core.send_message).was_called_with('test prompt', {
216222
new_session = false,
@@ -434,6 +440,12 @@ describe('opencode.api', function()
434440
end)
435441

436442
describe('user command model/agent selection', function()
443+
before_each(function()
444+
stub(api, 'open_input').invokes(function()
445+
return Promise.new():resolve('done')
446+
end)
447+
end)
448+
437449
it('invokes run with correct model and agent', function()
438450
local config_file = require('opencode.config_file')
439451
local original_get_user_commands = config_file.get_user_commands
@@ -466,8 +478,6 @@ describe('opencode.api', function()
466478
end,
467479
}
468480

469-
stub(api, 'open_input')
470-
471481
local slash_commands = api.get_slash_commands()
472482

473483
local test_no_model_cmd = nil
@@ -484,7 +494,7 @@ describe('opencode.api', function()
484494
assert.truthy(test_no_model_cmd, 'Should find /test-no-model command')
485495
assert.truthy(test_with_model_cmd, 'Should find /test-with-model command')
486496

487-
test_no_model_cmd.fn()
497+
test_no_model_cmd.fn():wait()
488498
assert.equal(1, #send_command_calls)
489499
assert.equal('test-session', send_command_calls[1].session_id)
490500
assert.equal('test-no-model', send_command_calls[1].command_data.command)
@@ -494,7 +504,7 @@ describe('opencode.api', function()
494504

495505
send_command_calls = {}
496506

497-
test_with_model_cmd.fn()
507+
test_with_model_cmd.fn():wait()
498508
assert.equal(1, #send_command_calls)
499509
assert.equal('test-session', send_command_calls[1].session_id)
500510
assert.equal('test-with-model', send_command_calls[1].command_data.command)

tests/unit/server_job_spec.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ describe('server_job', function()
9898
return fake
9999
end
100100

101-
local first = server_job.ensure_server()
101+
local first = server_job.ensure_server():wait()
102102
assert.same(fake, first._value or first) -- ensure_server returns resolved promise value
103-
local second = server_job.ensure_server()
103+
local second = server_job.ensure_server():wait()
104104
assert.same(fake, second._value or second)
105105
assert.equal(1, spawn_count)
106106
end)

0 commit comments

Comments
 (0)