Skip to content

Commit 13c15fa

Browse files
author
oujinsai
committed
test(commands): add boundary contracts and guards
Codify command-layer invariants so the refactor is reviewable and regression-safe. The tests lock parser/dispatcher behavior, handler boundaries, keymap routing, and registry contracts while tightening shared types used by those checks.
1 parent 730d7c7 commit 13c15fa

16 files changed

Lines changed: 1795 additions & 278 deletions

lua/opencode/commands/handlers/agent.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
local core = require('opencode.core')
22
local config_file = require('opencode.config_file')
3+
---@type OpencodeState
34
local state = require('opencode.state')
45
local util = require('opencode.util')
56
local Promise = require('opencode.promise')

lua/opencode/commands/handlers/diff.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local core = require('opencode.core')
22
local git_review = require('opencode.git_review')
33
local session_store = require('opencode.session')
4+
---@type OpencodeState
45
local state = require('opencode.state')
56

67
local M = {

lua/opencode/commands/handlers/permission.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
---@type OpencodeState
12
local state = require('opencode.state')
23

34
local M = {

lua/opencode/commands/handlers/session.lua

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ local M = {
33
handlers = {},
44
}
55

6+
local core = require('opencode.core')
7+
---@type OpencodeState
8+
local state = require('opencode.state')
9+
local session_store = require('opencode.session')
10+
local Promise = require('opencode.promise')
11+
local window_actions = require('opencode.commands.handlers.window').actions
12+
613
---@param message string
714
local function invalid_arguments(message)
815
error({
@@ -11,57 +18,37 @@ local function invalid_arguments(message)
1118
}, 0)
1219
end
1320

14-
local function core()
15-
return require('opencode.core')
16-
end
17-
18-
local function state()
19-
return require('opencode.state')
20-
end
21-
22-
local function session_store()
23-
return require('opencode.session')
24-
end
25-
26-
local function Promise()
27-
return require('opencode.promise')
28-
end
29-
30-
local function window_actions()
31-
return require('opencode.commands.handlers.window').actions
32-
end
33-
3421
function M.actions.open_input_new_session()
35-
return core().open({ new_session = true, focus = 'input', start_insert = true })
22+
return core.open({ new_session = true, focus = 'input', start_insert = true })
3623
end
3724

3825
---@param title string
3926
function M.actions.open_input_new_session_with_title(title)
40-
return Promise().async(function(session_title)
41-
local new_session = core().create_new_session(session_title):await()
27+
return Promise.async(function(session_title)
28+
local new_session = core.create_new_session(session_title):await()
4229
if not new_session then
4330
vim.notify('Failed to create new session', vim.log.levels.ERROR)
4431
return
4532
end
4633

47-
state().session.set_active(new_session)
48-
return window_actions().open_input()
34+
state.session.set_active(new_session)
35+
return window_actions.open_input()
4936
end)(title)
5037
end
5138

5239
---@param parent_id? string
5340
function M.actions.select_session(parent_id)
54-
core().select_session(parent_id)
41+
core.select_session(parent_id)
5542
end
5643

5744
function M.actions.select_child_session()
58-
local active = state().active_session
59-
core().select_session(active and active.id or nil)
45+
local active = state.active_session
46+
core.select_session(active and active.id or nil)
6047
end
6148

6249
---@param current_session? Session
6350
function M.actions.compact_session(current_session)
64-
local state_obj = state()
51+
local state_obj = state
6552
current_session = current_session or state_obj.active_session
6653
if not current_session then
6754
vim.notify('No active session to compact', vim.log.levels.WARN)
@@ -98,7 +85,7 @@ function M.actions.compact_session(current_session)
9885
end
9986

10087
function M.actions.share()
101-
local state_obj = state()
88+
local state_obj = state
10289
if not state_obj.active_session then
10390
vim.notify('No active session to share', vim.log.levels.WARN)
10491
return
@@ -124,7 +111,7 @@ function M.actions.share()
124111
end
125112

126113
function M.actions.unshare()
127-
local state_obj = state()
114+
local state_obj = state
128115
if not state_obj.active_session then
129116
vim.notify('No active session to unshare', vim.log.levels.WARN)
130117
return
@@ -145,10 +132,10 @@ function M.actions.unshare()
145132
end
146133

147134
function M.actions.initialize()
148-
return Promise().async(function()
135+
return Promise.async(function()
149136
local id = require('opencode.id')
150-
local state_obj = state()
151-
local core_obj = core()
137+
local state_obj = state
138+
local core_obj = core
152139

153140
local new_session = core_obj.create_new_session('AGENTS.md Initialization'):await()
154141
if not new_session then
@@ -168,7 +155,7 @@ function M.actions.initialize()
168155
end
169156

170157
state_obj.session.set_active(new_session)
171-
window_actions().open_input()
158+
window_actions.open_input()
172159
state_obj.api_client:init_session(state_obj.active_session.id, {
173160
providerID = providerId,
174161
modelID = modelId,
@@ -180,9 +167,9 @@ end
180167
---@param current_session? Session
181168
---@param new_title? string
182169
function M.actions.rename_session(current_session, new_title)
183-
return Promise().async(function(session_obj, requested_title)
184-
local promise = Promise().new()
185-
local state_obj = state()
170+
return Promise.async(function(session_obj, requested_title)
171+
local promise = Promise.new()
172+
local state_obj = state
186173
session_obj = session_obj or (state_obj.active_session and vim.deepcopy(state_obj.active_session) or nil) --[[@as Session]]
187174
if not session_obj then
188175
vim.notify('No active session to rename', vim.log.levels.WARN)
@@ -198,10 +185,10 @@ function M.actions.rename_session(current_session, new_title)
198185
vim.notify('Failed to rename session: ' .. vim.inspect(err), vim.log.levels.ERROR)
199186
end)
200187
end)
201-
:and_then(Promise().async(function()
188+
:and_then(Promise.async(function()
202189
session_obj.title = title
203190
if state_obj.active_session and state_obj.active_session.id == session_obj.id then
204-
local persisted_session = session_store().get_by_id(session_obj.id):await()
191+
local persisted_session = session_store.get_by_id(session_obj.id):await()
205192
if persisted_session then
206193
persisted_session.title = title
207194
state_obj.session.set_active(vim.deepcopy(persisted_session))

lua/opencode/commands/handlers/window.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
local core = require('opencode.core')
2+
---@type OpencodeState
23
local state = require('opencode.state')
34
local ui = require('opencode.ui.ui')
45
local config = require('opencode.config')

lua/opencode/commands/handlers/workflow.lua

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
local core = require('opencode.core')
22
local util = require('opencode.util')
33
local config_file = require('opencode.config_file')
4+
---@type OpencodeState
45
local state = require('opencode.state')
56
local quick_chat = require('opencode.quick_chat')
67
local history = require('opencode.history')

lua/opencode/state/init.lua

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,17 @@ local model = require('opencode.state.model')
66
local renderer = require('opencode.state.renderer')
77
local context = require('opencode.state.context')
88

9-
---@class OpencodeStateModule
9+
---@class OpencodeState : OpencodeStateData
1010
---@field store OpencodeStateStore
1111
---@field session OpencodeSessionStateMutations
1212
---@field jobs OpencodeJobStateMutations
1313
---@field ui OpencodeUiStateMutations
1414
---@field model OpencodeModelStateMutations
1515
---@field renderer OpencodeRendererStateMutations
1616
---@field context OpencodeContextStateMutations
17-
18-
---@alias OpencodeState OpencodeStateModule & OpencodeStateData
17+
---@field active_session Session|nil
18+
---@field current_model string|nil
19+
---@field api_client OpencodeApiClient|nil
1920

2021
---@type OpencodeState
2122
local M = {

0 commit comments

Comments
 (0)