Skip to content

Commit b379c29

Browse files
authored
fix(config_file): respect hidden agents and avoid duplicates (#263)
1 parent 96669d7 commit b379c29

2 files changed

Lines changed: 117 additions & 4 deletions

File tree

lua/opencode/config_file.lua

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ M.get_opencode_agents = Promise.async(function()
9292
local agents = {}
9393
for agent, opts in pairs(cfg.agent or {}) do
9494
-- Only include agents that are enabled and have the right mode
95-
if opts.disable ~= true and (opts.mode == 'primary' or opts.mode == 'all') then
95+
if opts.disable ~= true and opts.hidden ~= true and (opts.mode == 'primary' or opts.mode == 'all') then
9696
table.insert(agents, agent)
9797
end
9898
end
@@ -102,7 +102,7 @@ M.get_opencode_agents = Promise.async(function()
102102
for _, mode in ipairs({ 'plan', 'build' }) do
103103
if not vim.tbl_contains(agents, mode) then
104104
local mode_config = cfg.agent and cfg.agent[mode]
105-
if mode_config == nil or (mode_config.disable ~= true) then
105+
if mode_config == nil or (mode_config.disable ~= true and mode_config.hidden ~= true) then
106106
table.insert(agents, 1, mode)
107107
end
108108
end
@@ -119,11 +119,20 @@ M.get_subagents = Promise.async(function()
119119

120120
local subagents = {}
121121
for agent, opts in pairs(cfg.agent or {}) do
122-
if opts.mode ~= 'primary' or opts.mode == 'all' then
122+
-- Only include agents that are not disabled, not hidden, and not primary-only
123+
if opts.disable ~= true and opts.hidden ~= true and (opts.mode ~= 'primary' or opts.mode == 'all') then
123124
table.insert(subagents, agent)
124125
end
125126
end
126-
table.insert(subagents, 1, 'general')
127+
128+
for _, default_agent in ipairs({ 'general', 'explore' }) do
129+
if not vim.tbl_contains(subagents, default_agent) then
130+
local agent_config = cfg.agent and cfg.agent[default_agent]
131+
if agent_config == nil or (agent_config.disable ~= true and agent_config.hidden ~= true) then
132+
table.insert(subagents, 1, default_agent)
133+
end
134+
end
135+
end
127136

128137
return subagents
129138
end)

tests/unit/config_file_spec.lua

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,110 @@ describe('config_file.setup', function()
8585
end):wait()
8686
end)
8787

88+
it('get_opencode_agents filters out hidden agents', function()
89+
Promise.spawn(function()
90+
state.api_client = {
91+
get_config = function()
92+
return Promise.new():resolve({
93+
agent = {
94+
['custom'] = { mode = 'primary' },
95+
['compaction'] = { mode = 'primary', hidden = true },
96+
['title'] = { mode = 'primary', hidden = true },
97+
},
98+
})
99+
end,
100+
get_current_project = function()
101+
return Promise.new():resolve({ id = 'p1' })
102+
end,
103+
}
104+
local agents = config_file.get_opencode_agents():await()
105+
assert.True(vim.tbl_contains(agents, 'custom'))
106+
assert.False(vim.tbl_contains(agents, 'compaction'))
107+
assert.False(vim.tbl_contains(agents, 'title'))
108+
end):wait()
109+
end)
110+
111+
it('get_subagents filters out hidden agents', function()
112+
Promise.spawn(function()
113+
state.api_client = {
114+
get_config = function()
115+
return Promise.new():resolve({
116+
agent = {
117+
['explore'] = { mode = 'all' },
118+
['compaction'] = { mode = 'all', hidden = true },
119+
['summary'] = { hidden = true },
120+
},
121+
})
122+
end,
123+
get_current_project = function()
124+
return Promise.new():resolve({ id = 'p1' })
125+
end,
126+
}
127+
local agents = config_file.get_subagents():await()
128+
assert.True(vim.tbl_contains(agents, 'general'))
129+
assert.True(vim.tbl_contains(agents, 'explore'))
130+
assert.False(vim.tbl_contains(agents, 'compaction'))
131+
assert.False(vim.tbl_contains(agents, 'summary'))
132+
end):wait()
133+
end)
134+
135+
it('get_subagents does not duplicate built-in agents when configured', function()
136+
Promise.spawn(function()
137+
state.api_client = {
138+
get_config = function()
139+
return Promise.new():resolve({
140+
agent = {
141+
['general'] = { mode = 'subagent', model = 'custom/model' },
142+
['explore'] = { mode = 'all', temperature = 0.5 },
143+
['custom'] = { mode = 'subagent' },
144+
},
145+
})
146+
end,
147+
get_current_project = function()
148+
return Promise.new():resolve({ id = 'p1' })
149+
end,
150+
}
151+
local agents = config_file.get_subagents():await()
152+
153+
-- Count occurrences of each agent
154+
local general_count = 0
155+
local explore_count = 0
156+
for _, agent in ipairs(agents) do
157+
if agent == 'general' then
158+
general_count = general_count + 1
159+
elseif agent == 'explore' then
160+
explore_count = explore_count + 1
161+
end
162+
end
163+
164+
-- Each should appear exactly once
165+
assert.equal(1, general_count, 'general should appear exactly once')
166+
assert.equal(1, explore_count, 'explore should appear exactly once')
167+
assert.True(vim.tbl_contains(agents, 'custom'))
168+
end):wait()
169+
end)
170+
171+
it('get_subagents respects disabled built-in agents', function()
172+
Promise.spawn(function()
173+
state.api_client = {
174+
get_config = function()
175+
return Promise.new():resolve({
176+
agent = {
177+
['general'] = { disable = true },
178+
['explore'] = { hidden = true },
179+
},
180+
})
181+
end,
182+
get_current_project = function()
183+
return Promise.new():resolve({ id = 'p1' })
184+
end,
185+
}
186+
local agents = config_file.get_subagents():await()
187+
assert.False(vim.tbl_contains(agents, 'general'))
188+
assert.False(vim.tbl_contains(agents, 'explore'))
189+
end):wait()
190+
end)
191+
88192
it('get_opencode_project returns project', function()
89193
Promise.spawn(function()
90194
local project = { id = 'p1', name = 'X' }

0 commit comments

Comments
 (0)