Skip to content

Commit bc85505

Browse files
committed
feat: ensure we can't stay in a loading state forever
1 parent 2bfcb8f commit bc85505

File tree

2 files changed

+83
-33
lines changed

2 files changed

+83
-33
lines changed

lua/opencode/core.lua

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -69,47 +69,64 @@ function M.open(opts)
6969
state.windows = ui.create_windows()
7070
end
7171

72-
server_job.ensure_server():and_then(function(server)
73-
state.opencode_server = server
72+
if opts.focus == 'input' then
73+
ui.focus_input({ restore_position = are_windows_closed, start_insert = opts.start_insert == true })
74+
elseif opts.focus == 'output' then
75+
ui.focus_output({ restore_position = are_windows_closed })
76+
end
7477

75-
M.ensure_current_mode()
78+
server_job
79+
.ensure_server()
80+
:and_then(function(server)
81+
local ok, err = pcall(function()
82+
state.opencode_server = server
7683

77-
if opts.new_session then
78-
state.active_session = nil
79-
state.last_sent_context = nil
84+
M.ensure_current_mode()
8085

81-
state.current_model = nil
82-
state.current_mode = nil
83-
M.ensure_current_mode()
86+
if opts.new_session then
87+
state.active_session = nil
88+
state.last_sent_context = nil
89+
90+
state.current_model = nil
91+
state.current_mode = nil
92+
M.ensure_current_mode()
8493

85-
state.active_session = M.create_new_session()
86-
else
87-
if not state.active_session then
88-
state.active_session = session.get_last_workspace_session()
89-
if not state.active_session then
9094
state.active_session = M.create_new_session()
95+
else
96+
if not state.active_session then
97+
state.active_session = session.get_last_workspace_session()
98+
if not state.active_session then
99+
state.active_session = M.create_new_session()
100+
end
101+
else
102+
if not state.display_route and are_windows_closed then
103+
-- We're not displaying /help or something like that but we have an active session
104+
-- and the windows were closed so we need to do a full refresh. This mostly happens
105+
-- when opening the window after having closed it since we're not currently clearing
106+
-- the session on api.close()
107+
ui.render_output()
108+
end
109+
end
91110
end
92-
else
93-
if not state.display_route and are_windows_closed then
94-
-- We're not displaying /help or something like that but we have an active session
95-
-- and the windows were closed so we need to do a full refresh. This mostly happens
96-
-- when opening the window after having closed it since we're not currently clearing
97-
-- the session on api.close()
98-
ui.render_output()
99-
end
100-
end
101-
end
102-
promise:resolve()
103-
state.is_opening = false
104111

105-
if opts.focus == 'input' then
106-
ui.focus_input({ restore_position = are_windows_closed, start_insert = opts.start_insert == true })
107-
elseif opts.focus == 'output' then
108-
ui.focus_output({ restore_position = are_windows_closed })
109-
end
112+
state.is_opencode_focused = true
113+
end)
110114

111-
state.is_opencode_focused = true
112-
end)
115+
state.is_opening = false
116+
117+
if not ok then
118+
promise:reject(err)
119+
vim.notify('Error opening panel: ' .. tostring(err), vim.log.levels.ERROR)
120+
return
121+
end
122+
123+
promise:resolve()
124+
end)
125+
:catch(function(err)
126+
state.is_opening = false
127+
promise:reject(err)
128+
vim.notify('Error ensuring server: ' .. tostring(err), vim.log.levels.ERROR)
129+
end)
113130
return promise
114131
end
115132

tests/unit/core_spec.lua

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,39 @@ describe('opencode.core', function()
182182
assert.truthy(state.active_session)
183183
assert.truthy(state.active_session.id)
184184
end)
185+
186+
it('resets is_opening flag when error occurs', function()
187+
state.windows = nil
188+
state.is_opening = false
189+
190+
-- Simply cause an error by stubbing a function that will be called
191+
local original_create_new_session = core.create_new_session
192+
core.create_new_session = function()
193+
error('Test error in create_new_session')
194+
end
195+
196+
local notify_stub = stub(vim, 'notify')
197+
local result_promise = core.open({ new_session = true, focus = 'input' })
198+
199+
-- Wait for async operations to complete
200+
local ok, err = pcall(function()
201+
result_promise:wait()
202+
end)
203+
204+
-- Should fail due to the error
205+
assert.is_false(ok)
206+
assert.truthy(err)
207+
208+
-- is_opening should be reset to false even when error occurs
209+
assert.is_false(state.is_opening)
210+
211+
-- Should have notified about the error
212+
assert.stub(notify_stub).was_called()
213+
214+
-- Restore original function
215+
core.create_new_session = original_create_new_session
216+
notify_stub:revert()
217+
end)
185218
end)
186219

187220
describe('select_session', function()

0 commit comments

Comments
 (0)